在内存位置调用 add 是否比在寄存器上调用它然后移动值更快?
Is calling `add` on a memory location faster than calling it on a register and then moving the value?
什么更快:
add DWORD PTR [rbp-0x4],1
或
mov eax,DWORD PTR [rbp-0x4]
add eax,1
mov DWORD PTR [rbp-0x4],eax
我看过编译器生成的第二个代码,所以也许在寄存器上调用 add
会快得多?
添加到寄存器可能 更快(因为寄存器在芯片上)但是,由于您无论如何都必须加载和存储数据,所以您不太可能看到一个改进。
冗长的方法甚至可能 更慢 因为 CPU 可能有机会优化较短的代码。此外,较短的代码 可能 对 read/modify/write 具有原子性,具体取决于您的编码方式。肯定不会浪费eax
寄存器。
最重要的是,更长的代码不太可能足以改进(如果有的话)来证明可读性下降是合理的。
但您不必猜测(甚至不必问我们)- 芯片制造商提供了大量有关指令时序的详细信息。例如,Intel's optimisation manual.
它们都解码为相同数量的后端微指令,但内存目标 add
在现代 Intel/AMD CPU 上以更少的融合域微指令通过前端获取这些微指令.
在 Intel CPU 上,add [mem], imm
解码为微融合加载+添加和微融合存储地址+存储数据,因此前端总共有 2 个融合域微指令。 AMD CPU 始终将内存操作数与 ALU 操作分组,而不调用它 "micro-fusion",这就是它们一直以来的工作方式。
(https://agner.org/optimize/ and ).
第一种方法 不会将值留在寄存器中 ,因此如果表达式的值是用过的。仅针对内存的副作用。
使用 [rbp - 4]
并在内存中递增一个本地代码,闻起来像未优化/调试模式代码,您应该 不 查看 优化的代码通常使用 [rsp +- constant]
来寻址局部变量,并且(除非变量是 volatile
)不会立即将其再次存储回内存中。
Why does clang produce inefficient asm with -O0 (for this simple floating point sum)? - 在调试模式下编译,又名 -O0
(默认)分别编译每个 C 语句,并像 volatile
一样对待每个变量,这太可怕了。
请参阅 了解如何让编译器生成有趣的 asm。 编写一个接受 args 和 returns 值的函数,这样它可以做一些事情而无需优化或将常量传播到 mov eax, constant_result
.
什么更快:
add DWORD PTR [rbp-0x4],1
或
mov eax,DWORD PTR [rbp-0x4]
add eax,1
mov DWORD PTR [rbp-0x4],eax
我看过编译器生成的第二个代码,所以也许在寄存器上调用 add
会快得多?
添加到寄存器可能 更快(因为寄存器在芯片上)但是,由于您无论如何都必须加载和存储数据,所以您不太可能看到一个改进。
冗长的方法甚至可能 更慢 因为 CPU 可能有机会优化较短的代码。此外,较短的代码 可能 对 read/modify/write 具有原子性,具体取决于您的编码方式。肯定不会浪费eax
寄存器。
最重要的是,更长的代码不太可能足以改进(如果有的话)来证明可读性下降是合理的。
但您不必猜测(甚至不必问我们)- 芯片制造商提供了大量有关指令时序的详细信息。例如,Intel's optimisation manual.
它们都解码为相同数量的后端微指令,但内存目标 add
在现代 Intel/AMD CPU 上以更少的融合域微指令通过前端获取这些微指令.
在 Intel CPU 上,add [mem], imm
解码为微融合加载+添加和微融合存储地址+存储数据,因此前端总共有 2 个融合域微指令。 AMD CPU 始终将内存操作数与 ALU 操作分组,而不调用它 "micro-fusion",这就是它们一直以来的工作方式。
(https://agner.org/optimize/ and
第一种方法 不会将值留在寄存器中 ,因此如果表达式的值是用过的。仅针对内存的副作用。
使用 [rbp - 4]
并在内存中递增一个本地代码,闻起来像未优化/调试模式代码,您应该 不 查看 优化的代码通常使用 [rsp +- constant]
来寻址局部变量,并且(除非变量是 volatile
)不会立即将其再次存储回内存中。
Why does clang produce inefficient asm with -O0 (for this simple floating point sum)? - 在调试模式下编译,又名 -O0
(默认)分别编译每个 C 语句,并像 volatile
一样对待每个变量,这太可怕了。
请参阅 mov eax, constant_result
.