通过计算汇编指令来测量CPU速度
编辑:我最初的示例有一个愚蠢的错误。在修复它之后,我仍然得到奇怪的结果通过计算汇编指令来测量CPU速度,c,visual-c++,assembly,x86,cpu-speed,C,Visual C++,Assembly,X86,Cpu Speed,编辑:我最初的示例有一个愚蠢的错误。在修复它之后,我仍然得到奇怪的结果 我天真地试图用“暴力”的方式来衡量我的CPU速度,我编写了以下程序: #include <stdio.h> #include <stdlib.h> #include <time.h> #pragma comment(linker, "/entry:mainCRTStartup") #pragma comment(linker, "/Subsystem:Console") int ma
我天真地试图用“暴力”的方式来衡量我的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);
}
注意循环是3条指令,因此eax
的最终值应该是指令总数
为什么我在运行时会得到4.2?因为CPU速度不是以每秒字节数来衡量的,而是以每秒指令周期来衡量的,特别是在x86上,有些指令需要超过1个周期 有关指令定时,请参阅。 (实际上,这个数字只有486,仍然在为现代处理器寻找一个很好的参考)。因为它允许在一个时钟周期内执行多条指令 例如,在代码中,通过以下方式有效地消除了除最后一次
\u循环
迭代之外的所有cmp
指令:
cmp
和jb
,以及jb
分支处理器硬件总是在数据路径中寻找优化机会;编译器只是尝试组织指令以利用给定体系结构的模式。例如,硬件流水线可以在不增加IPC的情况下增加IPC,特别是对于相对自由的代码,如您的示例。一条指令执行所需的周期与它的字节大小没有直接关系。除了多个执行单元和推测性执行等现代CPU功能外,实际上不可能事先确定给定代码块需要多长时间才能准确执行。您可以使用计算CPU内部循环周期的rdtsc指令测量循环频率两个读数之间的差值是经过的循环数。让您的代码执行1000个循环,乘以3(循环中的指令),然后除以经过的周期。这将为您提供每个周期的说明。然后您可以将其扩展到您的CPU自己的频率 请记住,由于您的代码很短,它很可能从缓存级别1(或在预取器内部?)执行,这使得它仅适用于这种情况,而不适用于一般的CPU。它可能太短了,无法通过流水线实现有价值的东西
至于指令定时,似乎比AShelly建议的更为及时。它是由的定期重新计算的。RAM可以传输比CPU可以循环的更多的数据。@Lie Ryan:这如何解释为什么程序高估了他的时钟频率?我不敢相信我完全忘记了这一点(第1部分,而不是第2部分——后者会低估,而不是高估),尽管这是显而易见的!!那真是个愚蠢的错误。将3改为2使我的速度更加准确。谢谢你的回答!超过一个周期的指令会导致他的程序低估时钟频率,但实际上这是高估的。@AShelly:事实上,我不会接受这一点,因为我会在几分钟后发布一些东西,这仍然很奇怪。@AShelly:顺便说一句,你的链接断了。我认为这与管道无关,因为流水线并不会改变长期速率。但我想我明白你现在关于超标量架构的意思了。。。因此,2GHz的CPU实际上可能每秒执行4GA指令(假设内存保持不变)?是的,但与冗余功能元素(即超标量体系结构)和空间局部性相结合,编译器可以很容易地优化代码中的循环,使其执行速度比1IP快很多倍。编译器不应该对此进行优化(我没有告诉它,看起来也不像),但我认为您的推理仍然成立,因为这已经是一种优化,+1;谢谢贾斯汀:“从理论上讲,5级管道可以(大致…)给你5倍的加速(对于你幼稚的程序来说,这看起来像13.8GHz)。”这完全是胡说八道。您似乎混淆了超标量执行和管道。5级流水线将导致每个指令执行至少5个时钟(小部分)以及其他4条指令,这些指令都处于不同的执行状态。在最佳情况下,这将导致1条指令/周期。@drhirsch:我显著地更新了我的答案。。。让我知道你的想法。
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