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

Ala*_*air 4 c x86 gcc x86-64 compiler-optimization

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

[见组装]

void maxArray(double* x, double* y) {
    for (int i = 0; i < 65536; i++) {
        x[i] = ((y[i] > x[i]) ? y[i] : x[i]);
    }
}
Run Code Online (Sandbox Code Playgroud)

...比这个代码更快?

[见组装]

void maxArray(double* x, double* y) {
    for (int i = 0; i < 65536; i++) {
        if (y[i] > x[i]) x[i] = y[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

并且作为记录,第一个中的结果程序集与扩展版本相同:

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]);
    }
}
Run Code Online (Sandbox Code Playgroud)

[见组装]

我明白了。第一个是设置x[i]到条件,中间是有条件设置x[i]。两者都有条件,所以都有分支?是不是因为后者的扩展 if 语句被优化为向量汇编max命令,而前者由于某种原因未被识别为 max 函数?

gcc 10.3 x86_64 -Ofast -march=native

Mar*_*lli 5

从生成的汇编代码应该是清楚的。在第一种情况下,您会得到:

# 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
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,您会得到:

# 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
Run Code Online (Sandbox Code Playgroud)

正如您在第一个代码段中看到的,编译器使用VMAXPD专用指令来计算两个双精度浮点值的最大值,没有分支。但是,在第二个代码段中,有一个比较 ( VCMPPD),然后是一个测试 ( KORTESTB) 和一个分支 ( JE)。

  • @Alasdair:它不能优化为“max”+向量存储,因为不允许发明写入。[icc 崩溃:编译器可以发明抽象机中不存在的写入吗?](/sf/ask/3816746321/) 和 [AVX-512 和分支](https://stackoverflow.com/q /47481762) (3认同)