CPU TSC fetch 操作,尤其是在多核多处理器环境中

标签 c assembly multicore cpu-registers microprocessors

在 Linux 世界中,要获得纳秒精度的计时器/时钟可以使用:

#include <sys/time.h>

int foo()
{
   timespec ts;

   clock_gettime(CLOCK_REALTIME, &ts); 
   //--snip--      
}

This answer建议 asmRDTSC直接查询cpu时钟的方法操作说明。

在多核、多处理器架构中,这个时钟滴答/定时器值如何在多个核/处理器之间同步?我的理解是,在进行固有的击剑时。这种理解是否正确?

你能推荐一些可以详细解释这一点的文档吗?我对 Intel Nehalem 和 Sandy Bridge 微架构感兴趣。

编辑

将进程限制为单个内核或 CPU 不是一种选择,因为该进程非常庞大(就消耗的资源而言),并且希望以最佳方式利用包括所有内核和处理器在内的机器中的所有资源。

编辑

感谢您确认 TSC 在内核和处理器之间同步。但我最初的问题是这种同步是如何完成的?是用某种围栏吗?你知道任何公共(public)文件吗?

结论

感谢所有输入:以下是本次讨论的结论:TSC 在初始化时使用在多处理器/多核系统中的内核和处理器之间发生的 RESET 进行同步。之后,每个核心都是独立的。 TSC 通过锁相环保持不变,该锁相环将标准化频率变化,从而标准化时钟变化 在给定的核心内 这就是 TSC 在内核和处理器之间保持同步的方式。

最佳答案

直接来自英特尔,这里解释了最近的处理器如何保持 TSC 以恒定速率滴答,在多插槽主板上的内核和封装之间同步,甚至可能在处理器进入深度 sleep C 状态时继续滴答,特别是见 Vipin Kumar EK(英特尔)的解释:

http://software.intel.com/en-us/articles/best-timing-function-for-measuring-ipp-api-timing/

这是英特尔的另一个引用文献,讨论了跨内核的 TSC 同步,在这种情况下,他们提到了 rdtscp 允许您以原子方式读取 TSC 和处理器 ID 的事实,这在跟踪应用程序时很重要……假设您想跟踪线程的执行可能会从一个内核迁移到另一个内核,如果您在两个单独的指令(非原子)中执行此操作,那么您无法确定线程在读取时钟时所在的内核。

http://software.intel.com/en-us/articles/intel-gpa-tip-cannot-sychronize-cpu-timestamps/

主板上的所有插槽/封装都接收两个外部公共(public)信号:

  • 重置
  • 引用时钟

  • 当您为主板供电时,所有插槽同时看到 RESET,所有处理器包从外部晶体振荡器接收引用时钟信号,处理器中的内部时钟保持同相(尽管通常具有高倍频,如 25x)称为锁相环 (PLL) 的电路。最新的处理器将以处理器额定的最高频率(倍频)(所谓的恒定 TSC)为 TSC 提供时钟,而不管任何单个内核可能因温度或电源管理节流(所谓的不变 TSC)而使用的倍频。 Nehalem 处理器,如 2008 年发布的 X5570(以及更新的 Intel 处理器)支持“不间断 TSC”,即使在深度断电 C 状态 (C6) 下节省电力时,它也会继续滴答作响。有关不同断电状态的更多信息,请参阅此链接:

    http://www.anandtech.com/show/2199

    经过进一步研究,我发现了英特尔于 2009 年 12 月 22 日提交的专利,该专利于 2011 年 6 月 23 日发布,题为“控制多核和线程的时间戳计数器 (TSC) 偏移量”

    http://www.freepatentsonline.com/y2011/0154090.html

    此专利申请的 Google 页面(带有指向 USPTO 页面的链接)

    http://www.google.com/patents/US20110154090

    据我所知,非核心中有一个 TSC(围绕核心的封装中的逻辑,但不是任何核心的一部分),它在每个外部总线时钟上按 Vipin Kumar 指定的机器特定寄存器字段中的值递增在上面的链接中 (MSR_PLATFORM_INFO[15:8])。外部总线时钟运行在 133.33MHz。此外,每个内核都有自己的 TSC 寄存器,由所有内核共享的时钟域计时,并且可能与任何一个内核的时钟不同 - 因此,当 RDTSC 读取内核 TSC 时,必须有某种缓冲区(或 RDTSCP)指令在内核中运行。例如,封装上的 MSR_PLATFORM_INFO[15:8] 可以设置为 25,非核心 TSC 的每个总线时钟增加 25,有一个 PLL 将总线时钟乘以 25 并将此时钟提供给每个内核以计时它们的本地 TSC 寄存器,从而保持所有 TSC 寄存器同步。因此,将术语映射到实际硬件
  • 恒定 TSC 是通过使用运行在 133.33 MHz 的外部总线时钟来实现的,该时钟乘以 MSR_PLATFORM_INFO[15:8]
  • 中指定的恒定乘法器
  • 通过将每个内核中的 TSC 保持在单独的时钟域上来实现不变 TSC
  • 不间断 TSC 是通过在每个总线时钟上通过 MSR_PLATFORM_INFO[15:8] 滴答增加一个非核心 TSC 来实现的,这样多核封装可以进入深度断电(C6 状态)并可以关闭 PLL。 .. 没有必要将时钟保持在更高的乘数。当一个内核从 C6 状态恢复时,它的内部 TSC 将被初始化为非内核 TSC(没有进入休眠的那个)的值,并进行偏移调整,以防软件向 TSC 写入一个值,详细信息在专利中。如果软件确实写入 TSC,则该内核的 TSC 将与其他内核异相,但具有恒定偏移(TSC 时钟的频率均通过恒定倍频器与总线引用时钟相关联)。
  • 关于CPU TSC fetch 操作,尤其是在多核多处理器环境中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10921210/

    相关文章:

    c - 如何在不中断的情况下停止循环

    python - 使用数据转换器将 3D 体积显示为图像

    windows - MS 加载程序将 PE 文件的哪些部分映射到内存中?

    language-agnostic - 语言翻译器 : Anything to Assembly

    c# - Windows 上可靠的短时间跨度测量

    将 unsigned int 转换为 char 字母表

    c - time.h Clock() 在 Windows 下如何工作?

    c++ - 使用多核提升协程

    c - GNU 内联汇编中的百分比 (%) 符号(C 中的 asm)

    windows - Windows XP 上 R 中的多核处理 - 通过 doMC 和 foreach