簡體   English   中英

比較字符是否平等而沒有分支

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM