考虑以下代码:
#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
答案 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修正。