【发布时间】:2023-03-28 06:28:01
【问题描述】:
我写了很多向量化的循环,所以1个常见的成语是
volatile int dummy[1<<10];
for (int64_t i = 0; i + 16 <= argc; i+= 16) // process all elements with whole vector
{
int x = dummy[i];
}
// handle remainder (hopefully with SIMD too)
但是生成的机器代码比我想要的多 1 条指令(使用 gcc 4.9)
.L3:
leaq -16(%rax), %rdx
addq $16, %rax
cmpq %rcx, %rax
movl -120(%rsp,%rdx,4), %edx
jbe .L3
如果我将代码更改为for (int64_t i = 0; i <= argc - 16; i+= 16),那么“额外”
指令消失了:
.L2:
movl -120(%rsp,%rax,4), %ecx
addq $16, %rax
cmpq %rdx, %rax
jbe .L2
但为什么会有差异?我在想可能是由于循环不变量,但太模糊了。然后我注意到在 5 指令情况下,增量是在加载之前完成的,由于 x86 的破坏性 2 操作数指令,这将需要额外的 mov。 所以另一种解释可能是它的交易指令并行性为 1 条额外指令。
虽然看起来几乎不会有任何性能差异,但有人能解释一下这个谜团吗(最好谁知道编译器转换)?
理想情况下,我希望保留 i + 16
【问题讨论】:
-
只问关于优化代码的问题,非优化代码对程序来说是字面意思,根本不代表速度。当您打开优化器时,您现在所拥有的将一无所有,显然您无法让它更快。
-
但这是优化代码 (-O3),除了易失性负载吗?是为了用简单的方式来说明问题
-
我同意 supercat 的回答非常精确,但它假设将 i + 16
标签: gcc optimization assembly x86 gcc4.9