C++ 执行时间差异的来源?

C++ 执行时间差异的来源?,c++,C++,我想询问在分析某些数学运算时观察到的执行时间差异的来源。我发现了一些明显的差异,我希望有人能对这件事有所了解: 观察1:分析数学运算时,会观察到不同的执行时间。作为我的意思的一个例子,如果编译了下面的代码,并且生成的代码分别执行了10次,我将观察10次不同的执行时间。(此外,正如预期的那样,执行时间将取决于使用方法1还是方法2) intmain() { 无符号x{0xFFFFFFFF}; 无符号y; int MAX_循环{1000}; boost::posix_time::ptime start

我想询问在分析某些数学运算时观察到的执行时间差异的来源。我发现了一些明显的差异,我希望有人能对这件事有所了解:

观察1:分析数学运算时,会观察到不同的执行时间。作为我的意思的一个例子,如果编译了下面的代码,并且生成的代码分别执行了10次,我将观察10次不同的执行时间。(此外,正如预期的那样,执行时间将取决于使用方法1还是方法2)

intmain()
{
无符号x{0xFFFFFFFF};
无符号y;
int MAX_循环{1000};
boost::posix_time::ptime start=boost::posix_time::microsec_clock::local_time();
对于(int i=0;i>31;//方法1
//y=x/2^31;//方法2(注意:此表达式在实际代码中展开)
}
boost::posix_time::ptime stop=boost::posix_time::microsec_clock::local_time();
boost::posix_time::time_duration duration=开始-停止;
//输出到std::无法显示。。。
}
方法1产生平均执行时间[平均+/-标准偏差]575us+/-50us(!!),而方法2产生平均执行时间12.9us+/-1.6us

方法2与我关系不大,但方法1的方差似乎相当大。事实上,方法1观察到的时间范围为190 us!这种执行时间范围让我有些吃惊。我的问题是,我是否应该对这种执行时间范围感到惊讶?对这种差异有一个很好的解释吗

观察2:执行时间不随代码中执行的循环数而变化。上述统计数据基于最大回路值1e3。如果我将MAX_LOOP增加到1e8,那么我观察到方法1需要180.487ms+/-3.139ms,而方法2需要1021.825ms+/-16.597ms。执行时间的增加不随所需绝对执行次数的增加而增加。即:

  • 循环计数比率:1e8/1e3=1e5
  • 位移位分割配置文件时间比:180487/575=313
  • 正整数除法配置文件时间比率:1021825/12.9=79211
使用方法1(位移位除法),性能增益基本上从575ns/除法增加到1.805ns/除法。相反,正整数除法从13ns/除法变为10.22ns/除法。规则除法似乎与执行的循环迭代次数成线性关系,但当循环迭代次数较多时,位移位法似乎表现出极大的性能改进

我是否在某个不明显的地方犯了错误?如果没有,谁能解释为什么在这种情况下,位移位除法的性能增益变化如此之大?编译器是否可能正在使用默认优化?(如果是这样,(a)优化真的有那么好吗?和(b)我如何找出编译器默认使用的优化?)

其他可能重要的事情:

  • 苹果LLVM版本7.0.2(clang-700.1.81)
  • 增压1.65.1(严格用于计时)
  • 执行发生在我的笔记本电脑i7的一个核心上
  • 使用:clang++-std=c++11-I在没有优化的情况下编译-我-lboost_系统[fname.cpp]-o[fname]

不确定它是否适用于此处,但如果您使用秒表,则执行更多操作的方法将具有更高的差异,因为操作系统切换到其他线程/进程中间操作的可能性更高。如果是这样的话,那么它并不是一种真正随时间变化的方法,而是在等待处理器更频繁地从操作系统返回。好了,ptime是挂钟时间,在这种情况下,10%的偏差是没有什么可写的。还要注意,
2^31
执行XOR并生成
29
,不是只有1000次迭代的指数,结果可能会受到计时器分辨率的影响…计时器分辨率、上下文切换、进程启动时间。您需要的是一种特定于操作系统的方法来跟踪进程运行后分配给它的实际CPU时间。
int main()
{
    unsigned x { 0xFFFFFFFF };
    unsigned y; 
    int MAX_LOOP { 1000 };
    boost::posix_time::ptime start = boost::posix_time::microsec_clock::local_time();
    for( int i = 0; i < MAX_LOOP; i++ )
    {
        y = x >> 31;   // Method 1
    //  y = x/2^31;    // Method 2 (note: this expression is expanded in the actual code)
    }
    boost::posix_time::ptime stop = boost::posix_time::microsec_clock::local_time();
    boost::posix_time::time_duration duration = start - stop;

    // output to std::cout not shown...
}