"rdtsc"之前的"cpuid"

Ale*_*x B 18 x86 assembly rdtsc

有时我会遇到使用rdtsc指令读取TSC的代码,但cpuid之前会调用.

为什么要打电话cpuid?我意识到这可能是与有TSC的值不同的内核,但什么究竟,当你调用序列这两个指令会发生什么?

pax*_*blo 18

这是为了防止无序执行.从一个现在已经从网络上消失的链接(但在它消失之前偶然复制到这里),这篇文章来自John Eckerdal的一篇题为"性能监控"的文章:

Pentium Pro和Pentium II处理器支持无序执行指令,可以在编程时以其他顺序执行.如果不加以处理,这可能是错误的来源.

为了防止这种情况,程序员必须序列化指令队列.这可以通过在RDTSC指令之前插入CPUID指令之类的序列化指令来完成.


Ton*_*roy 6

两个原因:

  • 正如paxdiablo所说,当CPU看到CPUID操作码时,它确保执行所有先前的指令,然后在执行任何后续指令之前获取CPUID.如果没有这样的指令,CPU执行流水线可能会在您想要计时的指令之前执行TSC.
  • 很大一部分机器无法跨核心同步TSC寄存器.在你想从阅读它马的嘴-自己敲出来的http://msdn.microsoft.com/en-us/library/ee417693%28VS.85%29.aspx.因此,当测量TSC读数之间的间隔时,除非它们被置于相同的核心上,否则您将有一个有效随机但可能恒定(见下文)的间隔 - 即使启动后很快也可能很快几秒(是秒) .这有效地反映了BIOS在开启其他核心之前在单个核心上运行了多长时间,另外 - 如果您有任何令人讨厌的节电选项 - 增加由于以不同频率运行的核心或再次关闭而导致的漂移.因此,如果您没有将读取TSC寄存器的线程钉在同一个内核上,那么您将需要构建某种跨核心增量表并知道每个TSC样本的核心ID(由CPUID返回)以弥补这种抵消.这是你可以在RDTSC旁边看到CPUID的另一个原因,实际上为什么在更新的RDTSCP中,许多操作系统将核心ID号存储到返回的额外TSC_AUX [31:0]数据中.(可从Core i7和Athlon 64 X2获得,RDTSCP在所有方面都是一个更好的选择 - 操作系统通常会为您提供所提到的核心ID,TSC读取的原子,防止指令重新排序).