4

我读过 RDTSC 可以给出错误的读数,不应该依赖。
这是真的吗?如果是这样,可以做些什么呢?

4

1 回答 1

7

非常旧的 CPU 有一个准确的 RDTSC。

问题

但是较新的 CPU 有问题。
工程师们认为 RDTSC 非常适合显示时间。
但是,如果 CPU 限制频率,RDTSC 就无法告诉时间。
前面提到的脑残工程师随后决定通过让 TSC 始终以相同的频率运行来“解决”这个问题,即使 CPU 速度变慢也是如此。

这具有 TSC 可用于告知经过(挂钟)时间的“优势”。然而,它使 TSC对分析没有用处

如何判断你的 CPU 没有坏

TSC_invariant您可以通过读取CPUID 中的位来判断您的 CPU 是否正常。

设置EAX为 80000007H 并读取EDX.
如果它是 0,那么你的 CPU 没问题。
如果它是 1,那么你的 CPU 坏了,你需要确保你在全速运行 CPU 时进行配置。

function IsTimerBroken: boolean;
{$ifdef CPUX86}
asm
  //Make sure RDTSC measure CPU cycles, not wall clock time.
  push ebx
  mov eax,$80000007  //Has TSC Invariant support?
  cpuid
  pop ebx
  xor eax,eax        //Assume no
  and edx,$10        //test TSC_invariant bit
  setnz al           //if set, return true, your PC is broken.
end;
{$endif}
  //Make sure RDTSC measure CPU cycles, not wall clock time.
{$ifdef CPUX64}
asm
  mov r8,rbx
  mov eax,$80000007  //TSC Invariant support?
  cpuid
  mov rbx,r8
  xor eax,eax
  and edx,$10 //test bit 8
  setnz al
end;
{$endif}

如何解决乱序执行问题

请参阅: http: //www.intel.de/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf

使用以下代码:

function RDTSC: int64;
{$IFDEF CPUX64}
asm
  {$IFDEF AllowOutOfOrder}
  rdtsc
  {$ELSE}
  rdtscp        // On x64 we can use the serializing version of RDTSC
  push rbx      // Serialize the code after, to avoid OoO sneaking in
  push rax      // later instructions before the RDTSCP runs.
  push rdx      // See: http://www.intel.de/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf
  xor eax,eax
  cpuid
  pop rdx
  pop rax
  pop rbx
  {$ENDIF}
  shl rdx,32
  or rax,rdx
  {$ELSE}
{$IFDEF CPUX86}
asm
  {$IFNDEF AllowOutOfOrder}
  xor eax,eax
  push ebx
  cpuid         // On x86 we can't assume the existance of RDTSP
  pop ebx       // so use CPUID to serialize
  {$ENDIF}
  rdtsc
  {$ELSE}
error!
{$ENDIF}
{$ENDIF}
end;

如何在损坏的 CPU 上运行 RDTSC

诀窍是强制 CPU 以 100% 运行。
这通常通过多次运行示例代码来完成。
我通常使用 1.000.000 开始。
然后,我将这 100 万次运行计时 10 倍,并采用这些尝试中最短的时间。

与理论时间的比较表明,这给出了非常准确的结果。

于 2016-03-05T20:57:04.670 回答