为什么RDTSC不是序列化指令?

问题描述 投票:23回答:4

[Intel manuals for the RDTSC instruction警告,当实际执行RDTSC时,乱序执行可能会改变,因此他们建议在其前面插入CPUID指令,因为CPUID会序列化指令流(永远不会乱序执行CPUID)。我的问题很简单:如果他们能够进行指令序列化,为什么不进行RDTSC序列化呢?它的全部目的似乎是要获得精确的周期计时。是否有一种情况,您会not想要在其前面加上序列化指令?

较新的Intel CPU具有单独的RDTSCP指令,该指令正在序列化。英特尔选择引入单独的指令,而不是改变RDTSC的行为,这向我暗示,在某些情况下,您想要的是潜在的乱序时间。这是什么?

performance x86 x86-64 cpu-architecture cpu-cycles
4个回答
11
投票

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

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

如果正确预测了分支,则增量将很小(甚至可能为负?)。如果分支预测错误,则增量将很大。

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


13
投票

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

您提供的文档中实际上已经确认,并带有以下有关Pentium和Pentium / MMX的注释(在4.2中,稍有措辞):

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

并且,来自Wikipedia

时间戳记计数器是奔腾以来所有x86处理器上都存在的64位寄存器。

:::

[从奔腾Pro开始,英特尔处理器支持乱序执行,其中指令不一定按照它们在可执行文件中出现的顺序执行。这可能导致RDTSC的执行时间比预期的晚,从而产生误导的周期计数。


RDTSCP的两种用途之一是为时间戳信息提供addition中的处理器ID(名称为Read Time-Stamp Counter *AND* Processor ID),这在跨TSC不同步的系统上非常有用芯或插座(请参阅:How to get the CPU cycle count in x86_64 from C++?)。 rdtscp的附加序列化属性使它在感兴趣区域的末端更加方便(请参阅:Is there any difference in between (rdtsc + lfence + rdtsc) and (rdtsc + rdtscp) in measuring execution time?)。


7
投票

他们为什么不对RDTSC进行序列化?它的全部目的似乎是要获得精确的周期计时]

嗯,大多数时候都是要获得高分辨率的时间戳。这些时间戳至少在某些时候用于性能指标。进行指令序列化可能需要管道刷新,这对于绑定CPU的应用程序可能非常昂贵。

[Intel选择引入单独的指令,而不是改变RDTSC的行为,这向我表明,在某些情况下,您想要的是潜在的乱序时间。

更改行为几乎总是不希望的。英特尔的客户会失望地发现RDTSC在较新的部件上有不同之处。


2
投票

[如合理解释,RDTSC早于“序列化”指令的概念,因为它是在有序CPU上实现的。稍后添加该行为将更改使用该行为的代码的内存访问行为,因此出于某些目的不兼容。

相反,较新的CPU具有相关的RDTSCP指令,该指令[定义为序列化(实际上更强:它承诺等到all条指令完成之前执行,而不仅仅是内存访问已完成正是由于这个原因。如果您在现代CPU上运行,请使用它。

© www.soinside.com 2019 - 2024. All rights reserved.