簡體   English   中英

找出最大和最小兩個數字而不使用If else?

[英]Find out max & min of two number without using If else?

我能夠從這里找出邏輯:

r = y ^ ((x ^ y) & -(x < y)); // min(x, y)
r = x ^ ((x ^ y) & -(x < y)); // max(x, y)

它說這比做更快

r = (x < y) ? x : y

有人可以通過示例來解釋它以了解它。 怎么可能更快?

在沒有特定硬件的情況下討論優化沒有任何意義。 如果不深入了解特定系統的細節,你真的無法分清哪種替代方案最快。 在沒有任何特定硬件的情況下大膽地發表關於第一個替代品最快的聲明,只是預先成熟的優化。

如果給定CPU的性能嚴重依賴於分支預測,那么模糊的xor解決方案可能比比較替代方案更快。 換句話說,如果它執行常規指令(例如算術指令)非常快,但在任何條件語句(例如if )中都會遇到性能瓶頸,其中代碼可能會以多種方式分支。 諸如量指令高速緩沖存儲器等的其他因素也很重要。

但是,許多CPU將更快地執行第二種替代方案,因為它涉及更少的操作。

總而言之,你必須成為給定CPU的專家才能在理論上實際告訴哪些代碼是最快的。 如果您不是這樣的專家,只需對其進行基准測試即可。 或者看一下反匯編的顯着差異。

在您提供的鏈接中,明確說明:

在一些罕見的機器上,分支非常昂貴且沒有條件移動指令,[code]可能比明顯的方法更快,r =(x <y)? x:y

后來,它說:

在某些機器上,將(x <y)評估為0或1需要分支指令,因此可能沒有任何優勢。

簡而言之,位操作解決方案僅在分支執行較差的機器上更快,因為它僅依賴於操作數的數值。 在大多數機器上,分支方法同樣快(有時甚至更快),並且應該首選其可讀性。

? 用條件分支實現的風險(而不是條件分配)。

條件分支對於處理器來說是一個小小的“災難”,因為它無法猜測以后會取出什么指令。 這打破了ALU的管道組織(正在同時進行若干指令以增加吞吐量),並導致管道重新初始化延遲。 為了緩解這一點,處理器采用分支預測,即他們在將要采取的分支上下注,但他們不能一直成功。

總結:條件分支可以slloooowwwwwwww ...

該問題未指定將運行的硬件。 我的答案將解決在x86上運行的情況(例如任何PC)。 讓我們看看每個生成的程序集。

; r = y ^ ((x ^ y) & -(x < y))
xor    edx,edx
cmp    ebx,eax
mov    ecx,eax
setl   dl
xor    ecx,ebx
neg    edx
and    edx,ecx  
xor    eax,edx  

; r = (x < y) ? x : y
cmp    ebx,eax  
cmovl  eax,ebx  

XOR版本必須將寄存器置零,並在其本身需要執行的操作之上移動值,最多可添加8條指令。 但是x86有一個cmov或條件移動指令。 所以?:版本編譯成比較和cmovl ,只有2條指令。 但是,由於不同的指令可能具有不同的延遲和不同的依賴鏈,因此不必使?:版本快4倍。 但你當然可以看到如何?:很可能比XOR版本更快。

值得注意的是,兩個版本都不需要分支,因此沒有分支錯誤預測懲罰。

使用位操作:

void func(int a,int b){
    int c = a - b;
    int k = (c >> 31) & 0x1;
    int max = a - k * c;
    int min = b + k * c;
    printf("max = %d\nmin = %d",max,min);
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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