5

CPU に関する情報を読み取り、ユーザーに表示する C# ソフトウェアを作成しようとしています (CPU-Z と同様)。私の現在の問題は、CPU 周波数を表示する方法を見つけられなかったことです。

最初はWin32_Processor クラスを使った簡単な方法を試しました。CPU がオーバークロック (またはアンダークロック) されている場合を除いて、非常に効率的であることが証明されました。

次に、レジストリの HKLM\HARDWARE\DESCRIPTION\System\CentralProcessor\0に CPU の「標準」クロックが含まれていることを発見しました (オーバークロックされている場合でも)。問題は、最新の CPU では、CPU がフルパワーを必要としないときにコア乗数が減少するため、CPU 周波数も変化しますが、レジストリの値は同じままです。

私の次のステップは、RdTSCを使用して実際に CPU 周波数を計算することでした。メソッドが機能している場合は C# プロジェクトに埋め込むことができるため、これには C++ を使用しました。http://www.codeproject.com/Articles/7340/Get-the-Processor-Speed-in-two-simple-waysで次のコードを見つけました が、問題は同じでした: プログラムは最大周波数しか提供しません。 (レジストリ値のように、1〜2 Mhzの違い)、CPUに必要以上に負荷をかけているようにも見えます(CPU負荷のスパイクさえありました)。

#include "stdafx.h"
#include <windows.h>
#include <cstdlib>
#include "intrin.h"
#include <WinError.h>
#include <winnt.h>

float ProcSpeedCalc() {

#define RdTSC __asm _emit 0x0f __asm _emit 0x31

    // variables for the clock-cycles:
    __int64 cyclesStart = 0, cyclesStop = 0;
    // variables for the High-Res Preformance Counter:
    unsigned __int64 nCtr = 0, nFreq = 0, nCtrStop = 0;

    // retrieve performance-counter frequency per second:
    if(!QueryPerformanceFrequency((LARGE_INTEGER *) &nFreq))
        return 0;

    // retrieve the current value of the performance counter:
    QueryPerformanceCounter((LARGE_INTEGER *) &nCtrStop);

    // add the frequency to the counter-value:
    nCtrStop += nFreq;


    _asm
    {// retrieve the clock-cycles for the start value:
        RdTSC
        mov DWORD PTR cyclesStart, eax
        mov DWORD PTR [cyclesStart + 4], edx
    }

    do{
    // retrieve the value of the performance counter
    // until 1 sec has gone by:
         QueryPerformanceCounter((LARGE_INTEGER *) &nCtr);
      }while (nCtr < nCtrStop);

    _asm
    {// retrieve again the clock-cycles after 1 sec. has gone by:
        RdTSC
        mov DWORD PTR cyclesStop, eax
        mov DWORD PTR [cyclesStop + 4], edx
    }

    // stop-start is speed in Hz divided by 1,000,000 is speed in MHz
    return    ((float)cyclesStop-(float)cyclesStart) / 1000000;
}


int _tmain(int argc, _TCHAR* argv[])
{

    while(true)
    {
        printf("CPU frequency = %f\n",ProcSpeedCalc());
        Sleep(1000);
    }

    return 0;
}

また、AMD CPU で最後の方法をテストしたことにも言及する必要があります。RdTSC メソッドの他のコードもいくつか試しましたが、正しく動作するものはありませんでした。

最後に、このプログラムhttps://code.google.com/p/open-hardware-monitor/source/browse/を作成するために使用されるコードを理解しようとしましたが、私には複雑すぎました。

だから、私の質問は: C++ または C# を使用して (CPU がオーバークロックされている場合でも) リアルタイムで CPU 周波数を決定する方法は? この質問が何度も聞かれたことは知っていますが、実際に私の質問に答えてくれる人はいません。

4

3 に答える 3

1

答えは、あなたが本当に知りたいことによって異なります。

現在実行している特定のアプリケーションの動作周波数を見つけることが目標である場合、これは困難な問題であり、モデル固有のレジスタにアクセスするには管理者/ルート権限が必要であり、場合によっては BIOS にアクセスすることさえ必要です。これは、Windows の CPU-Z または Linux の powertop で実行できます。

ただし、たとえばピークフロップを計算できるように、負荷がかかっている1つまたは複数のスレッドのプロセッサの動作周波数を知りたい場合(これが私がこれを気にする理由です)、これは多かれ少なかれ一般的に行うことができます管理者権限を必要としないコード。

http://randomascii.wordpress.com/2013/08/06/defective-heat-sinks-causing-garbage-gaming/にあるBruce Dawson のコードからアイデアを得ました。私は主に、OpenMP を使用して複数のスレッドで動作するように彼のコードを拡張しました。

これは、1 つのソケットで最大 4 つのソケット (40 スレッド) の Nahalem、Ivy Bridge、および Haswell を含む Intel プロセッサ上の Linux および Windows でテストしました。結果はすべて、正解からの偏差が 0.5% 未満です。

ここで周波数を決定する方法を説明しましたhow-can-i-programmatically-find-the-cpu-frequency-with-c .

于 2014-08-20T09:07:49.830 に答える
0

あなたの質問は基本的に答えられません。CPU 周波数は常に変化します。OS が変更を認識して通知できる場合もありますが、そうでない場合もあります。CPU はオーバークロック (TurboBoost) またはアンダークロック (過熱による) する可能性があります。一部のプロセッサは、同じレートでクロックを実行することによって溶融を回避するために電力を削減しますが、一部のサイクルでのみ作業を行います。その時点で、クロック周波数の概念全体が無意味になります。

この投稿では、Windows が気付かずに CPU が熱的に調整されていた場所を分析した多数のマシンについて説明します。

http://randomascii.wordpress.com/2013/08/06/defective-heat-sinks-causing-garbage-gaming/

これを検出するために非常にプロセッサ固有の厄介なコードを書くことは可能ですが、管理者権限が必要です。

私が言いたいのは、あなたは答えられない質問をしているということであり、ほとんどの場合、それはあなたが尋ねるべき質問ではありません. レジストリの値を使用するか、CPU が実行されている周波数を Windows に問い合わせて (PROCESSOR_POWER_INFORMATION を参照)、それを十分に呼び出します。

于 2014-06-26T23:35:22.023 に答える