2011-05-28 55 views
0

我想寫一個(非常)短的程序集測試兩個dwords的相等性並返回一個布爾值(1 = true,0 = false)。到目前爲止,我已經提出了三種方法,其中一種使用LAHF,這在某些x86_64處理器中顯然不受支持,所以不幸的是,有一種方法不適用。優化的程序集等式例程

版本之一:

mov eax, [esp + 8] 
    cmp b, [esp + 4] 
    mov eax, 1 
    jnz jpt 
    mov eax, 0 
jpt: ret 

兩個版本:

mov eax, [ebp + 8] 
    cmp b, [ebp + 4] 
    pushf  ; Get lowest word of the flags register 
    pop ax  
    and eax, 0x0040 ; Extract the zero flag 
    shr eax, 6 ; eax is now true(1) if arg1 == arg2  
    ret 

的一個版本有一個額外的分支指令,但有兩個版本有一個額外的推動和一個額外的POP指令。你希望哪一個最快,爲什麼?這是否取決於如果分支將被採取/預測或不?

+0

既不是,因爲在任何真正的軟件中,瓶頸在兩個雙字的平等測試中不會發生。 – 2011-05-28 13:05:15

+0

什麼是「真正的軟件」? – James 2011-05-28 13:10:45

+0

只是_calling_「平等例程」的行爲可能比實際的比較更昂貴。 – Mat 2011-05-28 13:11:33

回答

2

兩者都是不好的。一個隨機分支需要很長的時間來執行,因爲它不能被預測,並且由於部分寄存器寫入,lahf只是一個「否」。但當然,寫彙編平等的測試完全是胡說八道,因爲那裏有功能的開銷將是等效指令內嵌的倍數,所以我來到這裏:

mov eax, [ebp + 8] 
cmp eax, [ebp + 4] 
setz al    ;set al to 1 if equal 
movzx eax,al   ;convert to dword 
ret 
+0

我沒有意識到SZ的存在,這比我的任何一次嘗試都要好得多。 – eyesathousand 2011-05-28 13:55:46

+0

「sz al」你是不是指「setz al」? – PhiS 2011-05-28 15:40:42

+0

當然可以。謝謝,修復它 – hirschhornsalz 2011-05-28 20:58:42

0

我已經在應用之前發現這些瓶頸我需要優化,他們肯定表明你已經撞上了牆壁,無法進一步優化。

最好的行動方式是選擇一種不同的算法或數據佈局,這種算法或數據佈局適合平臺和訪問模式,比現有的更好。這可能是你能做的最重要的事情。

但是,由於截止日期或其他限制,有時也是不可能的,因此您需要對其進行創新,這可能意味着使用SIMD操作一次測試多個元素(例如,使用_mm_cmpeq_epi32內在比較4個要素)。如果你打算在這個分支上進行分支,你可以比較16個元素,按位或者掩碼,然後在其上分支(然後在分支中選擇正確的數據)。

這主要是在分支機構非常昂貴並且在IA-32/64上不是這種情況的平臺上受益(例如,分支機構很便宜)。

另外請注意,由於英特爾平臺的無序執行(OOE)然後使用;很可能你正在使用的分析器報告一個或多或少的隨機位置,因爲處理器需要等待從緩存或RAM中讀取數據。

如果碰巧遇到這種情況,請確保優化算法以使其更容易緩存(例如,計算出緩存行中有多少物品,減少數據結構的大小等)。