英特尔的时间戳读取asm代码示例是否使用了两个以上的寄存器?

Edd*_*ett 8 c benchmarking assembly inline-assembly rdtsc

我正在研究使用x86 CPU中的时间戳寄存器(TSR)来测量基准性能.它是一个有用的寄存器,因为它以单调时间单位测量,不受时钟速度变化的影响.很酷.

这是一份英特尔文档,显示了使用TSR进行可靠基准测试的asm片段,包括使用cpuid进行管道同步.见第16页:

http://www.intel.com/content/www/us/en/embedded/training/ia-32-ia-64-benchmark-code-execution-paper.html

要读取开始时间,它说(我注释了一下):

__asm volatile (
    "cpuid\n\t"             // writes e[abcd]x
    "rdtsc\n\t"             // writes edx, eax
    "mov %%edx, %0\n\t" 
    "mov %%eax, %1\n\t"
    //
    :"=r" (cycles_high), "=r" (cycles_low)  // outputs
    :                                       // inputs
    :"%rax", "%rbx", "%rcx", "%rdx");       // clobber
Run Code Online (Sandbox Code Playgroud)

我不知道为什么暂存寄存器用来取的价值观edxeax.为什么不删除MOVS和读取TSR值右出的edxeax?像这样:

__asm volatile(                                                             
    "cpuid\n\t"
    "rdtsc\n\t"
    //
    : "=d" (cycles_high), "=a" (cycles_low) // outputs
    :                                       // inputs
    : "%rbx", "%rcx");                      // clobber     
Run Code Online (Sandbox Code Playgroud)

通过这样做,您可以保存两个寄存器,从而降低C编译器需要溢出的可能性.

我对吗?或者那些MOV在某种程度上是战略性的?

(我同意你确实需要临时寄存器来读取停止时间,因为在那种情况下指令的顺序是相反的:你有rdtscp,...,cpuid.cpuid指令破坏了rdtscp的结果).

谢谢

Pet*_*des 6

你是对的,这个例子很笨重. 通常if mov是inline-asm语句中的第一个或最后一个指令,你做错了,并且应该使用约束来告诉编译器你想要输入的位置,或输出的位置.

请参阅我的GNU C内联asm指南/链接集合,以及标记wiki 中的其他链接.(对于asm来说,标签wiki也充满了好东西.)


或者rdtsc具体来说,请参阅获取CPU周期数?对于__rdtsc()@ Mysticial的答案中的内在和良好的内联asm.


它以单调时间单位测量,不受时钟速度变化的影响.

是的,在过去10年左右的CPU上.

对于分析,在核心时钟周期中有时间而不是挂钟时间通常更有用,因此您的微基准测试结果不依赖于省电/ turbo. 性能计数器可以做到这一点以及更多.

尽管如此,如果实时是你想要的,rdtsc那么它是获得它的最低开销方式.


并且重新:评论中的讨论:是的cpuid是序列化,确保rdtsc在CPUID之后直到指令才能开始执行.您可以在RDTSC之后添加另一个CPUID,但这会增加测量开销,我认为在准确度/精度方面会给出接近零的增益.

LFENCE是一种更便宜的替代品,对RDTSC很有用.该指令裁判手动输入文档的事实,它不会让后面的指令开始执行,直到它和以前的指令已退休(从ROB /核心的乱序部分RS).请参阅是否加载并存储重新排序的唯一指令?,并且对于使用它的具体示例,请参阅clflush以通过C函数使高速缓存行无效.与真正的序列化指令不同cpuid,它不会刷新存储缓冲区.

(在最近的AMD的CPU没有幽灵缓解启用,lfence甚至不是部分序列化,并在4运行每个时钟根据昂纳雾的测试. 是LFENCE序列化的AMD处理器?)

玛格丽特布鲁姆挖出了这个有用的链接,这也证实了LFENCE根据英特尔的SDM序列化RDTSC,还有一些关于如何围绕RDTSC进行序列化的东西.