【发布时间】:2015-03-02 10:09:26
【问题描述】:
下面是一个计算多项式的 C 函数:
/* Calculate a0 + a1*x + a2*x^2 + ... + an*x^n */
/* from CSAPP Ex.5.5, modified to integer version */
int poly(int a[], int x, int degree) {
long int i;
int result = a[0];
int xpwr = x;
for (i = 1; i <= degree; ++i) {
result += a[i]*xpwr;
xpwr *= x;
}
return result;
}
还有一个主要功能:
#define TIMES 100000ll
int main(void) {
long long int i;
unsigned long long int result = 0;
for (i = 0; i < TIMES; ++i) {
/* g_a is an int[10000] global variable with all elements equals to 1 */
/* x = 2, i.e. evaluate 1 + 2 + 2^2 + ... + 2^9999 */
result += poly(g_a, 2, 9999);
}
printf("%lld\n", result);
return 0;
}
当我用GCC和选项-O1和-O2分别编译程序时,我发现-O1比-O2快很多。
平台详情:
- i5-4600
- 带有内核 3.18 的 Arch Linux x86_64
- GCC 4.9.2
- gcc -O1 -o /tmp/a.out test.c
- gcc -O2 -o /tmp/a.out test.c
结果:
- 当 TIMES = 100000ll 时,-O1 立即打印结果,而 -O2 需要 0.36s
- 当 TIMES = 1000000000ll 时,-O1 在 0.28 秒内打印结果,-O2 耗时太长,以至于我没有完成测试
似乎 -O1 比 -O2 快大约 10000 倍。
当我在 Mac (clang-600.0.56) 上测试它时,结果更加奇怪:-O1 即使在 TIMES = 1000000000000000000ll 时也不超过 0.02s
我已经测试了以下更改:
- 使 g_a 随机(元素从 1 到 10)
- x = 19234(或其他数字)
- 使用 int 而不是 long long int
结果是一样的。
我试图查看汇编代码,似乎 -O1 正在调用 poly 函数,而 -O2 正在执行内联优化。但是内联应该会让性能更好,不是吗?
是什么造成了这些巨大的差异?为什么clang上的-O1可以让程序这么快? -O1 做错了吗? (我无法检查结果,因为没有优化它太慢了)
【问题讨论】: