24

RDTSC 指令的Intel 手册警告说,当 RDTSC 实际执行时,乱序执行可能会发生变化,因此他们建议在其前面插入一条 CPUID 指令,因为 CPUID 会序列化指令流(CPUID 永远不会乱序执行)。我的问题很简单:如果他们有能力让指令序列化,为什么他们不让 RDTSC 序列化?它的全部目的似乎是获得周期准确的计时。是否存在您不想在其前面使用序列化指令的情况

较新的 Intel CPU 有一个单独的 RDTSCP 指令正在序列化。英特尔选择引入单独的指令,而不是更改 RDTSC 的行为,这向我表明,在某些情况下,您想要的可能是时序乱序。它是什么?

4

4 回答 4

12

时间戳计数器是在 Pentium 微架构上引入的。乱序执行直到 Pentium Pro 才出现。英特尔本可以进行rdtsc序列化(架构上或内部),但似乎他们决定将其保持为非序列化,这对于通用时间测量来说是可以的,并留给程序员在必要时添加序列化指令。这有利于减少测量的开销。

这实际上在您提供的文档中得到了证实,并附有以下关于 Pentium 和 Pentium/MMX 的评论(在 4.2 中,稍作解释):

第 4.1 节(Pentium Pro 和 Pentium II)中描述的所有规则和代码示例也适用于 Pentium 和 Pentium/MMX。唯一的区别是,CPUID 指令不是序列化所必需的。

而且,来自维基百科

时间戳计数器是一个 64 位寄存器,自 Pentium 以来所有 x86 处理器都存在。

: : :

从 Pentium Pro 开始,英特尔处理器支持乱序执行,其中指令不一定按照它们在可执行文件中出现的顺序执行。这可能会导致 RDTSC 的执行晚于预期,从而产生误导性的循环计数。


RDTSCP的两个用途之一是为您提供除了时间戳信息之外的处理器 ID(它就在名称中Read Time-Stamp Counter *AND* Processor ID),这在跨内核或插槽的 TSC 不同步的系统上很有用(请参阅:如何获取 CPU来自 C++ 的 x86_64 中的循环计数?)。的附加序列化属性rdtscp使其在感兴趣区域的末尾更方便(参见:在测量执行时间方面,(rdtsc + lfence + rdtsc) 和 (rdtsc + rdtscp) 之间有什么区别吗?)。

于 2012-08-22T03:00:20.220 回答
11

如果您尝试使用 rdtsc 来查看分支是否预测错误,则非序列化版本就是您想要的。

//math here
rdtsc
branch if zero to done
//do some work that always takes 1 cycle
done: rdtsc

如果分支预测正确,则增量会很小(甚至可能是负数?)。如果分支被错误预测,则增量会很大。

使用序列化版本,分支条件将得到解决,因为第一个 rdtsc 等待数学完成。

于 2012-08-23T11:09:32.490 回答
7

他们为什么不进行 RDTSC 序列化?它的重点似乎是获得周期准确的计时

好吧,大部分时间都是为了获得高分辨率的时间戳。至少在某些时候,这些时间戳用于性能指标。使指令序列化可能需要管道刷新,这对于受 CPU 限制的应用程序来说可能非常昂贵。

英特尔选择引入单独的指令,而不是更改 RDTSC 的行为,这向我表明,在某些情况下,您想要的可能是时序乱序。

改变行为几乎总是不可取的。英特尔的客户会失望地发现它RDTSC在新部件上做了不同的事情。

于 2012-08-22T02:54:38.873 回答
2

正如 paxdiably 解释的那样,RDTSC它早于“序列化”指令的概念,因为它是在有序 CPU 上实现的。稍后添加该行为会改变使用它的代码的内存访问行为,因此对于某些目的是不兼容的。

相反,最近的 CPU 有一条相关的RDTSCP指令,定义为序列化(实际上更强大:它承诺等到所有指令在它完成之前发出,而不仅仅是内存访问已经完成),正是出于这个原因。如果您在现代 CPU 上运行,请使用它。

于 2012-08-22T17:18:38.963 回答