言語:C全般
環境:VC++ 2008 EE
3DCG:Softimage Mod Tool
ゲームプログラマー目指して勉強している者です。
現在 C++ 修得にむけて頑張っています。
Began study since 2009/8/21
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
test(.exe)
どうもです。
今回はコンピュータの処理時間を取得してそれを乱数にしてしまおうという目論見のもとプログラミングしていきました。
全く同じ処理でも絶対に同じ処理時間ではないだろうと思っていたのでやってみようということになったのですが、この場合取得できる時間が秒単位では精度が悪すぎます。
ですので、まず高い精度で時間を取得できる関数を探しました。
検索したところいろいろあったのですが、少なくともマイクロ秒(100万分の1秒だったと思う)ぐらいはほしいので、 gettimeofday などの関数を使おうかと思ったのですが、
'sys/time.h':No such file or directory
つまり、インクルードしなければいけない sys/time.h が存在しないのです。
一応自分でも sys フォルダ内を見てみたが、似たようなのはあるのだが確かに time.h はなかった。
別の方法を探すことにしましょう。
そこで見つけたのがパフォーマンスカウンタの現在値を調べるものでした。
「パフォーマンスカウンタとはなんだ!?」
CPUの内部に搭載されている、CPUクロックを元にカウントしているカウンタのことである。
こいつはパソコンに電源が入ると同時にカウントを始める。
よって、「計測したい処理を開始する前のカウンタの現在値」※1と、「処理が終わった後のカウンタの現在値」※2を取得することで処理中にどれだけカウントしたかが分かる。
求め方は ※2 から ※1 を引くだけでよいのです。
あとはその差分をカウンタの1秒あたりの周波数(クロック周波数)で割ることで秒単位の時間が得られるわけです。
では、それぞれを値を得る関数を紹介します。
QueryPerformanceCounter()
QueryPerformanceFrequency()
それぞれカウンタの現在値と周波数を得る関数です。
それぞれの関数には数値を格納するための変数のアドレスを渡します。
その変数の型は LARGE_INTEGER 型となります。
ちなみに LARGE_INTEGER は大きな整数を扱う型(ていうか共用体です)なのですが、大きすぎて LowPart , QuadPart などという風に分けられていていろいろ面倒なので、今回は __int64型 を使います。
(この型についての詳細は自分で調べてみてください。)
よって、
__int64 start, end, freq;
QueryPerformanceFrequency((LARGE_INTEGER *)&freq);
QueryPerformanceCounter((LARGE_INTEGER *)&start);
//計測したい処理
QueryPerformanceCounter((LARGE_INTEGER *)&end);
という風な感じになります。
あとは、カウンタ値の差分をクロック周波数で割ります。
その値を格納する変数を pastmsec とします。
さらにそれに 1000 をかけたものを rand_val としたのが、上記の test.exe です。
(試験ファイルですので 30 回出力させています。)
しかし、このままでは乱数としては精度が悪すぎるのです(同じ数や似たような数値ばかりがでてしまう)。
そこでとりあえず、出力する数値が直前に出力した数値と同じ場合は出力しないようにしています。
ですので1桁の数字がないところがところどころあるかもしれませんが、こういうことなので気にしないでください。
ちなみに計測している処理は、 1千万回の空文 です。