c ++中可忽略不计的计时测量?

时间:2016-03-02 09:47:21

标签: c++ performance chrono

考虑以下代码:

#include <iostream>
#include <string>
#include <chrono>

using namespace std;

int main()
{
    int iter = 1000000;
    int loops = 10;
    while (loops)
    {
        int a=0, b=0, c=0, f = 0, m = 0, q = 0;
        auto begin = chrono::high_resolution_clock::now();
        auto end = chrono::high_resolution_clock::now();
        auto deltaT = end - begin;
        auto accumT = end - begin;
        accumT = accumT - accumT;
        auto controlT = accumT;
        srand(chrono::duration_cast<chrono::nanoseconds>(begin.time_since_epoch()).count());

        for (int i = 0; i < iter; i++) { 
            begin = chrono::high_resolution_clock::now();
            //no arithmetic operation
            end = chrono::high_resolution_clock::now();
            deltaT = end - begin;
            accumT += deltaT;
        }

        controlT = accumT; //control duration
        accumT = accumT - accumT; //reset to zero

        for (int i = 0; i < iter; i++) {
            auto n1 = rand() % 100;
            auto n2 = rand() % 100;
            begin = chrono::high_resolution_clock::now();
            c += i*2*n1*n2; //some arbitrary arithmetic operation
            end = chrono::high_resolution_clock::now();
            deltaT = end - begin;
            accumT += deltaT;
        }
        //print the difference in time between loop with no arithmetic operation and loop with
        cout << " c = " << c << "\t\t" << " | ";
        cout << "difference between 1st and 2nd loop: " << chrono::duration_cast<chrono::nanoseconds>(accumT - controlT).count() << endl;
        loops--;
    }
    return 0;
}

它尝试做的是隔离操作的时间测量。第一个循环是用于建立基线的控件,第二个循环具有任意算术运算。

然后输出到控制台。这是一个示例输出:

 c = 2116663282      | difference between 1st and 2nd loop: -8620916
 c = 112424882       | difference between 1st and 2nd loop: -1197927
 c = -1569775878     | difference between 1st and 2nd loop: -5226990
 c = 1670984684      | difference between 1st and 2nd loop: 4394706
 c = -1608171014     | difference between 1st and 2nd loop: 676683
 c = -1684897180     | difference between 1st and 2nd loop: 2868093
 c = 112418158       | difference between 1st and 2nd loop: 5846887
 c = 2019014070      | difference between 1st and 2nd loop: -951609
 c = 656490372       | difference between 1st and 2nd loop: 997815
 c = 263579698       | difference between 1st and 2nd loop: 2371088

这是非常有趣的部分:有时算术运算的循环比没有算术运算的循环(负差)完成更快。这意味着记录当前时间的操作比算术操作,因此不可忽略。

有什么方法吗?

PS:是的,我知道你可以在开始结束之间整个循环

编辑: 设置机器:i7架构,win10x64,vs2015

2 个答案:

答案 0 :(得分:2)

您的问题是您测量时间而不是处理的指令数量。时间可能会受到很多事情的影响,这些事情并不是你所期望的,或者想要衡量的。

相反,你应该测量时钟周期的数量,有一个库可以在Agner Fog的网站上找到,他有很多关于优化的有用信息:

http://www.agner.org/optimize/#manuals

即使使用时钟周期,您仍然可以在结果中遇到特殊情况,如果处理器使用Out-of-order execution使处理器能够优化操作的执行顺序,则可能会发生这种情况。

如果使用调试符号编译了代码,编译器可能会注入额外的代码,这可能会影响结果。执行这样的测试时,应始终在没有调试信息的情况下进行编译。

答案 1 :(得分:0)

你应该使用稳定的时钟 - std :: steady_clock,std :: system_clock / std :: high_resolution_clock正在被OS修正。