我有一个看起来像这样的循环:
while (elapsedTime < refreshRate)
{
timer.stopTimer();
elapsedTime=timer.getElapsedTime();
}
我在其他地方读到了类似的东西(没有 100% cpu 的 C 主循环),但是这个循环正在运行一个必须准确的高分辨率计时器。那么我应该如何在保持高分辨率的同时不占用 100% 的 CPU 呢?
我有一个看起来像这样的循环:
while (elapsedTime < refreshRate)
{
timer.stopTimer();
elapsedTime=timer.getElapsedTime();
}
我在其他地方读到了类似的东西(没有 100% cpu 的 C 主循环),但是这个循环正在运行一个必须准确的高分辨率计时器。那么我应该如何在保持高分辨率的同时不占用 100% 的 CPU 呢?
你不应该忙着等待,而是让操作系统告诉你时间过去了。
http://msdn.microsoft.com/en-us/library/ms712704(VS.85).aspx
高分辨率计时器(高于 10 毫秒)
当您说您的计时器必须“准确”时,您实际上需要多准确?如果您只需要精确到最接近的毫秒,那么您可以在循环内添加半毫秒睡眠。您还可以根据剩余的睡眠时间添加动态变化的睡眠语句。想想像(伪代码)这样的东西:
int time_left = refreshRate - elapsedTime;
while (time_left > 0) {
if (time_left > threshhold)
sleep_for_interval(time_left / 2);
update_timestamp(elapsedTime);
time_left = refreshRate - elapsedTime;
}
使用该算法,如果检测到您仍有一段时间要等待,您的代码将短暂休眠。您可能需要运行一些测试以找到一个最佳值,threshhold
以平衡 CPU 使用节省与超调风险(由于您的应用程序在睡眠时丢失 CPU 并且没有及时获得更多 CPU 时间)。
高分辨率定时的另一种方法是使用触发周期性中断的硬件定时器。你的中断处理程序会向某个线程发送一个信号,它需要唤醒并做某事,之后它会回到睡眠状态并等待下一个信号进来。
实时操作系统有办法在操作系统中做这类事情。如果您正在执行 Windows 编程并且需要极其精确的计时,请注意这不是像 Windows 这样的通用操作系统可以很好地处理的事情。
查看操作系统提供的一些计时器,例如 POSIX usleep
。
另一方面,如果您需要超精度,您的代码也将无法工作,因为操作系统会在耗尽其处理时间量子并跳转到内核空间以执行一些系统任务后打破这个循环。为此,您需要一些带有可中断内核的特殊操作系统和它提供的工具;寻找 RTOS 关键字。
通常,您以某种方式屈服于操作系统。这允许操作系统从您的程序中休息并做其他事情。
显然,这取决于操作系统,但是:
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
void yield(void)
{
#ifdef _WIN32
Sleep(0);
#else
usleep(1);
#endif
}
在停止计时器之前插入对 yield 的调用。操作系统将报告您的程序使用较少的时间。
当然,请记住,这会使您的计时器“不那么准确”,因为它可能不会尽可能频繁地更新。但是你真的不应该依赖极端的准确性,这太难了。近似值没问题。