最近发现了rdtsc指令,可以获取CPU指令周期数,喜出望外,wiki了下相关的知识,写了代码利用CPU周期来测量程序的运行时间。
rdtsc指令返回的是自开机始CPU的周期数,返回的是一个64位的值EDX:EAX(高32在EDX,低32位在EAX)。OK,完全可以利用这条指令,测试我们的关注的一段代码的执行效率。
题外话,我兴冲冲的告诉我老大,我发现了一个测量程序性能的好办法,老大淡然的说,不会是rdtsc吧。呵呵我和老大的水平差距还是云泥之别啊。他告诉我可以去Linux Kernel查看内核是如何做的。呵呵,我就照搬了kernel的实现。兼练习以下C和汇编混合编程。
1多核,不能保证每个核的TSC是一样的。
2 CPU的时钟频率可变
3 乱序执行导致测量不准。
文献5指出,指令可能乱序执行,并给出个例子,下面的一段代码,本意是测量fdiv需要的CPU周期,但是,由于乱序执行,第二个rdtsc指令可能在fdiv之前执行,造成,无法测量fdiv的需要的CPU周期。文献给出了解决办法。有兴趣的兄弟可以去阅读参考文献5.
rdtsc ; read time stamp
mov time, eax ; move counter into variable
fdiv ; floating-point divide
rdtsc ; read time stamp
sub eax, time ; find the differenc
参考文献:
1 深入理解计算机系统
2 Linux Kernel code
3 wiki
5
- #include
- #include
- #include<linux/types.h>
-
-
#define TIMES 100
-
#define SIZE 1024
-
- __u64 rdtsc()
-
{
- __u32 lo,hi;
-
-
__asm__ __volatile__
-
(
-
"rdtsc":"=a"(lo),"=d"(hi)
-
);
-
return (__u64)hi<<32|lo;
-
}
-
-
int myfunction()
-
{
- int i;
-
char *p = NULL;
-
for(i = 0;i<TIMES;i++)
-
{
- p = (char*)malloc(SIZE*sizeof(char));
-
if(p)
- {
- free(p);
- }
-
else
-
{
- printf("malloc failed when i = %d\n",i);
-
}
-
}
-
return 0;
-
}
-
int test_rdtsc()
-
{
- __u64 begin;
-
__u64 end;
-
-
begin = rdtsc();
-
myfunction();
-
end = rdtsc();
-
printf("myfunction cost %llu CPU cycles\n",end-begin);
-
return 0;
-
}
-
-
int main()
-
{
- test_rdtsc();
-
return 0;
-
}
- root@libin:~/program/assembly/rdtsc# ./test
-
myfunction cost 310949 CPU cycles
阅读(31021) | 评论(1) | 转发(2) |