[英]compare chars for equality without branching
對前一個問題 ,我想優化這個功能:
static
lvh_distance levenshtein_distance( const std::string & s1, const std::string & s2 )
{
const size_t len1 = s1.size(), len2 = s2.size();
std::vector<unsigned int> col( len2+1 ), prevCol( len2+1 );
const size_t prevColSize = prevCol.size();
for( unsigned int i = 0; i < prevColSize; i++ )
prevCol[i] = i;
for( unsigned int i = 0, j; i < len1; ++i )
{
col[0] = i+1;
const char s1i = s1[i];
for( j = 0; j < len2; ++j )
{
const auto minPrev = 1 + std::min( col[j], prevCol[1 + j] );
col[j+1] = std::min( minPrev, prevCol[j] + ( s1i == s2[j] ? 0 : 1 ) );
}
col.swap( prevCol );
}
return prevCol[len2];
}
用戶評論說我可以替換s1i == s2[j] ? 0 : 1
s1i == s2[j] ? 0 : 1
與((s1i - s2[j]) & 0x80) >> 7
以防止條件跳轉。 訣竅是錯誤的,用戶刪除了他的評論,但我想知道是否真的有辦法做到這一點。
假設代碼
s1i == s2[j] ? 0 : 1
確實給你一個分支操作,你真的想避免,你可以簡單地嘗試以下方法:
!(s1i == s2[j])
這應該會產生相同的效果,並可能有助於編譯器刪除分支。 或者,您可以反轉邏輯並寫入
s1i != s2[j]
與這種類型的優化一樣,永遠不能保證這將實際達到您希望的結果。 優化器可以做很多聰明的事情,並且試圖預測它們對你的技巧的反應往往很困難。 因此,即使在最好的情況下,您所能做的就是嘗試不同的解決方案並比較生成的二進制代碼。
為什么不使用以下內容: !(s1i == s2[j])
或(s1i != s2[j])
因為bool到int轉換是隱式的
不是一個實際的答案,而是解決一個難題。
創建一個數組one_or_zero[UCHAR_MAX+1]
用1s填充,並且one_or_zero[0] = 0;
現在你可以做一些像prevCol[j] + one_or_zero[s1i^s2[j]])
這將導致s1i==s2[j]
上的0和1否則被添加到prevCol[j]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.