提问者:小点点

std::chrono似乎没有提供精确的时钟分辨率/频率


我一直在读这方面的资料,但数字并不一致。在我的操作系统(Windows)上,我可以这样检查系统时钟的分辨率:

LARGE_INTEGER largeInt; // Basically a struct/union containing a long long
QueryPerformanceFrequency(&largeInt);
// largeInt now holds the frequency of my system's clock, it's 3903987
// This ends up being a resolution of about 256 nanoseconds

一切都很好,但是现在我想使用std::chrono来检查相同的细节。根据CPPreference.com和该网站上的一个流行答案,std::chrono时钟的周期是一个编译时间比,由分子和分母组成,分母指定节拍之间有多少秒。

CPPreference.com:

period:std::ratio,表示滴答周期(即每滴答秒数)

并从堆栈溢出回答:

可表示的最小持续时间为high_resolution_clock::period::num/high_resolution_clock::period::den秒。您可以这样打印它:

std::cout <<
(double)std::chrono::high_resolution_clock::period::num /   
std::chrono::high_resolution_clock::period::den;

所以我试着:

// On Windows the result is typedeffed as intmax_t, which is a typedef for a long long
    intmax_t numerator = std::chrono::high_resolution_clock::period::num;
    intmax_t denominator = std::chrono::high_resolution_clock::period::den;
    // numerator is 1 and denominator is one billion, which would suggest a 
    // tick period of one nanosecond?

根据上面的解释,我系统的时钟能够有一纳秒的分辨率?操作系统似乎不这么认为。我还尝试了其他一些工具,这些工具支持我的系统的时钟频率在3903987左右,所以我不知道它如何能够管理比这个更精细的分辨率。

虽然high_resolution_clock::is_steady结果为真,但我不确定频率是否随CPU电源设置/升压模式而变化。我重启了我的电脑两次,得到的频率计数器是3903994和3903991,所以每次开机这个数字似乎都在改变。我想在编译时计算时钟并不理想,而不是在开始运行程序时计算时钟。

那么,有没有方法通过std::chrono获得系统时钟的实际分辨率/频率呢?


共1个答案

匿名用户

null

在你的系统上,它的单位是纳秒。“滴答”不是时钟增加的单位,而是用来测量时钟时间的单位。

它不测量“处理器周期”,它测量的是纳秒。它的工作是相对一致地给你当前的时间,以纳秒为单位。

现在,如果CPU每256纳秒运行一个周期,那么对的两个调用和另一个调用的间隔不会少于这个周期(因为它们需要多个周期)。

C++不公开CPU的时钟时间。它并不是那么有用。

如果要记录两个时间点,请为您的时钟使用。如果您想要std库能够获得的最佳分辨率,请使用。如果时钟时间100%保证永不倒退,则使用(在检查其分辨率是否足够后)。

您可以将这些时间点转换为系统时钟,如果需要日历时间,则从系统时钟转换为time_t。(根据我的经验,在两个时钟之间进行转换需要您在两个时钟中有一个公共的时间点;您应该生成一次这个公共的时间点并重新使用它)

如果需要超过系统时钟允许的分辨率,可以将时间点转换为系统时钟,转换为time_t,转换回系统时钟和您的时钟,减去差值,并以纳秒为单位显示差值。

这里有一个SO答案,它做了一堆这些事情。

chrono提供的主要是一个库,使不同的时钟系统的工作变得容易和类型安全。它有持续时间和时间点,每一个时间点都带着它们的单位,所以不小心增加秒--纳秒--是不会发生的。