【发布时间】:2021-05-14 22:47:12
【问题描述】:
下面的程序...
int main() {
float t = 0;
for (int i = 0; i < 1'000'000'000; i++) {
const float x = i;
t += x*x*x;
}
return t;
}
...在我的机器上完成大约需要 900 毫秒。而……
#include <cmath>
int main() {
float t = 0;
for (int i = 0; i < 1'000'000'000; i++) {
const float x = i;
t += std::pow(x,3.0f);
}
return t;
}
...大约需要 6600 毫秒才能完成。
我有点惊讶优化器没有内联 std::pow 函数,因此两个程序生成相同的代码并具有相同的性能。
有什么见解吗?您如何解释 5 倍的性能差异?
作为参考,我在 Linux x86 上使用 gcc -O3
更新:(C 版)
int main() {
float t = 0;
for (int i = 0; i < 1000000000; i++) {
const float x = i;
t += x*x*x;
}
return t;
}
...在我的机器上完成大约需要 900 毫秒。而……
#include <math.h>
int main() {
float t = 0;
for (int i = 0; i < 1000000000; i++) {
const float x = i;
t += powf(x,3.0f);
}
return t;
}
...大约需要 6600 毫秒才能完成。
更新 2
以下程序:
#include <math.h>
int main() {
float t = 0;
for (int i = 0; i < 1000000000; i++) {
const float x = i;
t += __builtin_powif(x,3.0f);
}
return t;
}
像第一个程序一样在 900 毫秒内运行。
为什么pow 不内联到__builtin_powif ?
更新 3:
使用-ffast-math以下程序:
#include <math.h>
#include <iostream>
int main() {
float t = 0;
for (int i = 0; i < 1'000'000'000; i++) {
const float x = i;
t += powf(x, 3.0f);
}
std::cout << t;
}
运行时间为 227 毫秒(x*x*x 版本也是如此)。每次迭代需要 200 皮秒。使用-fopt-info 它说optimized: loop vectorized using 16 byte vectors 和optimized: loop with 2 iterations completely unrolled 所以我猜这意味着它对SSE 进行4 批迭代并一次进行2 次迭代流水线(一次总共进行8 次迭代),或者类似的东西?
【问题讨论】:
-
如果你使用
pow(x, 3)会发生什么? -
您对
std::pow的调用使用浮点值作为指数(您可以用它计算根),而x*x*x则更简单。 -
如您所知,请不要同时标记 C 和 C++,除非问题确实与两种语言有关(它们之间的翻译或类似语言)。您的代码是 C++ 特定的,不能使用 C 编译器构建。
-
既然您使用的是 GCC,请尝试
t += __builtin_powif(x, 3)-- 结果应该很有启发性。 -
试试
-ffast-math。