c++ - 以纳秒为单位测量精确时间 C++

标签 c++ performance profiling clock

我想测试一种方法来测量 C++ 中一段代码的精确执行时间(以纳秒为单位(精度高达 100 纳秒是可以的)。

为此,我尝试使用 chrono::high_resolution_clock。为了测试它是否正常工作。我执行以下操作:

  1. 使用 high_resolution_clock 获取以纳秒为单位的当前时间,称之为“开始”
  2. 使用 nanosleep(x) 休眠“x”纳秒
  3. 使用 high_resolution_clock 获取以纳秒为单位的当前时间,称之为“结束”
  4. 现在“结束”-“开始”应该与“x”大致相同。让我们称这种差异为“差异”

我对从 10 到 1000000 不等的 x 进行了上述测试。我得到的差异在 100000 左右,即(100 微秒)

因为这不应该超过 100 纳秒。请帮我解决这个问题。

#include <ctime>
#include <unistd.h>
#include <iostream>
#include <chrono>

using namespace std;

int main() {
    int sleep_ns[] = {10, 50, 100, 500, 1000, 2000, 5000, 10000, 20000, 50000, 100000, 200000, 500000, 1000000};
    int n = sizeof(sleep_ns)/sizeof(int);
    for (int i = 0; i < n; i++) {
        auto start = std::chrono::high_resolution_clock::now();
        timespec tspec = {0, sleep_ns[i]};
        nanosleep(&tspec, NULL);
        auto end = std::chrono::high_resolution_clock::now();
        chrono::duration<int64_t, nano> dur_ns = (end - start);
        int64_t measured_ns = dur_ns.count();
        int64_t diff = measured_ns - sleep_ns[i];
        cout << "diff: " << diff
             << " sleep_ns: " << sleep_ns[i]
             << " measured_ns: " << measured_ns << endl;
    }
    return 0;
}

以下是这段代码在我的机器上的输出。它正在运行“Ubuntu 16.04.4 LTS”

diff: 172747 sleep_ns: 10 measured_ns: 172757
diff: 165078 sleep_ns: 50 measured_ns: 165128
diff: 164669 sleep_ns: 100 measured_ns: 164769
diff: 163855 sleep_ns: 500 measured_ns: 164355
diff: 163647 sleep_ns: 1000 measured_ns: 164647
diff: 162207 sleep_ns: 2000 measured_ns: 164207
diff: 160904 sleep_ns: 5000 measured_ns: 165904
diff: 155709 sleep_ns: 10000 measured_ns: 165709
diff: 145306 sleep_ns: 20000 measured_ns: 165306
diff: 115915 sleep_ns: 50000 measured_ns: 165915
diff: 125983 sleep_ns: 100000 measured_ns: 225983
diff: 115470 sleep_ns: 200000 measured_ns: 315470
diff: 115774 sleep_ns: 500000 measured_ns: 615774
diff: 116473 sleep_ns: 1000000 measured_ns: 1116473

最佳答案

您尝试做的事情不会在每个平台上工作,甚至不会在大多数平台上工作。有几个原因。

第一个也是最大的原因是,从本质上讲,测量代码执行的精确时间是不精确的。它需要一个黑盒操作系统调用来确定,如果您首先查看过这些调用是如何实现的,那么很快就会发现该技术存在固有的不精确性。在 Windows 上,这是通过测量处理器的当前“滴答声”及其报告的频率,并将一个乘以另一个来确定两次连续调用之间经过了多少纳秒来完成的。但是 Windows 仅以微秒的精度开始报告,如果 CPU 更改其频率,即使只是适度(这在现代 CPU 中很常见,以在 CPU 未达到极限时降低频率,以节省电量)这可能会扭曲结果。

Linux 也有类似的怪癖,每个操作系统都受制于 CPU 准确报告其自身滴答计数器/滴答率的能力。

您将获得与您观察到的结果类似的第二个原因是,出于与第一个原因类似的原因,“休眠”线程通常非常不精确。 CPU 的休眠精度通常不能超过微秒精度,而且一次休眠通常不可能快于半毫秒。您的特定环境似乎至少能够达到几百微秒的精度,但显然不会比这更精确。有些环境甚至会完全降低纳秒分辨率。

总而言之,假设无需为显式实时操作系统编程,使用该操作系统的特定 API,您就可以获得您期望/想要的那种精度,这可能是错误的。如果您想要有关各个代码片段的时间的可靠信息,您需要一遍又一遍地运行所述代码,获取整个执行的样本,然后取平均值,以获得对每次运行的时间。它仍然是不精确的,但它将有助于解决这些限制。

关于c++ - 以纳秒为单位测量精确时间 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51638246/

相关文章:

linux - 内核中线程特定的单调时钟源

python - 为什么 Python 代码在函数中运行得更快?

C++ 如何将用户输入的字符串拆分为多个字符串

启用优化后,代码运行速度提高了一个数量级。我错过了什么吗?

unit-testing - 自动分析/单元测试 NHibernate 行为

java - 为什么^(?: x + y){5} $的性能比^ x + yx + yx + yx + yx + y $慢

mysql - 使用 CROSS JOIN 的超慢查询

c++ - DeferWindowPos 奇怪的行为

c++ - 使用混合 C 和 C++ 对函数的 undefined reference

c++ - 在不同类的运算符重载中访问/更改私有(private)变量的问题