Ami*_*mer 69 c++ cross-platform timer
我想在C++中实现一个简单的计时器机制.该代码应该适用于Windows和Linux.分辨率应尽可能精确(至少精确到毫秒).这将用于简单地跟踪时间的流逝,而不是实现任何类型的事件驱动设计.完成此任务的最佳工具是什么?
How*_*ant 141
更新旧问题的答案:
在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';
}
Run Code Online (Sandbox Code Playgroud)
示例输出:
74 nanoseconds
Run Code Online (Sandbox Code Playgroud)
"chrono_io"是用这些新类型缓解I/O问题的扩展,可在此处免费获取.
还有一个<chrono>
可用于boost 的实现(可能仍然在主干上,不确定它是否已被释放).
更新
这是对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();
Run Code Online (Sandbox Code Playgroud)
所以它不便携.但是如果你想在自己的英特尔硬件上试验高分辨率时钟,它就不会比这更好.虽然预先警告,但今天的时钟速度可以动态变化(它们实际上不是编译时常量).使用多处理器机器,您甚至可以从不同的处理器获取时间戳.但是,我的硬件实验仍然相当不错.如果你坚持毫秒级分辨率,这可能是一种解决方法.
这个时钟在你的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);
Run Code Online (Sandbox Code Playgroud)
转换将截断cpu周期的分数以形成纳秒.其他舍入模式也是可能的,但这是一个不同的主题.
对我来说,这将返回一个低至18个时钟周期的持续时间,截止为6纳秒.
我在上面的时钟中添加了一些"不变检查",其中最重要的是检查clock::period
机器是否正确.同样,这不是可移植的代码,但如果你使用这个时钟,你已经承诺了.get_clock_speed()
此处显示的私有函数获取OS X上的最大cpu频率,该值应与常量分母相同clock::period
.
当您将此代码移植到新计算机并忘记更新clock::period
到新计算机的速度时,添加此项将节省一些调试时间.所有检查都在编译时或程序启动时完成.所以它不会影响性能clock::now()
.
Jos*_*ley 40
对于C++ 03:
Boost.Timer可能会起作用,但它取决于C函数clock
,因此可能没有足够好的分辨率.
Boost.Date_Time包含之前在Stack Overflow上推荐的ptime
类.看到它的文档上microsec_clock::local_time
和microsec_clock::universal_time
,但要注意它告诫说,"Win32系统往往不通过这个API达到微秒级的分辨率."
除了其他功能之外,STLsoft还提供围绕特定于操作系统的API的瘦跨平台(Windows和Linux/Unix)C++包装器.它的性能库有几个类可以满足您的需求.(为了使它跨平台,选择类似于和名称空间performance_counter
中存在的类,然后使用与您的平台匹配的任何名称空间.)winstl
unixstl
对于C++ 11及更高版本:
该std::chrono
库内置了此功能.有关详细信息,请参阅@HowardHinnant的回答.
Matthew Wilson的STLSoft库提供了几种定时器类型,具有一致的接口,因此您可以即插即用.其中包括低成本但低分辨率的定时器,以及高分辨率但成本高的定时器.还有一些用于测量预螺纹时间和测量每个工艺时间,以及测量经过时间的所有时间.
几年前在Dobb博士的文章中有一篇详尽的文章,虽然它只涉及Windows,即WinSTL子项目中定义的那些.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;
}
Run Code Online (Sandbox Code Playgroud)
HTH
小智 5
ACE库还具有便携式高分辨率计时器.
用于高分辨率计时器的Doxygen:http:
//www.dre.vanderbilt.edu/Doxygen/5.7.2/html/ace/a00244.html
归档时间: |
|
查看次数: |
66419 次 |
最近记录: |