实现高分辨率计时器的最佳方法

Best way to implement a high resolution timer

本文关键字:最佳 方法 计时器 高分辨率 实现      更新时间:2023-10-16

在 C++11 中实现高分辨率计时器的最佳方法是什么,该计时器连续检查循环中的时间,并在经过某个时间点后执行一些代码? 例如,从上午 9 点开始检查它在循环中的时间,并在上午 11 点准确执行一些代码。我要求时间精确(即上午 9 点后不超过 1 微秒(。

我将在 Linux CentOS 7.3 上实现此程序,并且将 CPU 资源用于执行此任务没有任何问题。

您可以使用例如systemd.timer代替手动实现它。确保指定所需的精度,该精度显然可以精确到1us。

一个

高分辨率计时器,可以连续检查循环中的时间,

首先,你不想在一个循环中连续检查时间;这是非常低效的,而且完全没有必要。

。在经过某个时间点后执行一些代码?

好的,所以您希望在将来的给定时间尽可能准确地运行一些代码。

最简单的方法是简单地启动后台线程,计算距离目标时间(以所需分辨率(的时间,然后将线程置于该时间段的睡眠状态。当线程唤醒时,它会执行实际任务。这应该足够准确,可以满足绝大多数需求。

std::chrono库提供的调用使这变得简单:

  • 系统时钟输入std::chrono
  • 高分辨率时钟输入std::chrono

下面是一段代码,它使用系统时钟执行您想要的操作(这样可以更轻松地设置挂钟时间(:

// c++ --std=c++11 ans.cpp -o ans
#include <thread>
#include <iostream>
#include <iomanip>
// do some busy work
int work(int count)
{
int sum = 0;
for (unsigned i = 0; i < count; i++)
{
sum += i;
}    
return sum;
}
std::chrono::system_clock::time_point make_scheduled_time (int yyyy, int mm, int dd, int HH, int MM, int SS)
{
tm datetime = tm{};
datetime.tm_year = yyyy - 1900; // Year since 1900
datetime.tm_mon = mm - 1; // Month since January
datetime.tm_mday = dd; // Day of the month [1-31]
datetime.tm_hour = HH; // Hour of the day [00-23]
datetime.tm_min = MM;
datetime.tm_sec = SS;
time_t ttime_t = mktime(&datetime);
std::chrono::system_clock::time_point scheduled = std::chrono::system_clock::from_time_t(ttime_t);
return scheduled;
}
void do_work_at_scheduled_time()
{
using period = std::chrono::system_clock::period;
auto sched_start = make_scheduled_time(2019, 9, 17,  // date
00, 14, 00);  // time
// Wait until the scheduled time to actually do the work
std::this_thread::sleep_until(sched_start);
// Figoure out how close to scheduled time we actually awoke
auto actual_start = std::chrono::system_clock::now();
auto start_delta = actual_start - sched_start;
float delta_ms = float(start_delta.count())*period::num/period::den * 1e3f;
std::cout << "worker: awoken within " << delta_ms << " ms" << std::endl;
// Now do some actual work!
int sum = work(12345);
}
int main()
{
std::thread worker(do_work_at_scheduled_time);
worker.join();
return 0;
}

在我的笔记本电脑上,典型的延迟约为 2-3 毫秒。如果您使用high_resolution_clock,您应该能够获得更好的结果。

您还可以使用其他API,例如Boost,您可以在其中使用ASIO来实现高分辨率超时。

我要求时间精确(即上午 9 点后不超过 1 微秒(。

真的需要它精确到微秒吗?考虑到在此分辨率下,您还需要考虑各种其他因素,包括系统负载、延迟、时钟抖动等。您的代码可以在接近该时间开始执行,但这只是问题的一部分。

我的建议是使用 timer_create((。这允许您在给定时间收到信号通知。然后,您可以在信号处理程序中实现您的操作。

在任何情况下,您都应该知道,准确性当然取决于系统时钟的准确性。