|
ぬじぬじ
- 03/6/7(土) 7:30 -
|
|
|
|
ぬじぬじです。
実際の性能と比較してクロックが低く測定されることがある(俺の(ID=269)とか Kim さんの(ID=1029))ようです。
双方とも省電力プロセッサ(俺のが Pentium III-M で Kim さんのが Pentium M)でしかも ThinkPad X3* と云う点が共通しています。恐らく無負荷時には動作周波数を低くするような設定になっているのだと思います。(プロセッサが勝手にやるのか BIOS なのか Windows XP なのか IBM のユーティリティなのかは判りませんが)
解決策としては周波数測定の際に適切な負荷を与えてやれば正しい結果が得られると思います。
修正の必要性に関して議論はあると思います。それはそれで正しい(周波数測定時の)周波数を測定してはいますから。が。GHz 当たりの速度を比較したい場合などに正しいデータが得られません。そもそもランキングの際に不公平感が漂います。ちう訳でさくっと直して頂ければありがたいです。
;; 時節柄「でんこちゃん賞」(え。別に「とまりん賞」でも良いよ)を要求したって罰は当たらないとは思うんですけどね。スローガンは ``If you suffer from loss of power, it's Californication.'' で。
|
|
|
|
|
|
|
|
|
|
▼ぬじぬじさん:
こんにちは〜 ぬじぬじさんもいつの間にやらよさげなマシンを購入したようで...正直 ぬじぬじさんと WinXP の組み合わせにちょっぴり隔世の感が(笑)
> 双方とも省電力プロセッサ(俺のが Pentium III-M で Kim さんのが Pentium M)でしかも ThinkPad X3* と云う点が共通しています。
私も SpeedStep マシンは試してみたいのですが... 研究室には Crusoe マシンがあるので、LongRun を試してみますかね。
> 修正の必要性に関して議論はあると思います。それはそれで正しい(周波数測定時の)周波数を測定してはいますから。が。GHz 当たりの速度を比較したい場合などに正しいデータが得られません。そもそもランキングの際に不公平感が漂います。ちう訳でさくっと直して頂ければありがたいです。
ユーティリティで低クロック固定で無い場合は、自動でクロックが上がっていくと思っているのですが、ずっと負荷が無い状態から CrystalMark を起動するとクロックが上がりきる前にクロックの測定が終わるということになるみたいですね。自動でクロックが上がる設定なら、ベンチ中は常時 100% の CPU パワーが活用できるわけで、確かに測定時のクロックとは異なりますな... あと、古い SpeedStep は負荷ではなく AC アダプタがつながっているかどうかでクロックが変化するそうです。
解決策としては、SpeedStep や PowerNow! や Crusoe 等の CPU のクロックが動的に変更できるプロセッサかどうかを識別し、必要に応じて、負荷をかけてから、クロック周波数を測定するという方法が考えられます。ここで問題になるのは、どの程度の時間が必要なのかという一点のみ。調べてみると、二つのモードは 0.5ms で遷移できるそうです。う〜む、本当に 0.5ms ならクロック周波数の測定には影響なさそうですが...
QueryPerformanceCounter(&lPre);
QueryPerformanceCounter(&lStart);
_asm{
rdtsc
mov dwStartH , edx
mov dwStartL , eax
}
dwStart = GetTickCount();
// Sleep API だとまれに不具合が起きるため
TickCount = GetTickCount();
while(GetTickCount() - TickCount < SLEEP_TIME){}
dwEnd = GetTickCount();
_asm{
rdtsc
mov dwEndH , edx
mov dwEndL , eax
}
QueryPerformanceCounter(&lEnd);
QueryPerformanceFrequency(&lFrequency);
今はこんな感じでクロック周波数を取得していますが、SpeedStep 的には
while(GetTickCount() - TickCount < SLEEP_TIME){}
の部分が負荷のうちに入っていないのかもしれません。無限ループの中に無意味な内容の計算でも入れれば、うまくいくのかな?ちなみに現在の SLEEP_TIME は 500 ms と定義しています。(もっと短くても平気なのですが...)
というわけで、こんな感じにしました。
// 負荷増強
volatile int i=0; // 最適化対策のつもり
if( FlagClockModulation ){
TickCount = GetTickCount();
while(GetTickCount() - TickCount < 100){
i++;
}
}
// クロック測定
QueryPerformanceCounter(&lPre);
QueryPerformanceCounter(&lStart);
_asm{
rdtsc
mov dwStartH , edx
mov dwStartL , eax
}
dwStart = GetTickCount();
// Sleep API だとまれに不具合が起きるため
TickCount = GetTickCount();
while(GetTickCount() - TickCount < SLEEP_TIME){
i++; // ここでも無駄に...
}
dwEnd = GetTickCount();
_asm{
rdtsc
mov dwEndH , edx
mov dwEndL , eax
}
QueryPerformanceCounter(&lEnd);
QueryPerformanceFrequency(&lFrequency);
ひょっとしら、i が最適化されて消えちゃうかも知れないけど...
とりあえず、クロック周波数測定君 (VC++ コーナー) にはほぼ同様のコードがついてるんで、そいつで、どうすれば最大クロックが取得できるか試してみるのも良いかなと。
※FlagClockModulation は SpeedStep PowerNow! LongRun 対応 CPU で TRUE です。
今回の処理を追加したバージョンを期間限定で、
http://musee.cims.hokudai.ac.jp/~hiyohiyo/SysInfo.dll においておきます。
研究室の Crusoe も試してみて良い様だったら月曜日に更新しておきます。バグ(?)報告三サンキュです。もちろん、前からわかっていたのですが、腰が重くて...(と言い訳)
|
|
|
|
|
|
|
|
|
|