rdtsc命令でクロック計測

負荷の高い通信アプリケーションの時間計測になるべくCPU負荷にならない方法を考えていて、Pentium とかで使えるrdtsc命令を使う方法を検討していて、
とりあえず、インラインアセンブラを思い出すためにCPUの動作クロック計測プログラムを作ってみました。

#include
#include
#include

unsigned int g_begin_h;
unsigned int g_begin_l;
unsigned int g_end_h;
unsigned int g_end_l;

int
main(int argc, char *argv[])
{
unsigned long long int begin, end, usec1, usec2;
double clock;
struct timeval tv;

asm ("rdtsc");
asm ("movl %edx, _g_begin_h");
asm ("movl %eax, _g_begin_l");

(void) gettimeofday(&tv, NULL);
usec2 = tv.tv_sec * 1000 * 1000 + tv.tv_usec;
for (;;) {
(void) gettimeofday(&tv, NULL);
usec1 = tv.tv_sec * 1000 * 1000 + tv.tv_usec;
if (usec2 + 1000 * 1000 < usec1)
break;
}

asm ("rdtsc");
asm ("movl %edx, _g_end_h");
asm ("movl %eax, _g_end_l");

begin = g_begin_h;
begin = begin << 32;
begin |= g_begin_l;

end = g_end_h;
end = end << 32;
end |= g_end_l;

clock = (double) (end - begin) / 1;

(void) printf("clock = %.2f MHz\n", clock / 1000000);

return (0);
}


# gcc -m32 rdtsc.c -o rdtcs;./rdtcs
clock = 2194.52 MHz
それっぽい数字がでます。

(void) gettimeofday(&tv, NULL);
usec2 = tv.tv_sec * 1000 * 1000 + tv.tv_usec;
for (;;) {
(void) gettimeofday(&tv, NULL);
usec1 = tv.tv_sec * 1000 * 1000 + tv.tv_usec;
if (usec2 + 1000 * 1000 < usec1)
break;
}

はスマートじゃないですが、sleep(1)とかすると、その間CPUのクロックが下がって正確な値にならないため、ぐるぐるまわるようにしています。

本当は誤差を少なくするコードとか必要ですが、お遊びとしてはこんなもんでいいのではないでしょうか。