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

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

#include  int foo() { timespec ts; clock_gettime(CLOCK_REALTIME, &ts); //--snip-- } 

这个答案提出了一种使用RDTSC指令直接查询cpu时钟的asm方法。

在多核,多处理器架构中,如何在多个内核/处理器之间同步此时钟滴答/定时器值? 我的理解是,在固有的围栏中完成了。 这种理解是否正确?

你能否提出一些可以详细解释这个问题的文件? 我对Intel Nehalem和Sandy Bridge微体系结构感兴趣。

编辑

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

编辑

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

结论

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

在较新的CPU(i7 Nehalem + IIRC)上,TSC在所有内核之间同步并以恒定速率运行。 因此,对于单个处理器,或单个封装或主板(!)上的多个处理器,您可以依赖同步的TSC。

从英特尔系统手册16.12.1

较新处理器中的时间戳计数器可以支持增强,称为不变TSC。 CPUID.80000007H:EDX [8]表示处理器对不变TSC的支持。 不变的TSC将在所有ACPI P-,C-中以恒定速率运行。 和T状态。 这是未来的建筑行为。

在较旧的处理器上,您不能依赖于恒定速率或同步。

编辑:至少在单个包或主板中的多个处理器上,不变TSC是同步的。 TSC在/ RESET处复位为零,然后在每个处理器上以恒定速率向前滴答,没有漂移。 保证/ RESET信号同时到达每个处理器。

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

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

以下是英特尔讨论TSC跨内核同步的另一个参考,在这种情况下,他们提到了rdtscp允许您自动读取TSC和处理器ID的事实,这在跟踪应用程序时很重要…假设您要跟踪执行一个可能从一个核心迁移到另一个核心的线程,如果你在两个单独的指令(非primefaces)中执行,那么你就不能确定线程在读取时钟时所处的核心。

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

主板上的所有sockets/封装都会收到两个外部公共信号:

  1. 重启
  2. 参考时钟

当您为主板供电时,所有sockets都会同时看到RESET,所有处理器封装都从外部晶体振荡器接收参考时钟信号,并且处理器中的内部时钟保持同相(尽管通常具有高倍数,如25倍)称为锁相环(PLL)的电路。 最近的处理器将以处理器额定的最高频率(乘数)为TSC提供时钟(所谓的恒定TSC),而不管任何单个核心由于温度或功率管理限制而使用的乘数(所谓的不变TSC)。 像2008年发布的X5570(以及更新的英特尔处理器)这样的Nehalem处理器支持“不间断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
  • 通过在每个总线时钟上增加MSR_PLATFORM_INFO [15:8]滴答的非核TSC来实现不间断TSC,这样多核封装可以进入深度掉电(C6状态)并且可以关闭PLL。 ..没有必要在更高的乘数上保持时钟。 当核心从C6状态恢复时,其内部TSC将被初始化为非核心TSC(未进入hibernate状态)的值,并且在软件已向TSC写入值的情况下进行偏移调整,详细信息如下:这是专利中的。 如果软件写入TSC,则该内核的TSC将与其他内核异相,但处于恒定偏移(TSC时钟的频率全部通过常数乘法器与总线参考时钟相关联)。

RTDSC不在CPU之间同步。 因此,您不能在多处理器系统中依赖它。 我能想到的唯一可行的解​​决方法是通过设置其亲和性来实际限制进程在单个CPU上运行。 这可以使用taskset实用程序在外部完成,或使用sched_setaffinity或pthread_setaffinity_np函数在“内部”完成。

本手册第17.12章描述了最新处理器中使用的不变TSC。 与Nehalem一起提供此时间戳以及rtscp指令,允许用户在一次primefaces操作中读取时间戳(不受等待状态等影响)和处理器签名。

据说它适用于计算挂钟时间,但显然不希望处理器之间的值相同。 陈述的想法是,您可以查看连续读取是否属于同一CPU的时钟,还是调整多个CPU读取。 “它还可用于调整NUMA系统中每个CPU的TSC值差异。”

另请参阅CPU内核的rdtsc精度

但是,我不确定接受的答案中的最终一致性结论是否来自tsc可用于挂钟时间的说法。 如果它是一致的,那么有什么理由可以primefaces地确定时间的CPU源。

注意:在英特尔手册中,TSC信息已从第11章移至第17章。