测量时间导致返回值为0或0.001

我正在尝试使用chrono::steady_clock来测量我的程序中的一段代码之间经过的小数秒数。 我有这个代码块在LiveWorkSpace工作( http://liveworkspace.org/code/YT1I$9 ):

 #include <chrono> #include <iostream> #include <vector> int main() { auto start = std::chrono::steady_clock::now(); for (unsigned long long int i = 0; i < 10000; ++i) { std::vector<int> v(i, 1); } auto end = std::chrono::steady_clock::now(); auto difference = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count(); std::cout << "seconds since start: " << ((double)difference / 1000000); } 

当我把这个想法贯彻到我的程序中时,就像这样:

 auto start = std::chrono::steady_clock::now(); // block of code to time auto end = std::chrono::stead_clock::now(); auto difference = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() std::cout << "seconds since start: " << ((double) difference / 1000000); 

该程序将只打印出00.001值。 我非常怀疑我的代码块的执行时间总是等于01000微秒,那么这个四舍五入的计算是什么,我怎样才能消除它,以便我可以得到正确的小数值?

这是一个Windows程序。

Solutions Collecting From Web of "测量时间导致返回值为0或0.001"

在MSVC2012上运行一些测试之后,我可以确认微软实施的C ++ 11时钟没有足够高的分辨率。 请参阅C ++标头的high_resolution_clock没有关于此问题的错误报告的高分辨率 。

所以,不幸的是,对于更高分辨率的计时器,您将需要直接使用boost::chrono或QueryPerformanceCounter,直到他们修复该错误:

 #include <iostream> #include <Windows.h> int main() { LARGE_INTEGER frequency; QueryPerformanceFrequency(&frequency); LARGE_INTEGER start; QueryPerformanceCounter(&start); // Put code here to time LARGE_INTEGER end; QueryPerformanceCounter(&end); // for microseconds use 1000000.0 double interval = static_cast<double>(end.QuadPart- start.QuadPart) / frequency.QuadPart; // in seconds std::cout << interval; } 

这个问题已经有了很好的答案。 但我想补充一点建议:

<chrono>框架内工作。 建立你自己的时钟。 建立自己的时间点。 建立你自己的时间。 <chrono>框架是非常可定制的。 通过在该系统中工作,您不仅可以学习std::chrono ,而且当您的供应商开始运送您所喜欢的时钟时,将您的代码从手动滚动的chrono :: clock转换为std::high_resolution_clock (或其他)。

首先,对你原来的代码有一个小小的批评:

 std::cout << "seconds since start: " << ((double) difference / 1000000); 

每当你看到自己介绍转换常量(如1000000)得到你想要的,你没有正确使用chrono 。 你的代码是不正确的,只是脆弱的。 你确定你在那个常量中得到了正确的零个数?

即使在这个简单的例子中,你应该对自己说:

我希望看到以秒为单位的输出。

然后你应该使用chrono为你做。 一旦学习如何,这很容易:

 typedef std::chrono::duration<double> sec; sec difference = end - start; std::cout << "seconds since start: " << difference.count() << '\n'; 

第一行创建一个1秒的类型,以双精度表示。

第二行简单地减去您的time_points并将其分配给您的自定义持续时间类型。 由steady_clock::time_point单位到自定义持续时间( steady_clock::time_point的转换由steady_clock::time_point库自动完成。 这比以下简单得多:

 auto difference = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() 

然后,最后只需使用.count()成员函数打印出结果。 这又比以下简单得多:

 std::cout << "seconds since start: " << ((double) difference / 1000000); 


但是因为你对std::chrono::steady_clock的精度std::chrono::steady_clock ,而且你可以访问QueryPerformanceCounter,所以你可以做得更好。 您可以在QueryPerformanceCounter之上构建自己的时钟。

<disclaimer>

我没有Windows系统来测试下面的代码。

</disclaimer>

 struct my_clock { typedef double rep; typedef std::ratio<1> period; typedef std::chrono::duration<rep, period> duration; typedef std::chrono::time_point<my_clock> time_point; static const bool is_steady = false; static time_point now() { static const long long frequency = init_frequency(); long long t; QueryPerformanceCounter(&t); return time_point(duration(static_cast<rep>(t)/frequency)); } private: static long long init_frequency() { long long f; QueryPerformanceFrequency(&f); return f; } }; 

既然你想要你的输出是双倍的,我已经把这个时钟的rep double了1秒。 你可以很容易地做出rep积分和其他单位,如微秒或纳秒。 您只需在now()调整typedef和从QueryPerformanceCounter到您的duration的转换即可。

现在你的代码看起来很像你的原始代码:

 int main() { auto start = my_clock::now(); for (unsigned long long int i = 0; i < 10000; ++i) { std::vector<int> v(i, 1); } auto end = my_clock::now(); auto difference = end - start; std::cout << "seconds since start: " << difference.count() << '\n'; } 

但是没有手工编码的转换常数,以及(我希望的是)足够的精度满足您的需求。 并有一个更容易移植到未来的std::chrono::steady_clock实现的路径。

<chrono>被设计成一个可扩展的库。 请扩展它。 🙂