10

编辑:我原来的例子有一个愚蠢的错误。不过,修复它后,我仍然得到奇怪的结果。


在我天真的尝试以“蛮力”方式测量我的 CPU 速度时,我制作了以下程序:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#pragma comment(linker, "/entry:mainCRTStartup")
#pragma comment(linker, "/Subsystem:Console")

int mainCRTStartup()
{
    char buf[20];
    clock_t start, elapsed;
    unsigned long count = 0;
    start = clock();
    __asm
    {
        mov EAX, 0;
    _loop:
        add EAX, 3; // accounts for itself and next 2 instructions
        cmp EAX, 0xFFFFFFFF - 0x400;
        jb _loop;
        mov count, EAX;
    }
    elapsed = clock() - start;
    _gcvt(count * (long long)CLOCKS_PER_SEC / (elapsed * 1000000000.0), 3, buf);
    puts(buf);
}

分解成类似的东西:

mainCRTStartup:
  push   ebp
  mov    ebp,esp
  sub    esp,28h
  mov    dword ptr [count],0
  call   dword ptr [_clock]
  mov    dword ptr [start],eax
  mov    eax,0

_loop:
  add    eax,03h
  cmp    eax,0FFFFFBFFh
  jb     _loop

  mov    dword ptr [count],eax
  call   dword ptr [_clock]
  sub    eax,dword ptr [start]

  ...    // call _gcvt, _puts, etc.

  mov    esp,ebp
  pop    ebp
  ret

请注意,循环是 3 条指令,因此 的最终值eax应该是指令的总数。

为什么我运行它时会得到 4.2?

4

4 回答 4

12

因为指令级并行超标量架构允许在单个流水线时钟周期内执行多条指令。

例如,在您的代码中,分支预测通过以下方式 有效地消除了除最后一次迭代cmp之外的所有指令:_loop

  1. 并行执行,cmp并且jb
  2. 总是拿jb树枝。

当然,(2) 在最后一次迭代中被抛出,导致管道被清除。额外的约 20 个周期(对于 20 级流水线)可以忽略不计,因为您的循环大约是 10^9 条指令。

编译器不应该对此进行优化

处理器硬件总是在数据路径中寻找优化机会;编译器只是尝试组织指令以利用给定架构的模式。例如,硬件流水线可以在没有软件流水线的情况下增加 IPC ,尤其是对于相对无风险的代码,例如您的示例。

于 2011-08-10T03:47:52.980 回答
9

因为 CPU 速度不是以每秒字节数来衡量的,而是以每秒指令周期数来衡量的,尤其是在 x86 上,一些指令需要超过 1 个周期。

有关指令时序,请参见此页面。(实际上,这仅上升到 486 - 仍在为现代处理器寻找一个很好的参考)。

于 2011-08-10T03:42:09.633 回答
2

一条指令执行多少个周期与它的字节大小没有直接关系。除了现代 CPU 功能(如多个执行单元和推测执行)之外,实际上不可能事先确定给定的代码块需要多长时间才能准确执行。

于 2011-08-10T03:49:11.877 回答
1

您可以使用rdtsc指令测量循环,该指令计算 CPU 内部频率的周期。两个读数之间的差异是经过的周期数。让您的代码执行 1000 个循环,乘以 3(循环中的指令)并除以经过的循环。这将为您提供每个周期的说明。然后您可以将其扩展到您的 CPU 自己的频率。

请记住,由于您的代码很短,它很可能会从缓存级别 1(或在预取器内部?)执行,这使得它仅适用于这种情况,而不适用于一般的 CPU。对于流水线来说,它可能太短而无法做出有价值的事情。

至于指令时间,这个页面似乎比 AShelly 建议的更新。它由瑞典皇家理工学院的Torbjörn Granlund定期重新计算。

于 2011-08-11T08:01:01.247 回答