有时我会遇到使用rdtsc
指令读取TSC的代码,但之前会调用cpuid
。
为什么要调用cpuid
?我意识到它可能与具有TSC值的不同内核有关,但当你按顺序调用这两个指令时,完全会发生什么?
答案 0 :(得分:18)
这是为了防止无序执行。从一个现在已经从网络上消失的链接(但在它消失之前被偶然复制到这里),这篇文章来自John Eckerdal的一篇名为“性能监控”的文章:
Pentium Pro和Pentium II处理器支持无序执行指令,可以在编程时以其他顺序执行。如果不加以处理,这可能是错误的来源。
为了防止这种情况,程序员必须序列化指令队列。这可以通过在RDTSC指令之前插入CPUID指令之类的序列化指令来完成。
答案 1 :(得分:6)
有两个原因:
答案 2 :(得分:1)
CPUID正在序列化,以防止RDTSC乱序执行。
这几天,您可以放心使用LFENCE。它被记录为在Intel CPU上的指令流上进行序列化(但不存储到内存),而在针对Spectre的微代码更新后,现在也在AMD上进行序列化。
https://hadibrais.wordpress.com/2018/05/14/the-significance-of-the-x86-lfence-instruction/详细介绍了LFENCE。
另请参阅https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf,以了解使用RDTSC P 的方法,该方法可将CPUID(或LFENCE)保持在定时区域之外:
LFENCE ; (or CPUID) Don't start the timed region until everything above has executed
RDTSC ; EDX:EAX = timestamp
mov ebx, eax ; low 32 bits of start time
code under test
RDTSCP ; built-in one way barrier stops it from running early
LFENCE ; (or CPUID) still use a barrier after to prevent anything weird
sub eax, ebx ; low 32 bits of end-start
另请参阅Get CPU cycle count?,以获取有关RDTSC注意事项的更多信息,例如constant_tsc和nonstop_tsc。
作为奖励,RDTSCP为您提供了核心ID。如果要检查核心迁移,也可以使用RDTSCP作为开始时间。但是,如果您的CPU具有constant_tsc
功能,则包中的所有内核都应同步其TSC,因此在现代x86上通常不需要此功能。
正如@Tony的答案所指出的那样,您可以从CPUID中获取核心ID。