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版本使用对glibc
sqrt
函数的调用

优化版使用SSE
sqrtsd
指令。但指令完成后,它会检查结果值是否为NaN。如果结果值为NaN,则会调用glibc
sqrt
函数来设置正确的错误标志(有关
数学错误(7)
,请参阅手册页)。有关详细说明,请参阅


为什么gcc认为这更快?没有人知道。如果您确定您的数字不生成NaN,请使用
-fno math errno
编译选项。

调查程序集可能会找到一些答案,但查看代码差异的最简单方法是执行
-fdump tree优化
。问题似乎与
有关>sqrt
重载,即由C库
sqrt(double)
和C++11
sqrt(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>;