C++ 跨平台高分辨率定时器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1487695/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ Cross-Platform High-Resolution Timer
提问by Amish Programmer
I'm looking to implement a simple timer mechanism in C++. The code should work in Windows and Linux. The resolution should be as precise as possible (at least millisecond accuracy). This will be used to simply track the passage of time, not to implement any kind of event-driven design. What is the best tool to accomplish this?
我希望在 C++ 中实现一个简单的计时器机制。该代码应该适用于 Windows 和 Linux。分辨率应尽可能精确(至少毫秒精度)。这将用于简单地跟踪时间的流逝,而不是实现任何类型的事件驱动设计。实现这一目标的最佳工具是什么?
采纳答案by Josh Kelley
For C++03:
对于 C++03:
Boost.Timermight work, but it depends on the C function clockand so may not have good enough resolution for you.
Boost.Timer可能有效,但它取决于 C 函数clock,因此可能没有足够好的分辨率。
Boost.Date_Time includes a ptimeclassthat's been recommended on Stack Overflow before. See its docs on microsec_clock::local_timeand microsec_clock::universal_time, but note its caveat that "Win32 systems often do not achieve microsecond resolution via this API."
Boost.Date_Time 包含一个之前在 Stack Overflow 上推荐过的ptime类。看到它的文档上microsec_clock::local_time和microsec_clock::universal_time,但要注意它告诫说,“Win32系统往往不通过这个API达到微秒级的分辨率。”
STLsoftprovides, among other things, thin cross-platform (Windows and Linux/Unix) C++ wrappers around OS-specific APIs. Its performance libraryhas several classes that would do what you need. (To make it cross platform, pick a class like performance_counterthat exists in both the winstland unixstlnamespaces, then use whichever namespace matches your platform.)
STLsoft提供围绕操作系统特定 API 的瘦跨平台(Windows 和 Linux/Unix)C++ 包装器。它的性能库有几个类可以满足您的需求。(要使其跨平台,请选择一个performance_counter存在于winstl和unixstl命名空间中的类,然后使用与您的平台匹配的命名空间。)
For C++11 and above:
对于 C++11 及更高版本:
The std::chronolibrary has this functionality built in. See this answerby @HowardHinnant for details.
该std::chrono库内置了此功能。有关详细信息,请参阅@HowardHinnant 的这个答案。
回答by Howard Hinnant
Updated answer for an old question:
更新了一个旧问题的答案:
In C++11 you can portably get to the highest resolution timer with:
在 C++11 中,您可以通过以下方式轻松获得最高分辨率的计时器:
#include <iostream>
#include <chrono>
#include "chrono_io"
int main()
{
typedef std::chrono::high_resolution_clock Clock;
auto t1 = Clock::now();
auto t2 = Clock::now();
std::cout << t2-t1 << '\n';
}
Example output:
示例输出:
74 nanoseconds
"chrono_io" is an extension to ease I/O issues with these new types and is freely available here.
“chrono_io”是用于缓解这些新类型的 I/O 问题的扩展,可在此处免费获得。
There is also an implementation of <chrono>available in boost (might still be on tip-of-trunk, not sure it has been released).
<chrono>在 boost 中还有一个可用的实现(可能仍然在主干上,不确定它是否已经发布)。
Update
更新
This is in response to Ben's comment below that subsequent calls to std::chrono::high_resolution_clocktake several milliseconds in VS11. Below is a <chrono>-compatible workaround. However it only works on Intel hardware, you need to dip into inline assembly (syntax to do that varies with compiler), and you have to hardwire the machine's clock speed into the clock:
这是对 Ben 在下面的评论的回应,即随后的调用std::chrono::high_resolution_clock在 VS11 中需要花费几毫秒。下面是一个<chrono>兼容的解决方法。然而,它仅适用于英特尔硬件,您需要深入了解内联汇编(执行此操作的语法因编译器而异),并且您必须将机器的时钟速度硬连线到时钟中:
#include <chrono>
struct clock
{
typedef unsigned long long rep;
typedef std::ratio<1, 2800000000> period; // My machine is 2.8 GHz
typedef std::chrono::duration<rep, period> duration;
typedef std::chrono::time_point<clock> time_point;
static const bool is_steady = true;
static time_point now() noexcept
{
unsigned lo, hi;
asm volatile("rdtsc" : "=a" (lo), "=d" (hi));
return time_point(duration(static_cast<rep>(hi) << 32 | lo));
}
private:
static
unsigned
get_clock_speed()
{
int mib[] = {CTL_HW, HW_CPU_FREQ};
const std::size_t namelen = sizeof(mib)/sizeof(mib[0]);
unsigned freq;
size_t freq_len = sizeof(freq);
if (sysctl(mib, namelen, &freq, &freq_len, nullptr, 0) != 0)
return 0;
return freq;
}
static
bool
check_invariants()
{
static_assert(1 == period::num, "period must be 1/freq");
assert(get_clock_speed() == period::den);
static_assert(std::is_same<rep, duration::rep>::value,
"rep and duration::rep must be the same type");
static_assert(std::is_same<period, duration::period>::value,
"period and duration::period must be the same type");
static_assert(std::is_same<duration, time_point::duration>::value,
"duration and time_point::duration must be the same type");
return true;
}
static const bool invariants;
};
const bool clock::invariants = clock::check_invariants();
So it isn't portable. But if you want to experiment with a high resolution clock on your own intel hardware, it doesn't get finer than this. Though be forewarned, today's clock speeds can dynamically change (they aren't really a compile-time constant). And with a multiprocessor machine you can even get time stamps from different processors. But still, experiments on my hardware work fairly well. If you're stuck with millisecond resolution, this could be a workaround.
所以它不便携。但是如果你想在自己的英特尔硬件上试验高分辨率时钟,没有比这更好的了。尽管预先警告,今天的时钟速度可以动态变化(它们实际上并不是编译时常数)。使用多处理器机器,您甚至可以获得来自不同处理器的时间戳。但是,在我的硬件上进行的实验仍然运行良好。如果您坚持使用毫秒分辨率,这可能是一种解决方法。
This clock has a duration in terms of your cpu's clock speed (as you reported it). I.e. for me this clock ticks once every 1/2,800,000,000 of a second. If you want to, you can convert this to nanoseconds (for example) with:
这个时钟在你的 CPU 时钟速度方面有一个持续时间(正如你报告的那样)。即对我来说,这个时钟每 1/2,800,000,000 秒滴答一次。如果需要,您可以将其转换为纳秒(例如):
using std::chrono::nanoseconds;
using std::chrono::duration_cast;
auto t0 = clock::now();
auto t1 = clock::now();
nanoseconds ns = duration_cast<nanoseconds>(t1-t0);
The conversion will truncate fractions of a cpu cycle to form the nanosecond. Other rounding modes are possible, but that's a different topic.
转换将截断 cpu 周期的一小部分以形成纳秒。其他舍入模式也是可能的,但这是一个不同的主题。
For me this will return a duration as low as 18 clock ticks, which truncates to 6 nanoseconds.
对我来说,这将返回低至 18 个时钟滴答的持续时间,截断为 6 纳秒。
I've added some "invariant checking" to the above clock, the most important of which is checking that the clock::periodis correct for the machine. Again, this is not portable code, but if you're using this clock, you've already committed to that. The private get_clock_speed()function shown here gets the maximum cpu frequency on OS X, and that should be the same number as the constant denominator of clock::period.
我在上面的时钟中添加了一些“不变检查”,其中最重要的是检查clock::period机器是否正确。同样,这不是可移植的代码,但如果您正在使用这个时钟,那么您已经承诺了。get_clock_speed()此处显示的私有函数获取 OS X 上的最大 cpu 频率,该数字应与 的常数分母相同clock::period。
Adding this will save you a little debugging time when you port this code to your new machine and forget to update the clock::periodto the speed of your new machine. All of the checking is done either at compile-time or at program startup time. So it won't impact the performance of clock::now()in the least.
当您将此代码移植到新机器而忘记更新clock::period到新机器的速度时,添加它会为您节省一点调试时间。所有检查都在编译时或程序启动时完成。所以它clock::now()至少不会影响性能。
回答by dcw
Matthew Wilson's STLSoft librariesprovide several timer types, with congruent interfaces so you can plug-and-play. Amongst the offerings are timers that are low-cost but low-resolution, and ones that are high-resolution but have high-cost. There are also ones for measuring pre-thread times and for measuring per-process times, as well as all that measure elapsed times.
Matthew Wilson的STLSoft 库提供了多种定时器类型,具有一致的接口,因此您可以即插即用。其中包括低成本但低分辨率的计时器,以及高分辨率但成本高的计时器。还有一些用于测量线程前时间和用于测量每个进程的时间,以及所有测量经过的时间。
There's an exhaustive article covering it in Dr. Dobb'sfrom some years ago, although it only covers the Windows ones, those defined in the WinSTL sub-project. STLSoft also provides for UNIX timers in the UNIXSTL sub-project, and you can use the "PlatformSTL" one, which includes the UNIX or Windows one as appropriate, as in:
几年前,Dobb 博士的一篇详尽的文章涵盖了它,尽管它只涵盖了 WinSTL 子项目中定义的 Windows 版本。STLSoft 还在 UNIXSTL 子项目中提供了 UNIX 计时器,您可以使用“PlatformSTL”计时器,其中包括适用的 UNIX 或 Windows 计时器,如下所示:
#include <platformstl/performance/performance_counter.hpp>
#include <iostream>
int main()
{
platformstl::performance_counter c;
c.start();
for(int i = 0; i < 1000000000; ++i);
c.stop();
std::cout << "time (s): " << c.get_seconds() << std::endl;
std::cout << "time (ms): " << c.get_milliseconds() << std::endl;
std::cout << "time (us): " << c.get_microseconds() << std::endl;
}
HTH
HTH
回答by dcw
The ACE library has portable high resolution timers also.
ACE 库也有可移植的高分辨率计时器。
Doxygen for high res timer:
http://www.dre.vanderbilt.edu/Doxygen/5.7.2/html/ace/a00244.html
高分辨率计时器的 Doxygen:http:
//www.dre.vanderbilt.edu/Doxygen/5.7.2/html/ace/a00244.html
回答by Malte Clasen
The StlSoftopen source library provides a quite good timeron both windows and linux platforms. If you want it to implement on your own, just have a look at their sources.
该StlSoft开源库提供了一个相当不错的计时器在Windows和Linux平台。如果您希望它自己实现,只需查看它们的来源。
回答by Dirk Eddelbuettel
I have seen this implemented a few times as closed-source in-house solutions .... which all resorted to #ifdefsolutions around native Windows hi-res timers on the one hand and Linux kernel timers using struct timeval(see man timeradd) on the other hand.
我已经看到这作为封闭源代码的内部解决方案实现了几次......#ifdef一方面它们都求助于围绕本机 Windows 高分辨率计时器的解决方案,另一方面使用 Linux 内核计时器struct timeval(请参阅参考资料man timeradd)。
You can abstract this and a few Open Source projects have done it -- the last one I looked at was the CoinOR class CoinTimerbut there are surely more of them.
您可以将其抽象化,并且一些开源项目已经做到了——我看到的最后一个是CoinOR 类 CoinTimer,但肯定还有更多。
回答by Maciek
I highly recommend boost::posix_time library for that. It supports timers in various resolutions down to microseconds I believe
我强烈推荐 boost::posix_time 库。它支持各种分辨率的计时器,我相信可以低至微秒
回答by metamorphosis
SDL2has an excellent cross-platform high-resolution timer. If however you need sub-millisecond accuracy, I wrote a very small cross-platform timer library here. It is compatible with both C++03 and C++11/higher versions of C++.
SDL2具有出色的跨平台高分辨率计时器。但是,如果您需要亚毫秒级的精度,我在这里编写了一个非常小的跨平台计时器库。它与 C++03 和 C++11/更高版本的 C++ 兼容。
回答by JamieH
STLSofthave a Performance Library, which includes a set of timer classes, some that work for both UNIX and Windows.
STLSoft有一个Performance Library,其中包括一组计时器类,其中一些适用于 UNIX 和 Windows。
回答by jmucchiello
The first answer to C++ library questions is generally BOOST: http://www.boost.org/doc/libs/1_40_0/libs/timer/timer.htm. Does this do what you want? Probably not but it's a start.
C++ 库问题的第一个答案通常是 BOOST:http: //www.boost.org/doc/libs/1_40_0/libs/timer/timer.htm。这是你想要的吗?可能不是,但这是一个开始。
The problem is you want portable and timer functions are not universal in OSes.
问题是您想要可移植性,而计时器功能在操作系统中并不通用。

