为什么 x[i]=if 比 if... x[i]= 快
Why is x[i]=if faster than if... x[i]=
这个有我baffled/intrigued,为什么是这个代码
void maxArray(double* x, double* y) {
for (int i = 0; i < 65536; i++) {
x[i] = ((y[i] > x[i]) ? y[i] : x[i]);
}
}
...比此代码更快?
void maxArray(double* x, double* y) {
for (int i = 0; i < 65536; i++) {
if (y[i] > x[i]) x[i] = y[i];
}
}
并且作为记录,第一个中的结果程序集与扩展版本相同:
inline double fn(double a, double b) {
if (a > b) {
return a;
} else {
return b;
}
}
void maxArray(double* x, double* y) {
for (int i = 0; i < 65536; i++) {
x[i] = fn(y[i], x[i]);
}
}
我明白了。第一个是设置x[i]
为条件,中间是有条件设置x[i]
。两者都有条件,所以两者都有分支?是因为后者的扩展 if 语句被优化为 vector assembly max
命令,而前者由于某种原因未被识别为 max 函数?
gcc 10.3 x86_64 -Ofast -march=native
从生成的汇编代码中应该就清楚了。在第一种情况下你得到:
# x[i] = ((y[i] > x[i]) ? y[i] : x[i])
vmovupd ymm1, YMMWORD PTR [rsi+rax
vmaxpd ymm0, ymm1, YMMWORD PTR [rdi+rax]
vmovupd YMMWORD PTR [rdi+rax], ymm0
而在第二种情况下你得到:
# if (y[i] > x[i]) x[i] = y[i];
vmovupd ymm0, YMMWORD PTR [rsi+rax]
vcmppd k1, ymm0, YMMWORD PTR [rdi+rax], 14
kortestb k1, k1
je .L3
vmovupd YMMWORD PTR [rdi+rax]{k1}, ymm0
正如您在第一个片段中看到的,编译器使用了 VMAXPD
specialized instruction to compute the maximum of two double precision floating point values, without branching. In the second snippet though, there is a compare (VCMPPD
) followed by a test (KORTESTB
) and a branch (JE
).
这个有我baffled/intrigued,为什么是这个代码
void maxArray(double* x, double* y) {
for (int i = 0; i < 65536; i++) {
x[i] = ((y[i] > x[i]) ? y[i] : x[i]);
}
}
...比此代码更快?
void maxArray(double* x, double* y) {
for (int i = 0; i < 65536; i++) {
if (y[i] > x[i]) x[i] = y[i];
}
}
并且作为记录,第一个中的结果程序集与扩展版本相同:
inline double fn(double a, double b) {
if (a > b) {
return a;
} else {
return b;
}
}
void maxArray(double* x, double* y) {
for (int i = 0; i < 65536; i++) {
x[i] = fn(y[i], x[i]);
}
}
我明白了。第一个是设置x[i]
为条件,中间是有条件设置x[i]
。两者都有条件,所以两者都有分支?是因为后者的扩展 if 语句被优化为 vector assembly max
命令,而前者由于某种原因未被识别为 max 函数?
gcc 10.3 x86_64 -Ofast -march=native
从生成的汇编代码中应该就清楚了。在第一种情况下你得到:
# x[i] = ((y[i] > x[i]) ? y[i] : x[i])
vmovupd ymm1, YMMWORD PTR [rsi+rax
vmaxpd ymm0, ymm1, YMMWORD PTR [rdi+rax]
vmovupd YMMWORD PTR [rdi+rax], ymm0
而在第二种情况下你得到:
# if (y[i] > x[i]) x[i] = y[i];
vmovupd ymm0, YMMWORD PTR [rsi+rax]
vcmppd k1, ymm0, YMMWORD PTR [rdi+rax], 14
kortestb k1, k1
je .L3
vmovupd YMMWORD PTR [rdi+rax]{k1}, ymm0
正如您在第一个片段中看到的,编译器使用了 VMAXPD
specialized instruction to compute the maximum of two double precision floating point values, without branching. In the second snippet though, there is a compare (VCMPPD
) followed by a test (KORTESTB
) and a branch (JE
).