使用 -O3 或 -Ofast 来编译您的基准代码是否现实,还是会删除代码?

Lat*_*Guy 5 c++ optimization g++ compiler-flags compiler-optimization

当使用下面的基准代码编译时,-O3它在延迟方面的差异给我留下了深刻的印象,所以我开始怀疑编译器是否通过以某种方式删除代码而“作弊”。有没有办法检查?我可以安全地进行基准测试-O3吗?期望速度提高 15 倍是否现实?

没有的结果-O3:平均:239纳米最小:230 纳米(900 万次迭代) 有
结果-O3:平均:14纳米,最小:12 纳米(900 万次迭代)

int iterations = stoi(argv[1]);
int load = stoi(argv[2]);

long long x = 0;

for(int i = 0; i < iterations; i++) {

    long start = get_nano_ts(); // START clock

    for(int j = 0; j < load; j++) {
        if (i % 4 == 0) {
            x += (i % 4) * (i % 8);
        } else {
            x -= (i % 16) * (i % 32);
        }
    }

    long end = get_nano_ts(); // STOP clock

    // (omitted for clarity)
}

cout << "My result: " << x << endl;
Run Code Online (Sandbox Code Playgroud)

注意:我clock_gettime用来测量:

long get_nano_ts() {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec * 1000000000 + ts.tv_nsec;
}
Run Code Online (Sandbox Code Playgroud)

wal*_*lyk 1

对您认为正在测量的内容进行基准测试可能非常困难。在内循环的情况下:

for (int j = 0;  j < load;  ++j)
        if (i % 4 == 0)
                x += (i % 4) * (i % 8);
        else    x -= (i % 16) * (i % 32);
Run Code Online (Sandbox Code Playgroud)

精明的编译器也许能够看穿这一点并将代码更改为如下所示:

 x = load * 174;   // example only
Run Code Online (Sandbox Code Playgroud)

我知道这并不等同,但有一些相当简单的表达式可以代替该循环。

确定的方法是使用gcc -S编译器选项并查看它生成的汇编代码。