CPUのクロック周波数の計測方法

[戻る]
鳥の子 2006/10/15(日) 10:37:16
WinXP Pro. と Borland C++ Builder 6 です。
PC のクロックは 公称(Dell) fc=2.6 GHz です。

http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200610/06100022.txt

を読み、このようなこともできるのだと感じたので、実行してみました。 
アセンブリ言語を組み入れるのは初めてなので、
アッセンブリ言語の部分はおおよそしか読みとれません。

実行する前の私の予想は次のとおりです。
PCのクロックの周波数をカウントするといっても、
基準となる一秒間の時計は自分のPCのクロックの周波数のはずです。
つまり自分の基準で自分を計測することになります。
だから、計測するたびごとに同じ数値が得られるはずだと予想しました。
実行してみると、

wait=100; ミリ秒に設定の場合、
1   2899.134 MHz
2   2834.364
3   2822.778
4   2912.229
5   2914.862

wait=1000; ミリ秒に設定の場合、
1   2593.200 MHz
2   2602.351
3   2592,188
4   2585.130
5   2602.351

たしかにクロック周波数を計っているようです。
ざっと見てそれぞれ数パーセントから0.5パーセントのばらつきがあります。
PCの安い水晶振動子でも安定度は0.01パーセントはあるはずです。
最初の計測するたびごとに同じ数値が得られるはずだと予想ははずれました。

コピーして実行した下のコードはCPUのクロック周波数の何を計っている
のでこのようなばらつきが出たのでしょうか?

//-----------------------------
int cpu_clk()
{
    unsigned __int64 c1 = 0, c2 = 0;

    DWORD flag, mask = 0x10;
    DWORD wait = 1000; // ミリ秒
    DWORD time;

    __asm{
        mov eax, 0x01; // 01H;
        cpuid;
        mov flag, edx;
    }

    if(flag & mask){   // rdtsc 命令のサポートチェック
        time = GetTickCount() + wait; 
        __asm{
            rdtsc;   // 電源投入時からのクロックのカウント数
            mov dword ptr[c1],  eax;
            mov dword ptr[c1+4], edx;
        }

        while(time > GetTickCount()); // wait ミリ秒待つ
        
        __asm{
            rdtsc;
            mov dword ptr[c2],  eax;
            mov dword ptr[c2+4], edx;
        }
    }
    return int ((c2 -c1) / wait ); // MHz 単位で表示する。
}
//---EOF----------------------

επιστημη 2006/10/15(日) 11:02:56
GetTickCount()にはさほどの精度がありませんから。

ITO 2006/10/15(日) 13:37:16
 最近のマザーボードは、「オーバクロック」に対応するとかで
正確に計測しているんじゃないかと思います。
 システム情報取得とか、レジストリーから取得するのがいいと思います。
どうしても計測してみたいなら、デバイスドライバー作るしかないですね。

おと 2006/10/15(日) 14:02:56
うまく表現できないが
アナログからデジタルへ移る境目はアナログ的です
波形のスレッショルドレベルとか
半導体の温度変化とか
それからPCは測定器としてつくられていません
アセンブラでプログラムつくってもその下(深部)には
ファームウエアのプログラムが動いているわけで
>つまり自分の基準で自分を計測することになります。
>だから、計測するたびごとに同じ数値が得られるはずだと予想しました。
この考え方は論理的におかしいのでは? というのは たとえば
田中太郎(だれでもよいが)は田中太郎の脳みそが正常であることを
証明できません 循環論法になるからです
>コピーして実行した下のコードはCPUのクロック周波数の何を計っている
>のでこのようなばらつきが出たのでしょうか?
>GetTickCount()); 
たとえGetTickCount()のソースがわかっても正確な精度はわからないでしょう

c 2006/10/15(日) 16:52:49
Intelのcpuinfoツール(cpuinfo.zip)の中にあるソース(Speed.c)を見てみると、
GetTickCountではなくQueryPerformanceCounterを使ってるみたいですね。
あと、計測中はSetThreadPriorityでTHREAD_PRIORITY_TIME_CRITICALに
設定してる。

さやぴ 2006/10/16(月) 08:50:38
GetTickCount()はミリ秒、QueryPerformanceFrequency()はマイクロ秒単位で
時間が測れますが、Windowsのタイマは信頼性が低いようなので、毎回同じ値
にならないと思います。

古いスレッドには追加発言できません。