【プログラミングの美】CPU占有率曲線を指揮に聴かせる


プログラミングの美しさ:CPU占有率曲線に指揮を聞かせます Posted on 2008-04-17 00:20 
Fox読書(8300)
コメント(10)   
編む
まとめる  
コレクション  
参照所属分類:
T技術のささやき  

Author: Fox http://www.cppblog.com/Fox/archive/2008/04/17/control_cpu_using_curve.html
先日「コンピュータプログラミングアート」の中国語版を買った時、偶然「プログラミングの美しさ」という本を見つけた.CPU占有率曲線に滑らかな正弦波曲線を描くコードを書きます.
もちろん、最後にこの本を買わなかった.これはいい本だと確信できるが.
私はCSDN読書からいくつかの節を見つけて、暇に読んでみました.今日は『CPU占有率曲線を指揮に聴かせる』について議論します.
タイトル:Windowsタスクマネージャ(Task Manager)のCPU占有率をユーザーに決定させるプログラムを作成します.プログラムが簡素であればあるほど、コンピュータ言語は限らない.例えば、以下の3つのケースを実現することができる.
1.CPUの占有率は50%に固定され、一直線である;
2.CPUの占有率は一直線であるが、具体的な占有率はコマンドラインパラメータによって決定される(パラメータ範囲1~100).
3.CPUの占有率状態は正弦波曲線である.
具体的な実装について議論する前に、CPU占有率とは何ですか.
プログラミングの美しさ」は、「タスクマネージャの1つのリフレッシュサイクルにおいて、CPUが忙しい(アプリケーションを実行する)時間とリフレッシュサイクルの合計時間の比率は、CPUの占有率、すなわち、タスクマネージャに表示されるのは、リフレッシュサイクルごとのCPU占有率の合計平均値である」と記載している.
「Windowsタスクマネージャ」を開くと、「パフォーマンス」に「CPU使用レコード」という項目があり、CPU占有率曲線が表示されます.
リフレッシュサイクルの長さについては、本の中は明確に示されていないようで、「約1秒に1回更新されます」と言っているだけで、Windowsに付属している時計を開けても、約1秒だと感じます.
もう一つの常識は:
シングルコア環境では,デッドサイクルは100%のCPU占有率をもたらす.デュアルコア環境では、CPUの総占有率は約50%で、クアッドコアは25%前後ではないでしょうか.(私はクアッドコアを持っていないので、推測するしかありません.各コア間の切り替えにも時間がかかると思います.私のデュアルコア環境には1コア100%が現れていないので、もう1コアが空いている場合はありません).
CPU占有率は、CPUがリフレッシュ期間(ほとんどの時間)全体にわたってアイドル状態である場合、0になる傾向がある.
本の中によって与えられる正弦波は、以下のように実現される.
1 #include "Windows.h"

2 #include "stdlib.h"

3 #include "math.h" 

4 

5 const double SPLIT = 0.01;

6 const int COUNT = 200;

7 const double PI = 3.14159265;

8 const int INTERVAL = 300; 

9 

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

11 {

12     DWORD busySpan[COUNT];  //array of busy times

13     DWORD idleSpan[COUNT];  //array of idle times

14     int half = INTERVAL / 2;

15     double radian = 0.0;

16     for(int i = 0; i < COUNT; i++)

17     {

18         busySpan[i] = (DWORD)(half + (sin(PI * radian) * half));

19         idleSpan[i] = INTERVAL - busySpan[i];

20         radian += SPLIT;

21     }

22     DWORD startTime = 0;

23     int j = 0;

24     while (true)

25     {

26         j = j % COUNT;

27         startTime = GetTickCount();

28         while ((GetTickCount() - startTime) <= busySpan[j]) ;

29         Sleep(idleSpan[j]);

30         j++;

31     }

32     return 0;

33 }

 
シングルコア環境(P 4.40)では、そのパフォーマンスは良好です.
クリックして大きい図を見ます
デュアルコア環境(Core 2 E 4500)では、少し劣っています.
クリックして大きい図を見ます
しかし、正弦曲線であることがうかがえる.
上の2つの図の問題:
1)シングルコア時の曲線が滑らかでないのは、QQなどのプログラムがCPUを占有しているためである.
2)デュアルコアでは曲線がよりジグザグになりますが、他のプログラムの影響を除いて、スレッドがCPU上で固定的に動作していないため、本の上でスレッド移行について言及されているのを見て、個人的にはこの呼び方が妥当ではないと思います.
すぐに考えられるのは、指定されたプロセッサ上でプロセスを実行させ(プロセッサの親縁関係)、Windowsによって2つのAPIが提供されていることです.GetCurrentProcessとSetProcessAffinityMaskです.
修正後のコードは次のとおりです.
1 #include "Windows.h"

2 #include "stdlib.h"

3 #include "math.h" 

4 

5 const double SPLIT = 0.01;

6 const int COUNT = 200;

7 const double PI = 3.14159265;

8 const int INTERVAL = 300; 

9 

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

11 {

12    SetProcessAffinityMask(

13         GetCurrentProcess(),

14         0x00000001          //cpu mask

15         ); 

16 

17     DWORD busySpan[COUNT];  //array of busy times

18     DWORD idleSpan[COUNT];  //array of idle times

19     int half = INTERVAL / 2;

20     double radian = 0.0;

21     for(int i = 0; i < COUNT; i++)

22     {

23         busySpan[i] = (DWORD)(half + (sin(PI * radian) * half));

24         idleSpan[i] = INTERVAL - busySpan[i];

25         radian += SPLIT;

26     }

27     DWORD startTime = 0;

28     int j = 0;

29     while (true)

30     {

31         j = j % COUNT;

32         startTime = GetTickCount();

33         while ((GetTickCount() - startTime) <= busySpan[j]) ;

34         Sleep(idleSpan[j]);

35         j++;

36     }

37     return 0;

38 }

 
デュアルコア環境(Core 2 E 4500)の修正後の出力は次のとおりです.
クリックして大きい図を見ます
私の理想の表現は:
1)曲線は滑らかで、他のアプリケーションや操作の実行によって変更されないことが望ましい.
2)シングルコアでもデュアルコアでもピークは100%,谷値は0であった.
第1の点は、いずれのリフレッシュサイクルにおいてもCPU占有率が0-100の間で正確に制御されることを保証することであり、CPUを50%(近似的な上下変動ではなく)維持し続けることができれば、滑らかな曲線を生成することはeasyである.
問題の鍵は、現在書いているプログラムを除いて、他のプログラムや操作をどのように制御できるかということです.あるいは、CPUの運転状況をどのように制御するかが重要です.
PS:一晩中ネットが切れていて、考えが途切れていて、興味も大半を失いました.とにかく、『プログラミングの美しさ』は味わう価値があるでしょう:D.