5

現在、C++ を使用して Windows でアプリケーションを作成しており、CPU 負荷をシミュレートしたいと考えています。

次のコードがあります。

void task1(void *param) { 

unsigned elapsed =0;
unsigned t0;

while(1){

    if ((t0=clock())>=50+elapsed){//if time elapsed is 50ms

        elapsed=t0;
        Sleep(50);
    }
  }
}

int main(){

int ThreadNr;

for(int i=0; i < 4;i++){//for each core (i.e. 4 cores)
    _beginthread( task1, 0, &ThreadNr );//create a new thread and run the "task1" function
}

while(1){}
}

このスレッドで与えられた回答と同じ方法論を使用して、このコードを書きました:安定した CPU 負荷とスパイクをシミュレートする

私の質問は次のとおりです。

  1. 他の投稿の C# コードを正しく C++ に翻訳しましたか?
  2. このコードは、クアッドコア プロセッサで 50% の平均 CPU 負荷を生成しますか?
  3. 妥当な精度で、CPU の負荷率を知るにはどうすればよいですか? (タスクマネージャは私の唯一のオプションですか?)

編集:この質問をする理由は、最終的に妥当な許容範囲内で 10、20、30、...、90% の CPU 負荷を生成できるようにしたいからです。このコードは 70% 未満の負荷を生成する場合はうまく機能するようですが、70% 未満の負荷では非常に不正確なようです (タスク マネージャーの CPU 負荷の読み取り値で測定)。

上記の負荷を生成する方法について、誰かがアイデアを持っていますか?

4

3 に答える 3

8

一見すると、これは、きれいではないが正しい C++ または C のように見えます (確認する簡単な方法は、コンパイルすることです)。インクルード ( <windows.h><process.h>、および<time.h>) がありませんが、それ以外は正常にコンパイルされます。

clockSleepはそれほど正確ではなく、Sleep信頼性も高くないことに注意してください。ただし、平均して、スレッド関数は意図したとおりに機能するはずです (数パーセントの変動があります)。

while(1){}ただし、質問 2) に関しては、最後をスピンではなくブロックするものに置き換える必要があります (たとえばWaitForSingleObjectSleepそうする場合)。そうしないと、クアッドコアでプログラム全体の負荷が 50%になりません。メイン スレッドにより 1 つのコアに 100% の負荷がかかり、さらに 4 つのワーカーから 4x 50% の負荷がかかります。これは明らかに、コアあたり 50% を超えます (そして、スレッドが 1 つのコアから別のコアにバウンスし、厄介な副作用が発生します)。

タスク マネージャーまたは同様のユーティリティを使用して、必要な負荷が得られるかどうかを確認するのが適切なオプションです (これは最も簡単な解決策であり、最適な解決策でもあります)。

また、このような方法で負荷をシミュレートすることは、おそらくある程度は機能しますが、100% 信頼できるわけではないことに注意してください。
予測が難しい影響 (メモリ、実行ユニット) が存在する可能性があります。たとえば、このループで CPU の整数実行ユニットを 100% 使用しているが (合理的な仮定)、浮動小数点または SSE ユニットはゼロであると仮定します。最新の CPU は、実際のコアまたは論理コア間でリソースを共有する場合があり、どのような影響が得られるかを正確に予測できない場合があります。または、別のスレッドがメモリにバインドされているか、重大なページ フォールトが発生している可能性があるため、CPU 時間を取り除いても、思ったほど影響を受けません (実際には、プリフェッチの動作を改善するのに十分な時間を与える可能性があります)。または、AGP 転送でブロックされる可能性があります。または、あなたが言うことができない他の何か。

編集:

改善されたバージョン、いくつかの問題を修正し、意図したとおりに動作する短いコード:

  • clock_t(これは、特別に 'd でない整数を使用clockするよりも、技術的には「より正確」です。偶然にも、それがおそらく元のコードが意図したtypedefとおりに機能しないまさにその理由です。 in は常に を評価するため、ワーカーはほぼ常にスリープ状態になり、CPU を消費しません。clock_tif()true
  • コードが少なくなり、回転時の複雑な計算が少なくなります。50 ティック後のウェイクアップ時間を計算し、その時間に達するまでスピンします。
  • getchar最後にプログラムをブロックするために使用します。これにより CPU 時間が消費されることはなく、 を押してプログラムを終了できますEnter。スレッドは通常のように適切に終了されませんが、この単純なケースでは、プロセスが終了するときに OS にスレッドを終了させるだけで問題ないでしょう。
  • 元のコードと同様に、これは同じティックclockを使用することを前提としています。Sleepこれは確かに大胆な仮定ですが、元のコードで使用した Win32 でも当てはまります (両方の「ティック」はミリ秒です)。C++ には( 、または C++11Sleepなしで) のようなものがないため、Windows 以外の移植性が意図されている場合は、とにかく再考する必要があります。boost::threadstd::thread
  • 元のコードと同様に、不正確で信頼性の低い関数 (clockおよび)に依存しています。を使用せずに私のシステムで等しい。それにもかかわらず、プログラムは「ほぼ完璧」に動作し、私のマシンには 50% +/- 0.5% の負荷がかかります。SleepSleep(50)Sleep(63)timeBeginPeriod
  • 元のコードと同様に、これはスレッドの優先度を考慮していません。通常よりも優先順位の高いプロセスは、このスロットリング コードによってまったく影響を受けません。これは、Windows スケジューラがそのように機能するためです

    #include <windows.h>
    #include <process.h>
    #include <time.h>
    #include <stdio.h>
    
    
    void task1(void *)
    {
        while(1)
        {
            clock_t wakeup = clock() + 50;
            while(clock() < wakeup) {}
            Sleep(50);
        }
    }
    
    int main(int, char**)
    {
        int ThreadNr;
        for(int i=0; i < 4; i++) _beginthread( task1, 0, &ThreadNr );
    
        (void) getchar();
        return 0;
    }
    
于 2013-01-09T10:48:46.690 に答える
1

WindowsパフォーマンスカウンターAPIを使用して、CPU負荷を取得できます。システム全体またはプロセスのいずれか。

于 2013-01-09T08:57:24.927 に答える