为什么在我的电脑上没有g++中的-O2,sqrt会变得更快
Why sqrt become much faster without -O2 in g++ on my computer?
考虑以下代码:
#include <cstdio>
#include <cmath>
const int COUNT = 1000000000;
int main()
{
double sum = 0;
for (int i = 1; i <= COUNT; ++i) {
sum += sqrt(i);
}
printf("%fn", sum);
return 0;
}
没有-O2
,它在我的计算机上只运行2.9秒,而有-O2
时它运行6.4秒。
我的电脑是Fedora 23,g++5.3.1。
我在Ubuntu 14.04(g++4.8)上也尝试过同样的方法,它没有问题(都是6.4秒)。
sqrt
函数的调用。
优化版本使用SSE sqrtsd
指令。但在指令完成后,它会检查结果值是否不是NaN。如果结果值是NaN,那么它会调用glibc sqrt
函数来设置正确的错误标志(请参阅math_error(7)
的手册页)。有关详细解释,请参阅编译器为什么在编译的汇编代码中生成额外的sqrt。
为什么gcc认为这更快?没人知道。如果您确信您的数字不会生成NaN,请使用-fno-math-errno
编译选项。
调查程序集可能会找到一些答案,但查看代码差异的最简单方法是执行-fdump-tree-optimized
。这个问题似乎与sqrt
过载有关,即由C库sqrt(double)
和C++11sqrt(int)
提供的过载。后者似乎更快,GCC似乎不在乎您是否使用-std=c++11
或前缀std::
到sqrt
。
以下是带有-O2
或-O
的转储摘录(没有编号的-O
启用优化,要禁用所有优化,请省略-O
):
int i;
double sum;
double _9;
__type _10;
<bb 2>:
<bb 3>:
# sum_15 = PHI <sum_6(3), 0.0(2)>
# i_16 = PHI <i_7(3), 1(2)>
_9 = (double) i_16;
_10 = __builtin_sqrt (_9);
sum_6 = _10 + sum_15;
i_7 = i_16 + 1;
if (i_7 == 1000000001)
goto <bb 4>;
else
goto <bb 3>;
则无-O2
:
<bb 4>:
_8 = std::sqrt<int> (i_2);
sum_9 = sum_1 + _8;
i_10 = i_2 + 1;
goto <bb 3>;
请注意,它使用std::sqrt<int>
。对于持怀疑态度的人,请参阅为什么全球范围内的sqrt比MinGW中的std::sqrt慢得多?
相关文章:
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 如果我重新定义 sqrt 函数,为什么使用 std::sqrt 失败?
- 使用未声明的标识符"sqrt"?
- 在 SVM-Struct 中未定义对 sqrt 的引用(已使用 -lm)
- 为什么我的程序在 O0 和 O2 的优化级别返回不同的结果
- C++ 在类中使用常量引用文本时 O2 内存泄漏
- 重载标准::sqrt
- O2优化水平中断程序工作
- 为什么添加 sqrt() 不会导致C++冲突?
- 如何在 Skylake 架构上最大化 sqrt-heavy loop 的指令级并行性?
- gcc -O2 比 gcc -O2 -g 小,后跟 strip --strip-all
- How can I std::sqrt(boost::lambda::placeholder1_type)?
- 计算 1 - sqrt(x) 用于小参数 x (~10^-12),类似于 expm1(在 C/C++ 中)
- ICC 中的 -O3 会弄乱内联函数,使用 -O1 或 -O2 或相应的手动组装
- ICC 中的 -O2 搞砸了汇编程序,ICC 中的 -O1 和 GCC / Clang 中的所有优化都很好
- 如何获取特征张量的 sqrt() 函数返回的标量值
- C++ sqrt() 计算帮助
- 非初始化警告需求-O2
- 尽可能快地比较形式(a + sqrt(b))中的两个值
- 为什么在我的电脑上没有g++中的-O2,sqrt会变得更快