代码之家  ›  专栏  ›  技术社区  ›  Vincent

STD::时钟:硬件时钟和循环计数

  •  3
  • Vincent  · 技术社区  · 8 年前

    std::chrono 提供几个时钟来测量时间。同时,我想CPU唯一能计算时间的方法,就是计算周期。

    问题1: CPU或GPU除了计算周期之外,还有其他方法来计算时间吗?

    如果是这样的话,因为计算机计算周期的方式永远不会像原子钟那样精确,这意味着“秒”( period = std::ratio<1> )因为一台计算机实际上可以比一秒钟短或大,这就导致了计算机时钟和gps之间时间测量的长期差异。

    问题2: 是这样吗?

    一些硬件具有不同的频率(例如空闲模式和涡轮模式)。在这种情况下,这意味着循环次数在一秒钟内会发生变化。

    问题3: CPU和GPU测量的“周期计数”是否随硬件频率而变化?如果是,那么如何 STD::计时 处理好了吗?如果不是,那么周期对应什么(比如什么是“基本”时间)?是否有方法在编译时访问转换?有办法在运行时访问转换吗?

    2 回复  |  直到 8 年前
        1
  •  2
  •   Peter Cordes    7 年前

    计数周期,是的,但是 什么 ?

    在现代x86上,内核使用的时间源(内部和 clock_gettime 和其他系统调用)通常是一个固定频率计数器,它计算“参考周期”,而不考虑涡轮、节能或时钟停止空闲。(这是你的柜台 rdtsc __rdtsc() in C/C++ )

    正常的 std::chrono 实现将使用操作系统提供的函数,如 时钟时间 在UNIX上。(在Linux上,这可以纯粹在用户空间中运行,代码+比例因子数据在VDSO页面中由内核映射到每个进程的地址空间中。低开销的时间资源很好。避免用户-内核-用户往返对熔毁+幽灵缓解有很大帮助。)

    分析不受内存限制的紧循环可能需要使用实际的核心时钟周期,因此它对当前核心的实际速度不敏感。(也不必担心将CPU提高到最大涡轮等)例如使用 perf stat ./a.out perf record ./a.out . 例如 Can x86's MOV really be "free"? Why can't I reproduce this at all?


    有些系统没有/没有在cpu中内置一个与挂钟等效的计数器,所以要么操作系统在ram中保留一个时间,以便在计时器中断时更新,要么时间查询功能从单独的芯片读取时间。

    (系统调用+硬件I/O=更高的开销,这是x86 RDSTC 指令从一个分析对象转变为一个时钟源对象。)

    所有这些时钟频率最终都来自mobo上的晶体振荡器。但是,正如@tony指出的那样,从周期计数推断时间的比例因子可以调整,以保持时钟与原子时同步,通常使用网络时间协议(ntp)。

        2
  •  1
  •   Tony Delroy    8 年前

    问题1:CPU或GPU除了计算周期之外,还有其他方法来计算时间吗?

    不同的硬件可以提供不同的设施。例如,x86 PC采用了几种硬件设施来计时:在过去的十年左右,x86 CPU Time Stamp Counters 以它们的处理频率或最近的一些固定频率(即“恒定速率”或“不变”tsc)运行;可能有 High Precision Event Timer ,再往前看,有可编程中断计时器( https://en.wikipedia.org/wiki/Programmable_interval_timer )

    如果是这样,因为计算机计数周期永远不会像原子钟那样精确,这意味着计算机的“秒”(周期=STD::比率& lt;1和gt)实际上可以比实际秒短或更大,从而导致长期测量之间的差异。电脑时钟和GPS。

    是的,没有原子钟的电脑(现在有了 on a chip )不会像原子钟那样精确。也就是说,诸如 Network Time Protocol 允许您在多台计算机之间保持更紧密的一致性。

    问题3:CPU和GPU测量的“周期计数”是否随硬件频率而变化?

    那要看情况。对于tsc,较新的“恒定速率”tsc实现没有变化,其他实现也有变化。

    如果是,那么STD::如何处理它?

    我希望大多数实现调用操作系统提供的时间服务,因为操作系统往往对硬件有最好的了解和访问。有很多因素需要考虑-例如,TSC读数是否在内核之间同步,如果PC进入某种睡眠模式会发生什么,TSC采样周围需要什么样的内存栅栏……

    如果不是,那么周期对应什么(比如什么是“基本”时间)?

    对于英特尔CPU,请参阅 this answer .

    是否有方法在编译时访问转换?有办法在运行时访问转换吗?

    std::chrono::duration::count 显示所用时间源的原始计时计数,您可以 duraction_cast 其他时间单位(如秒)。预计C++ 20将引入更多类似的设备 clock_cast . 阿飞,没有 constexpr 可用的转换:如果一个程序最终运行在一台tsc速率与编译它的机器不同的机器上,似乎也有疑问。