C++ 为什么在g++;在我的电脑上?
考虑以下代码:C++ 为什么在g++;在我的电脑上?,c++,performance,g++,sqrt,C++,Performance,G++,Sqrt,考虑以下代码: #包括 #包括 常数整数计数=100000000; int main() { 双和=0; 对于(inti=1;iNaive版本使用对glibcsqrt函数的调用 优化版使用SSEsqrtsd指令。但指令完成后,它会检查结果值是否为NaN。如果结果值为NaN,则会调用glibcsqrt函数来设置正确的错误标志(有关数学错误(7),请参阅手册页)。有关详细说明,请参阅 为什么gcc认为这更快?没有人知道。如果您确定您的数字不生成NaN,请使用-fno math errno编译选项。调
#包括
#包括
常数整数计数=100000000;
int main()
{
双和=0;
对于(inti=1;iNaive版本使用对glibcsqrt
函数的调用
优化版使用SSEsqrtsd
指令。但指令完成后,它会检查结果值是否为NaN。如果结果值为NaN,则会调用glibcsqrt
函数来设置正确的错误标志(有关数学错误(7)
,请参阅手册页)。有关详细说明,请参阅
为什么gcc认为这更快?没有人知道。如果您确定您的数字不生成NaN,请使用-fno math errno
编译选项。调查程序集可能会找到一些答案,但查看代码差异的最简单方法是执行-fdump tree优化
。问题似乎与有关>sqrt
重载,即由C库sqrt(double)
和C++11sqrt(int)
提供的重载。后者似乎更快,GCC似乎并不关心是否使用-std=C++11
或前缀std:
到sqrt
下面是使用-O2
或-O
转储的摘录(-O
无编号启用优化,要禁用所有优化,请省略-O
):
请注意,它使用了std::sqrt
。对于怀疑者,请使用time
命令查看@kfsone。如果已经有一个非常好的计时机制,则不需要创建自己的计时机制。使用-O
,GCC使用sqrtsd%xmm0,%xmm0
指令。使用-O2
,GCC使用sqrtsd%xmm0,%xmm1
指令,它在我的系统上会将时间增加2秒。如果我使用-O2
汇编代码,将其更改,并将剩余的%xmm1
引用更改为%xmm0
,时间会再次减少2秒。但我不知道为什么它会更快,也不知道为什么如果它更快,GCC不会使用更快的版本在上。@user6292850那个否决票是我的,我否决了它,因为它是错误的,我对这个问题的评论在你发布答案之前就已经表明它是错误的。@user6292850如果我能够看到性能上的差异,并且调用哪些函数的更改为零,那么问题不可能出在调用哪些函数上。@user6292850使用-O0
和-O
时的性能是相同的。我使用-O
是因为使用-O
生成的汇编代码与使用-O2
生成的汇编代码更接近,从而更容易锁定有问题的特定指令。对于-ffast math
,此检查是无效的o删除并生成更快的代码。除了在-o
,GCC使用sqrtsd
指令(使用不同的操作数),但是比在-O2
@hvd上获得了更好的性能,你是对的。似乎分支预测在某种程度上涉及了?-O2
生成jp
,而-O
使用jnp
。我不这么认为,请看我对这个问题的评论,但我不知道原因是什么。
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>;
<bb 4>:
_8 = std::sqrt<int> (i_2);
sum_9 = sum_1 + _8;
i_10 = i_2 + 1;
goto <bb 3>;