Assembly 优化装配均衡程序

Assembly 优化装配均衡程序,assembly,x86,Assembly,X86,我正在尝试编写一个(非常)短的汇编例程,它测试两个DWORD是否相等,并返回一个布尔值(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

我正在尝试编写一个(非常)短的汇编例程,它测试两个DWORD是否相等,并返回一个布尔值(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

版本1有一条额外的分支指令,但版本2有一条额外的push和一条额外的pop指令。你希望哪一个跑得最快?为什么?这是否取决于分支是否会被执行/预测?

这两个版本都不好。一个随机分支需要很长时间才能执行,因为它无法预测,而且由于部分寄存器写入,lahf只是一个no no。但当然,在汇编程序中编写相等性测试完全是胡说八道,因为函数开销将是内联等效指令的倍数,所以我来:

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

我以前在需要优化的应用程序中发现过这些瓶颈,它们肯定表明您遇到了瓶颈,无法进一步优化

最好的做法是选择一种不同的算法或数据布局,这种算法或数据布局比当前的算法或布局更适合平台和访问模式。这可能是你能做的最重要的一件事

但是,由于截止日期或其他限制,有时也不可能,因此您需要对其进行创新,这可能意味着使用SIMD操作一次测试多个元素(例如,使用_-mm_-cmpeq_-epi32内在函数来比较4个元素)。如果要在该分支上进行分支,可以将16个元素(按位或掩码)进行比较,然后在该分支上进行分支(然后在分支内选择正确的数据)

这主要是在分支机构非常昂贵的平台上以及在IA-32/64上(例如,分支机构很便宜)带来的好处

还要注意的是,由于无序执行(OOE),英特尔平台将无法使用;很可能是您正在使用的探查器报告了或多或少随机位置上的暂停,因为处理器需要等待从缓存或RAM读取数据


如果碰巧遇到这种情况,请确保优化算法,使其更便于缓存(例如,计算出缓存线中适合的项目数,减小数据结构的大小等)

两者都不是,因为在任何实际软件中,瓶颈不会发生在两个DWORD的相等测试中。什么是“真正的软件”?仅仅调用“相等例程”的行为可能比实际比较更昂贵。我知道这不可能是瓶颈,但这更像是一个学术练习。这是一个过于简单的代码生成器的一部分,因此任何性能优势都会被应用到相当大的代码体上,显然是内联的。@Cat,我不止一次看到这是一个瓶颈。我不知道SZ的存在,这比我的两次尝试都要好。“SZ al”你不是说“setz al”吗?