Assembly 在内存位置上调用'add'是否比在寄存器上调用它然后移动值更快?
更快的是:Assembly 在内存位置上调用'add'是否比在寄存器上调用它然后移动值更快?,assembly,x86,x86-64,micro-optimization,Assembly,X86,X86 64,Micro Optimization,更快的是: add DWORD PTR [rbp-0x4],1 或 我见过编译器生成的第二个代码,因此在寄存器上调用add可能要快得多?添加到寄存器可能要快得多(因为寄存器是片上的),但是,由于无论如何都必须加载和存储数据,所以不太可能看到改进 冗长的方法甚至可能更慢,因为CPU可能有机会优化较短的代码。此外,较短的代码可能具有读/修改/写的原子性,这取决于您如何编写代码。它当然不会浪费eax寄存器 总之,较长的代码不太可能有足够的改进(如果有的话)来证明其可读性 但你不必猜测(甚至不必问我们
add DWORD PTR [rbp-0x4],1
或
我见过编译器生成的第二个代码,因此在寄存器上调用
add
可能要快得多?添加到寄存器可能要快得多(因为寄存器是片上的),但是,由于无论如何都必须加载和存储数据,所以不太可能看到改进
冗长的方法甚至可能更慢,因为CPU可能有机会优化较短的代码。此外,较短的代码可能具有读/修改/写的原子性,这取决于您如何编写代码。它当然不会浪费eax
寄存器
总之,较长的代码不太可能有足够的改进(如果有的话)来证明其可读性
但你不必猜测(甚至不必问我们)——芯片制造商提供了大量关于指令时间安排的详细信息。例如,.它们都解码为相同数量的后端UOP,但内存目标
add
通过前端在现代Intel/AMD CPU上较少的融合域UOP中获取这些UOP
在英特尔CPU上,add[mem],imm
解码为微融合加载+添加和微融合存储地址+存储数据,因此前端总共有2个融合域UOP。AMD CPU总是将内存操作数与ALU操作分组,而不称之为“微融合”,这正是它们一直以来的工作方式。
(和)
第一种方法不会将值保留在寄存器中,因此如果使用了表达式的值,则不能将其用作
++a
的一部分。仅用于治疗对记忆的副作用
使用
[rbp-4]
并递增内存中的本地代码闻起来像是未优化/调试模式代码,您不应该查看它的效率。优化代码通常使用[rsp+-constant]
来处理本地代码,并且(除非变量是volatile
)不会马上把它重新存储到内存中
-在调试模式下编译,aka-O0
(默认值)分别编译每个C语句,并将每个变量视为volatile
,这非常可怕
有关如何让编译器生成有趣的asm的信息,请参阅。编写一个函数,该函数接受args并返回一个值,这样它就可以执行某些操作,而无需优化掉常量或将常量传播到
mov eax,常量结果
可能较慢,但实现已定义…您可能看到它是由禁用优化的编译器生成的…Re:atomicity:仅针对中断,因此仅wrt。在该内核上运行的其他代码。在C++中,我们可以说它是原子WRT。同一线程中的一个信号处理程序。@Peter,这就是为什么我使用了黄鼠狼的话“取决于您如何编码”:-)我的理解是,内存上的inc
操作码上的lock
前缀将被buslock锁定,以便其他内核不会尝试使用该值。我可能是错的,当然,我已经有一段时间没有在金属附近编码了。对,让它成为原子wrt。您需要的其他内核lock inc[mem]
或lock add[mem],1
。但是,如果内存没有跨缓存线拆分,那么内核只需要保留从加载到存储的那一行(一个“缓存锁”)的MESI独占所有权;无需打扰正在访问不同线路的其他内核。有详细的概述。感谢您的详细回答。
mov eax,DWORD PTR [rbp-0x4]
add eax,1
mov DWORD PTR [rbp-0x4],eax