如何获取高分辨率时钟的精度?

27

C++11定义了high_resolution_clock,它具有periodrep成员类型。但我无法确定如何获取该钟表的精度

如果可能的话,我是否可以通过使用period来以纳秒计算出在两个滴答之间的最小可表示时间间隔

#include <iostream>
#include <chrono>
void printPrec() {
    std::chrono::high_resolution_clock::rep x = 1;
    // this is not the correct way to initialize 'period':
    //high_resolution_clock::period y = 1;

    std::cout << "The smallest period is "
              << /* what to do with 'x' or 'y' here? */
              << " nanos\n";
}

你正在寻找 std::ratio 吗? - Yappie
@Yappie:部分正确,但接下来怎么做? - towi
2
std::ratio 基本上是用于编译时算术的编译时值。它没有实例成员,只有静态 constexpr 成员,因此“初始化”比率没有任何意义。您可以执行诸如 std::ratio_less_equal<std::milli,std::high_resolution_clock::period>::value 的操作,如果时钟周期小于或等于一毫秒,则该操作将为 true - bames53
1
只是想留个便条,@bames53 的操作数被交换了。以防有人不熟悉 std::ratio_less_equal 并且对语义产生疑问(就像我一样)。 - Crazor
3个回答

31

最小可表示的时间是 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;

为什么会这样?时钟的::period成员被定义为“时钟的滴答周期(以秒为单位)”。它是std::ratio的一个特化,用于在编译时表示比率的模板。它提供了两个整数常量:numden,分别表示分数的分子和分母。


明白了!总有一天我会学会如何找到所有“比率”隐藏的地方。 - towi

25

我对R. Martinho Fernandes的答案进行了点赞,因为我认为它提供了最清晰、最直接的答案来回答这个问题。但是我想添加一些代码,展示更多<chrono>的功能,并解决问题中的这部分:

我是否可以以纳秒计算出最小表示时间间隔的计数?

而将这么多信息放入评论中是不切实际的。但在其他方面,我认为这个答案是对R. Martinho Fernandes答案的支持性评论。

首先是代码,然后是解释:

#include <iostream>
#include <chrono>

template <class Clock>
void
display_precision()
{
    typedef std::chrono::duration<double, std::nano> NS;
    NS ns = typename Clock::duration(1);
    std::cout << ns.count() << " ns\n";
}

int main()
{
    display_precision<std::chrono::high_resolution_clock>();
    display_precision<std::chrono::system_clock>();
}

首先,我创建了一个使用 double 作为表示方式的nanosecondNS)。我使用 double 是为了在需要显示纳秒分数时(例如0.5ns)有所准备。

接下来,每个时钟都有一个嵌套类型名为duration。这是一个chrono::duration,它会具有与R. Martinho Fernandes回答中指出的相同的std::ratio,因此具有相同的numden。其中一个转换为NSduration将给出我们在Clock的一个时钟滴答中有多少纳秒。并且可以使用count()成员函数从duration中提取该值。

对于我而言,这个程序打印出:

1 ns
1000 ns

是的,你成功地提高了我对chrono的理解。 chrono::nanoseconds不适合NS?等等...我会试一下。 - towi
其实,第一次我差点就成功了:typename Clock::duration x{1}; cout << duration_cast<nanoseconds>(x).count() << " ns\n"; 我没有成功是因为我之前尝试的是 x = 1 而不是 x{1}。这是一个显式构造函数。 - towi
@towi:在显式构造函数上是正确的。这样做是为了防止意外地将标量传递给需要持续时间的函数,并且该调用的持续时间单位不是显式的。 - Howard Hinnant
2
@towi:如果chrono::nanosecondsClock::durationchrono::nanoseconds之间的精确转换,那么它将适用于NS。在我所知道的所有平台上,这都是正确的。但是,Clock::duration可能是皮秒的情况是有可能的。在这种情况下,当尝试将皮秒转换为基于整数的chrono::nanoseconds时,会导致编译时失败。但是,使用基于双精度的纳秒将导致0.001存储在ns中。 - Howard Hinnant

2

std::ratio类型代表时钟的滴答周期,以秒为单位。定义在命名空间std::chrono中。

template<intmax_t Num, intmax_t Denom = 1 > class ratio;

我必须承认,我不知道比率具体在哪里隐藏,以及如何处理它。现在明白了。 - towi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接