高解像度と移植性を備えたコード セクションのタイミングを計る最良の方法は何ですか?
/* Time from here */
ProcessIntenseFunction();
/* to here. */
printf("Time taken %d seconds %d milliseconds", sec, msec);
クロスプラットフォーム ソリューションを持つ標準ライブラリはありますか?
高解像度と移植性を備えたコード セクションのタイミングを計る最良の方法は何ですか?
/* Time from here */
ProcessIntenseFunction();
/* to here. */
printf("Time taken %d seconds %d milliseconds", sec, msec);
クロスプラットフォーム ソリューションを持つ標準ライブラリはありますか?
私はこれがうまくいくと思います:
#include <time.h>
clock_t start = clock(), diff;
ProcessIntenseFunction();
diff = clock() - start;
int msec = diff * 1000 / CLOCKS_PER_SEC;
printf("Time taken %d seconds %d milliseconds", msec/1000, msec%1000);
gettimeofday() はおそらくあなたが望むことをします。
Intel ハードウェアを使用している場合、CPU リアルタイム命令カウンターを読み取る方法は次のとおりです。プロセッサが起動してから実行された CPU サイクルの数がわかります。これはおそらく、パフォーマンス測定用に取得できる最も粒度が細かく、オーバーヘッドが最も低いカウンターです。
これは CPU サイクルの数であることに注意してください。Linux では、/proc/cpuinfo から CPU 速度を取得し、除算して秒数を取得できます。これを double に変換すると非常に便利です。
これを自分のボックスで実行すると、
11867927879484732 11867927879692217 printf を呼び出すのにこれほど時間がかかりました: 207485
これは、大量の詳細を提供するIntel 開発者ガイドです。
#include <stdio.h>
#include <stdint.h>
inline uint64_t rdtsc() {
uint32_t lo, hi;
__asm__ __volatile__ (
"xorl %%eax, %%eax\n"
"cpuid\n"
"rdtsc\n"
: "=a" (lo), "=d" (hi)
:
: "%ebx", "%ecx");
return (uint64_t)hi << 32 | lo;
}
main()
{
unsigned long long x;
unsigned long long y;
x = rdtsc();
printf("%lld\n",x);
y = rdtsc();
printf("%lld\n",y);
printf("it took this long to call printf: %lld\n",y-x);
}
gettimeofdayは、システム クロックの分解能内でマイクロ秒単位の正確な時間を返します。SourceForge のHigh Res Timersプロジェクトもチェックしてみてください。
CPU 時間が必要ない場合は、探しているのは timeval 構造体だと思います。
実行時間の計算には以下を使用します。
int timeval_subtract(struct timeval *result,
struct timeval end,
struct timeval start)
{
if (start.tv_usec < end.tv_usec) {
int nsec = (end.tv_usec - start.tv_usec) / 1000000 + 1;
end.tv_usec -= 1000000 * nsec;
end.tv_sec += nsec;
}
if (start.tv_usec - end.tv_usec > 1000000) {
int nsec = (end.tv_usec - start.tv_usec) / 1000000;
end.tv_usec += 1000000 * nsec;
end.tv_sec -= nsec;
}
result->tv_sec = end.tv_sec - start.tv_sec;
result->tv_usec = end.tv_usec - start.tv_usec;
return end.tv_sec < start.tv_sec;
}
void set_exec_time(int end)
{
static struct timeval time_start;
struct timeval time_end;
struct timeval time_diff;
if (end) {
gettimeofday(&time_end, NULL);
if (timeval_subtract(&time_diff, time_end, time_start) == 0) {
if (end == 1)
printf("\nexec time: %1.2fs\n",
time_diff.tv_sec + (time_diff.tv_usec / 1000000.0f));
else if (end == 2)
printf("%1.2fs",
time_diff.tv_sec + (time_diff.tv_usec / 1000000.0f));
}
return;
}
gettimeofday(&time_start, NULL);
}
void start_exec_timer()
{
set_exec_time(0);
}
void print_exec_timer()
{
set_exec_time(1);
}
SDL ライブラリのSDL_GetTicksを使用します。
高解像度は相対的です...私は例を見ていましたが、ほとんどミリ秒に対応しています。しかし、私にとってはマイクロ秒を測定することが重要です。マイクロ秒のプラットフォームに依存しないソリューションを見たことがなく、以下のコードのようなものが役立つと思いました。当分の間、Windows でのみタイミングを計っていましたが、AIX/Linux で同じことを行う場合は、gettimeofday() 実装を追加する可能性が最も高いでしょう。
#ifdef WIN32
#ifndef PERFTIME
#include <windows.h>
#include <winbase.h>
#define PERFTIME_INIT unsigned __int64 freq; QueryPerformanceFrequency((LARGE_INTEGER*)&freq); double timerFrequency = (1.0/freq); unsigned __int64 startTime; unsigned __int64 endTime; double timeDifferenceInMilliseconds;
#define PERFTIME_START QueryPerformanceCounter((LARGE_INTEGER *)&startTime);
#define PERFTIME_END QueryPerformanceCounter((LARGE_INTEGER *)&endTime); timeDifferenceInMilliseconds = ((endTime-startTime) * timerFrequency); printf("Timing %fms\n",timeDifferenceInMilliseconds);
#define PERFTIME(funct) {unsigned __int64 freq; QueryPerformanceFrequency((LARGE_INTEGER*)&freq); double timerFrequency = (1.0/freq); unsigned __int64 startTime; QueryPerformanceCounter((LARGE_INTEGER *)&startTime); unsigned __int64 endTime; funct; QueryPerformanceCounter((LARGE_INTEGER *)&endTime); double timeDifferenceInMilliseconds = ((endTime-startTime) * timerFrequency); printf("Timing %fms\n",timeDifferenceInMilliseconds);}
#endif
#else
//AIX/Linux gettimeofday() implementation here
#endif
使用法:
PERFTIME(ProcessIntenseFunction());
or
PERFTIME_INIT
PERFTIME_START
ProcessIntenseFunction()
PERFTIME_END