gpt4 book ai didi

c++ - 使用汇编加速位测试操作

转载 作者:太空狗 更新时间:2023-10-29 20:25:08 28 4
gpt4 key购买 nike

我有一个性能问题 - 我根本无法超越编译器生成代码的发布版本速度。它慢了 25%。我编写的函数在我的测试中被调用了大约 2000 万次,因此让它运行得更快会有返回。

C++ 中的代码非常简单:

static inline char GetBit(char *data, size_t bit)
{
return 0 != (data[bit / 8] & (1 << (bit % 8)));
}

这是我为 64 位 MASM 编写的版本:

mov   rax, rdx  
mov r10, 8h
xor rdx, rdx
div rax, r10
mov al, byte ptr [rax+rcx]
mov bl, 1h
mov cl, dl
shl bl, cl
and al, bl
shr al, cl
ret

好吧,我不是一个汇编专家,但我不认为编译器仅仅创建更好的汇编就可以使代码速度提高 25%。所以诀窍[可能]在函数调用中。它尊重 C++ 代码的内联关键字并且不生成任何调用,但我就是不能让它为 asm 代码工作:

extern "C" inline char GetBitAsm(char *data, size_t bit);

我已经使用 dumpbin 反汇编了代码,我可以清楚地看到我的代码 + 函数调用。虽然没有为编译器版本生成调用:

mov   rdx, qword ptr [bit]  
mov rcx, qword ptr [data]
call GetBitAsm (013F588EFDh)
mov byte ptr [isbit], al

另外还有2次读取和1次写入内存,而在编译器生成的内容中,可能只有1次读取。我在某处读到 div 操作码大约需要 20 个周期,而单个内存访问至少需要 100 个周期。因此,从内存中删除 mov rdx 和 mov rcx,用父函数中寄存器中的值替换它们,我认为,可以解决问题

问题:

  1. 这真的是它运行如此缓慢的原因吗?

  2. 如何在 release 版本中使用 asm 编写的函数内联?

  3. 如何进一步增强我的汇编代码,使其更快?

最佳答案

相对于任何编译器的内联代码,无意中听到的函数调用和汇编代码中的 DIV 指令会降低性能。仅函数调用开销就可能大于编译器代码平均花费的周期数。 DIV 指令可能会大几倍。

内存访问在现代处理器上通常是免费的,因为它们可以从处理器的缓存中得到满足。在您的汇编版本中,您的内存访问平均花费 0 个周期,因为您的代码可能足够慢,以至于处理器可以在需要访问之前轻松地将内存预取到其缓存中。另一方面,编译器的代码可能足够快,以至于它从内存中读取值的速度可能比处理器获取它的速度更快。它必须定期停止等待提取编译。因此,虽然编译器代码中的平均内存访问周期时间会更长,但这只是因为它得到了更好的优化。

您的问题的最佳解决方案是让编译器进行优化。坦率地说,它似乎比您更了解如何生成更好的代码。即使是汇编专家也很难改进编译器,并且需要在更广泛的范围内查看问题,而不仅仅是这个函数的指令选择。

如果您仍然宁愿使用自己的汇编代码,那么可以使用编译器的内联汇编功能,并摆脱 DIV 指令。它的性能仍然不如编译器的版本,但应该更接近。

关于c++ - 使用汇编加速位测试操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24723158/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com