rdtsc
rdtscとはRead Time Stamp Counterである。これは何かというと、CPUクロックに基づく相対時刻の計測のページを引用させてもらうと
Intel x86系のCPU(AMDのAthlon等も含む)では、CPUクロックごとに加算される64bitのタイムスタンプカウンタ(IA32_TIME_STAMP_COUNTER_MSR:通称TSC_MSR)があります。
となっており、これを読み込むアセンブラ命令がrdtscとのことのようだ。
実際VC++など関数として使う場合では、
1 2 3 4 5 6 7 |
__int64 getRdTsc() { _asm { rdtsc } }; |
このようにしてカウンタを取ることができる(QueryPerformanceCounterでの測定は時間の測定であったが、こちらはもろに消費クロック数を測定できるという意味で興味深い)。
ちなみにx64の場合、上記アセンブラはエラーになるので__rdtsc()というのを使う。また、intrin.hというヘッダーをインクルードすることで32bitでも64bitでも__rdtsc()が使えるようになる。
クラス化
簡単にクラス化してみた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
class RdTsc { private: __int64 oldRdTsc_; __int64 newRdTsc_; inline static __int64 getRdTsc() { #ifdef _M_IX86 _asm { rdtsc } #endif #ifdef _M_X64 return __rdtsc(); #endif }; public: RdTsc() : oldRdTsc_( 0 ), newRdTsc_( 0 ) { }; inline void update() { oldRdTsc_ = newRdTsc_; newRdTsc_ = getRdTsc(); }; void trace() { ATLTRACE2( _T( "%I64d\n" ), newRdTsc_ - oldRdTsc_ ); }; void print() { _tprintf( _T( "%I64d\n" ), newRdTsc_ - oldRdTsc_ ); }; }; |
コードがシンタックス的にあってるかどうかはさておき、使う直前使う直後にupdateという感じだ。一応inlineという指定はしているものの、クラス化によって若干パフォーマンスが悪くなっている気もする(無駄な消費クロック数が増えている?)。ただ、クラス化したほうが使うときは楽かなという気もするので、その点を次に実験で調査する。
パフォーマンス
クラス化による余計なクロック数の増加を見てみようと思い、クラス化をしないバージョンと比較してみた。実験するコードは何もしないコードを1000回まわしてその平均を取るといったものである(一連rdtscルーチンそれ自体が消費するクロック数の測定)。その結果、
インライン | 66 |
クラス | 66 |
とのことであった。つまりクラス化による損失は、1000回の試行では特に発生しないという結果になった。
ちなみに、rdtscの結果は両者ともに最初の数回99という値を発生した後72か63の値しか吐き出さない(9の倍数になるのが普通なのだろうか、、、)という傾向であった。
なお、今回はリリース最適化コンパイル版での比較であるが、デバッグ版(非最適化)時にはインラインは変わらず66だったのに対し、クラスでは238であった。最適化するかどうかでこの変のクロック数は変わってくるようだ。(逆に言えば、単なるクラス化でのクロック損失はリリース最適化版においては、ほとんど発生しないということ。なお、今回はVisual Studio 2005のVC++8.0でコンパイルしている)
GUIアプリケーションの場合は、ウインドウのタイトル部分にでも出せばよいでしょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
void update_window_text ( HWND hWnd ) { TCHAR text[ 65 ] = { 0 }; if( _i64tot_s( newRdTsc_ - oldRdTsc_, text, 65, 10 ) ) { return; } SetWindowText( hWnd, text ); }; |
ループなどでrdtscの平均値を測定する方法については、こちら。
ピンバック: SleepExとQueueUserAPCの割り込みパフォーマンス | 豆知識
ピンバック: VC++ BitBltとメモリ内ScrollDCの速度 | 豆知識
ピンバック: ATLのCStringとWTLのCStringのパフォーマンス比較 | 豆知識
ピンバック: rdtsc(Read Time Stamp Counter)の平均値測定 | 豆知識