std::chrono
宣称它可以报告低至纳秒级别的结果。在典型的 x86_64 Linux 或 Windows 计算机上,人们期望该值的准确度如何?例如,测量 10 ns、10 µs、10 ms 和 10 s 时的误差线是多少?
这很可能取决于硬件和操作系统。例如,当我使用 QueryPerformanceFrequency() 询问 Windows 时钟频率是多少时,我得到 3903987,如果取其倒数,则得到大约 256 纳秒的时钟周期或分辨率。这是我的操作系统报告的值。
根据文档,使用 std::chrono 时,最小可表示持续时间为 high_resolution_clock::period::num / high_resolution_clock::period::den。
num 和 den 是分子和分母。 std::chrono::high_resolution_clock 告诉我分子是 1,分母是 10 亿,据说对应于 1 纳秒:
std::cout << (double)std::chrono::high_resolution_clock::period::num /
std::chrono::high_resolution_clock::period::den; // Results in a nanosecond.
因此,根据 std::chrono 我有一纳秒分辨率,但我不相信它,因为本机操作系统系统调用更有可能报告更准确的频率/周期。
准确性将取决于应用程序以及该应用程序与操作系统的交互方式。我对计时并不熟悉,但您必须考虑较低级别的限制。
例如,如果使用 CPU 对网络数据包添加时间戳,则测量精度的噪声非常大。尽管时间测量的精度可能是 1 纳秒,但与数据包到达相对应的中断的上下文切换时间可能约为 1 微秒。您可以准确测量应用程序处理数据包的时间,但无法测量数据包到达的时间。
准确性取决于实现,据我所知,没有标准 API 来查询它。但是,您可以大致如下测量(godbolt):
#include <chrono>
#include <iostream>
int main(int argc, char *argv[]) {
const int num_measurements = 100;
using clock = std::chrono::steady_clock;
clock::time_point measurements[num_measurements];
for (int i = 0; i < num_measurements; ++i) {
measurements[i] = clock::now();
}
auto min_duration = clock::duration::max();
for (int i = 1; i < num_measurements; ++i) {
auto duration = measurements[i] - measurements[i - 1];
if (duration != clock::duration() && duration < min_duration)
min_duration = duration;
}
std::cout << min_duration;
}
在 godbolt 使用的 libstdc++ 和 Linux 上,这大约需要 20ns。
在 libc++ 和 macOS 上,这大约需要 41ns。
长答案:
我很想知道我的两个 dp 程序需要多少时间来执行。所以我使用了 chrono 库,但是当我运行它时它显示 0 微秒。所以从技术上来说我无法比较。我无法增加数组大小,因为不可能将其扩展到 1e8。
所以我写了一个排序程序来测试它并运行了100,结果如下:
很明显,对于相同的输入,它并不一致,所以我建议不要使用更高的精度。