2026年11月4日水曜日

コードチューニングのための時間計測

 C++でコード実行時間をナノ秒(ns)単位で計測する場合は、通常 std::chrono::steady_clock を使います。

関数化

使用例:

注意点

極めて短いコード(数ns~100ns程度)を計測する場合、

1回だけの計測ではタイマ精度やOS割込みの影響が大きくなります。

そのため、

のように大量ループして1回当たりの時間を求める方が正確です。

さらにSIMD命令やCPUサイクル単位で測るなら、RDTSC/RDTSCP を使う方法もあります。

ただし __rdtsc() は命令の並べ替えの影響を受けるため、ベンチマーク用途では通常

のように LFENCE + RDTSC + RDTSCP + LFENCE を組み合わせます。

SSE/AVXレベルの最適化を評価するなら、chrono よりも RDTSCP で「サイクル数」を測定する方が有用です。例えば _mm_store_si128 と memcmp の比較などでは、nsよりcyclesの方が差が見えやすくなります。

サイクル数を時間に換算するには?

CPUサイクル数から時間への換算は、

時間[s]=cyclesCPU周波数[Hz]時間[s]=CPU周波数[Hz]cycles​

です。

例えば 4.0GHz のCPUで、

なら

400/(4.0×109)=100𝑛𝑠400/(4.0×109)=100ns

となります。

nsへ直接換算

時間[ns]=cycles×109CPU周波数[Hz]時間[ns]=CPU周波数[Hz]cycles×109​

4GHzなら

になります。

なぜなら4 GHz = 4 cycles/ns

だからです。


実際にはTurboで周波数が変わる

最近のCPUは

のように動的に変化します。

そのため

で計算しても誤差があります。

ベンチマークでは通常、

のまま比較します。


TSCがInvariantの場合

最近のIntel/AMDでは TSC(Time Stamp Counter) が一定速度です。

例えば

なら

です。

TSC周波数は実クロックとは異なり、

に固定されていることが多いです。



正確な換算方法

chrono と rdtsc を同時に計測して較正します。

すると

で高精度に換算できます。

SIMDコード(_mm_store_si128、memcmp、8byte比較など)の性能評価なら、ユーザーさんの用途では ns換算せず cycles のまま比較するのが一般的 です。CPU周波数変動の影響を受けず、

のように直接性能差が分かります。さらに命令単位で評価する場合は、ループ展開して「cycles/iteration」または「cycles/op」を見るのが定番です。

0 件のコメント:

コメントを投稿