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

Jay*_*y D 14 c assembly multicore cpu-registers microprocessors

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

#include <sys/time.h>

int foo()
{
   timespec ts;

   clock_gettime(CLOCK_REALTIME, &ts); 
   //--snip--      
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

编辑

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

编辑

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

结论

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

amd*_*mdn 23

直接来自英特尔,这里解释了最近的处理器如何维持恒定速率的TSC,在多插槽主板上的内核和封装之间是同步的,甚至可能在处理器进入深度睡眠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/

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

  1. 重启
  2. 参考时钟

当您为主板供电时,所有插座都会同时看到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将初始化为非核心TSC(未进入休眠状态)的值,并进行偏移调整,详细信息如下:这是专利中的.如果软件写入TSC,那么该内核的TSC将与其他内核异相,但处于恒定偏移(TSC时钟的频率全部通过常数乘法器与总线参考时钟相关联).


Gun*_*iez 16

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

从英特尔系统手册16.12.1

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

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

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

  • 请注意,它仅适用于英特尔处理器。我已经有一段时间没有对 AMD 进行任何测试(我测试的最新 AMD CPU 是 IIRC,Phenom II),但当时它们甚至没有在单个芯片中的内核之间进行同步。 (2认同)

小智 5

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


小智 5

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

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

另请参阅CPU内核的rdtsc精度

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

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