c - 为什么 x[i]=if 比 if... x[i]= 快

标签 c gcc x86 x86-64 compiler-optimization

这让我感到困惑/好奇,为什么这个代码
[see assembly]

void maxArray(double* x, double* y) {
    for (int i = 0; i < 65536; i++) {
        x[i] = ((y[i] > x[i]) ? y[i] : x[i]);
    }
}
...比这个代码更快?
[see assembly]
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]);
    }
}
[see assembly]
我明白了。第一个是设置x[i]到一个条件,中间是条件设置x[i] .两者都有条件,所以都有分支?是不是因为后者的扩展if语句被优化成 vector 汇编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 计算两个 double 浮点值的最大值的专用指令,无需分支。不过,在第二个片段中,有一个比较( VCMPPD ),然后是一个测试( KORTESTB )和一个分支( JE )。

关于c - 为什么 x[i]=if 比 if... x[i]= 快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67123745/

相关文章:

c - 使用switch语句是否可以得到 'and'操作

assembly - 如何将二进制整数转换为十六进制字符串?

c - 缓冲区溢出攻击格式

assembly - 无法从 kernel.s 打印,即使它已加载到内存中

c - 如何编写一个 C 程序来确定输入是否为质数和数字

c - 如何从 C 中的数组中删除一个元素?

c - 如何在 C 中创建节点中具有不同类型值的树?

c++ - 适用于 Windows 的可移植 C/C++ 应用程序的 DLL 依赖项

c++ - 为什么 g++ 在启用 `-fpic` 的情况下不发出与构造函数相关的 noexcept 警告?

gcc - qsort_s 位于 Windows 的 MingGW (gcc 4.8) 中的哪个 header 中?