c ++ while循环计时器的准确性变化很大

Posted

技术标签:

【中文标题】c ++ while循环计时器的准确性变化很大【英文标题】:c++ while loop timer varying wildly in accuracy 【发布时间】:2019-04-23 19:24:39 【问题描述】:

我正在尝试使用 while 循环来创建一个持续测量 3000μs (3 ms) 的计时器,虽然它大部分时间都在工作,但其他时候计时器可能会延迟多达 500μs。为什么会发生这种情况,有没有更精确的方法来制作这样的计时器?

int getTime() 
    chrono::microseconds μs = chrono::duration_cast< chrono::microseconds >(
        chrono::system_clock::now().time_since_epoch() //Get time since last epoch in μs
        );
    return μs.count(); //Return as integer


int main()

    int target = 3000, difference = 0;
    while (true) 
        int start = getTime(), time = start;
        while ((time-start) < target) 
            time = getTime();
        
        difference = time - start;
        if (difference - target > 1)  //If the timer wasn't accurate to within 1μs
            cout << "Timer missed the mark by " + to_string(difference - target) + " microseconds" << endl; //Log the delay
        
    
    return 0;

我希望这段代码记录的延迟始终在 5 微秒左右,但 the console output looks like this。

编辑澄清:我在 Windows 10 Enterprise Build 16299 上运行,但该行为在 Debian 虚拟机上仍然存在。

【问题讨论】:

您在 RTOS 上运行吗?如果没有,不要期待任何事情。 Windows 10 Enterprise Build 16299,尽管该行为在 Debian 虚拟机上仍然存在。 在多任务操作系统上,当您的应用程序运行像这样的无限循环并且永不休眠时,操作系统可能会任意将其暂停以给其他进程一个时间片。这可能是一个原因。 What is the best, most accurate timer in C++?的可能重复 ***.com/q/37444594/2785528 的可能重复项。另请参阅我在***.com/a/37445086/2785528 的回答。 【参考方案1】:

您还需要考虑其他正在运行的进程。操作系统可能会抢占您的进程以将 CPU 时间分配给其他进程/线程,并且会不确定地将控制权返回给运行此计时器的进程/线程。

当然,当我们考虑实时操作系统或平面调度程序时,这并不是 100% 正确的。但如果您在通用机器上运行,您的代码中可能会出现这种情况。

【讨论】:

所以这是在 Windows 上运行我的代码的问题,而不是我的代码的问题? 几乎,实时操作系统意味着您可以拥有确定性的性能,而 Windows 绝对不是其中之一。没有操作系统的微处理器是我知道的唯一可以在几个时钟周期内保证准确性的地方。机器人的 ROS 和其他一些 linux 变体可能会让您不到一微秒,但不确定它们的准确度下限是什么,超过没有操作系统。 请注意,ROS 本身并不是一个操作系统,而是一个元操作系统。它的调度器也与 OS 调度器并行运行。【参考方案2】:

由于您在 Windows 上运行,RTOS 负责通过 NTP 保持时间,因为 C++ 没有内置函数。查看SetTimer() 函数的此 Windows API:http://msdn.microsoft.com/en-us/library/ms644906(v=vs.85).aspx。

如果您想通过 C++ 获得最佳和最高分辨率的时钟,请查看 chrono 库:

#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';

【讨论】:

使用 Lubuntu 18.04、g++ 7.3.0 在我的旧戴尔上进行的测量:每次“时间(nullptr)”事件需要 3.95 秒;每个 'Posix clock_gettime (CLOCK_REALTIME, &ts);' 1.288 µ 秒事件;每个“HRClk_t:now()”事件需要 1.382 µ 秒。 chrono high-resolution-clock 并不比 'Posix clock' 慢太多。 如果您使用的是 Ubuntu,请记住,由于内核进程不同,时间的计算速度与 Windows 不同。 Posix 仅适用于 Linux,与 chrono 不同,在 Windows 上不受支持。您还会遇到 Posix 的 2038 年问题。

以上是关于c ++ while循环计时器的准确性变化很大的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C(Linux)中的 while 循环中准确睡眠?

使用 sleep() 函数作为带有 while 循环的计时器不起作用?

为啥while循环的执行速度会随时间变化?

C#使用while循环将项添加到List [关闭]

C++ / Qt 减少循环频率

C语音while循环语句的用法