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

Jos*_*vin 23 performance x86 x86-64 cpu-cycles cpu-architecture

英特尔手册的RDTSC指令警告说,当实际执行RDTSC乱序执行可以改变,所以他们建议将在它前面的CPUID指令,因为CPUID将序列指令流(CPUID是永远不会乱序执行).我的问题很简单:如果他们有能力进行序列化指令,他们为什么不进行RDTSC序列化?它的全部要点似乎是获得周期精确的时间.是否存在一种情况,您希望在它之前加上序列化指令?

较新的Intel CPU具有单独的序列化RDTSCP指令.英特尔选择引入一个单独的指令,而不是改变RDTSC的行为,这表明我必须存在一些可能出现故障时序的情况.它是什么?

pax*_*blo 12

因为时间戳计数器是从内存中引入的Pentium.

在Pentium Pro之前没有出现乱序执行,此时改变指令所做的为时已晚.

这实际上已经在您提供的文档中被证实(钝),以及关于Pentium和Pentium/MMX的以下评论(在4.2中,略有释义):

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

并且,来自维基百科:

自Pentium以来,时间戳计数器是所有x86处理器上的64位寄存器.

:::

从Pentium Pro开始,Intel处理器支持无序执行,其中指令不一定按它们在可执行文件中出现的顺序执行.这可能导致RDTSC执行得比预期的要晚,从而产生误导性的循环计数.


而且,据我所知,RDTSCP(从i7开始)的主要用途是为您提供处理器ID,因为每个处理器都维护着一个独立的TSC.它很可能是序列化的,但我发现更多的是一个简单的"bug修复"而不是旧的指令.

  • @Joseph,我想你误解了我所说的确认的内容.我并没有说明他们所做的是正确的,只是时间戳计数器和OOO执行的时间表得到了该文件的确认.事实上,我相信他们所做的是错误的,因为他们对RDTSC的行为进行了回归 - 它在早期的处理器上工作而不是在后者上工作.我怀疑有人没有考虑到OOOE,直到为时已晚,但这只是我的假设. (3认同)
  • 英特尔?犯了一个错误?没有机会。就像 4195835 除以 3145727 等于 1.333739068902037589 一样,它们是绝对可靠的。Foof,我很惊讶你会认为这是可能的:-) (2认同)

Dan*_*nny 11

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

//math here
rdtsc
branch if zero to done
//do some work that always takes 1 cycle
done: rdtsc
Run Code Online (Sandbox Code Playgroud)

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

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


Bri*_*ain 7

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

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

英特尔选择引入一个单独的指令,而不是改变RDTSC的行为,这表明我必须存在一些可能出现故障时序的情况.

改变行为几乎总是不可取的.英特尔的客户会发现RDTSC在新零件上有所不同,会感到失望.

  • 实际上,他们已经习惯了.当从Pentium切换到Pentium Pro时,行为发生了变化 - 它在没有序列化的情况下停止提供有用的结果:-)但是你不对它是不合适的. (3认同)