明らかに時間のかかるループなどを行う際にCPUの利用率を見ながら処理速度を調節するには?

解決


どら  2007-01-31 17:35:26  No: 64339  IP: [192.*.*.*]

こんにちは、どらです。

for文やwhile文で明らかに処理に時間がかかるループを作成した場合、基本的に、そのループが終わるまで、CPU使用率がボコッと上がってしまいますよね?

このような処理を行うときに、例えば「ループを実行しているプロセスのは30%以上CPUの利用率を占有しないようにする」といったような制御を行うことは可能なのでしょうか?

開発環境はWindows XP(SP2) + VC.NET 2003 Enterprise です。

ご存じの方いらっしゃいましたらご教授ください。
よろしくお願いします。

編集 削除
超初心者  2007-01-31 19:06:33  No: 64340  IP: [192.*.*.*]

ハイパースレッドだとどんなにがんばっても2個のCPUのうち1個しか使わないから50%を超えられないんだよね。

時間を調べて0.1秒動かしたらSleep(200)を実行すればいいんじゃないの。
頻繁に時間を調べる分余計な負担になるけどね。

編集 削除
とーりすがり  2007-01-31 19:19:22  No: 64341  IP: [192.*.*.*]

>時間を調べて0.1秒動かしたらSleep(200)を実行すればいいんじゃないの。
それだとCPUあいてても無駄に待つぞ
スレッドの優先度下げておいて
CPU暇なときなるべく優先度上げたいならパフォーマンスカウンタ見ながら優先度調整とか

編集 削除
超初心者  2007-01-31 20:54:02  No: 64342  IP: [192.*.*.*]

今まで実装しようとは思わないというかしたくないので気にしていなかったが
自分のスレッドだけのCPU占有率って負荷をあまりかけずに調べられるものなのかな。

トータルのCPU負荷が100%に近いときは
自分のスレッドを30%以下にするっていうのは実現できるのかな。

最初あまり興味なかったが、出来たら面白そうだ。
常時CPU負荷30%を維持するのかと思った。

俺はそんな時、タスクマネージャを使って
手動でスレッド優先度とかCPU1個に制限とかしちゃうものでして。

編集 削除
Ban  2007-02-01 01:12:53  No: 64343  IP: [192.*.*.*]

んなことしなくても、スレッドの優先度下げれば
OSがまぁよしなにやってくれると思う。

編集 削除
Ban  2007-02-01 01:15:05  No: 64344  IP: [192.*.*.*]

更新したら盛大にかぶってた…orz

編集 削除
tetrapod  2007-02-01 09:39:03  No: 64345  IP: [192.*.*.*]

よく考え違いをしている人がいるんだけどCPU100% は悪いことぢゃ無い。
CPU利用率30%ってことは70%は寝ているということだ。
つまり「もっと高速に処理できるのに、なんかの理由で待ってる」のだ。

かなり違うが、暴言してしまえば
1GHzのCPUがついてても30%しか使わないなら300MHzで十分
つーことだ。

・システム全体のCPU利用率30%   と
・有効CPU利用時間中の30%  とは違う。

一般ユーザの作るプログラムでは難しいこと考えずに単純にループすればいい。
他のタスクに時間をまわしたいなら優先順位を下げるだけでいい。

編集 削除
どら  2007-02-03 00:14:05  No: 64346  IP: [192.*.*.*]

すみません、しばらく来れない間にたくさんのレスありがとうございます。

優先順位を下げるには、どうしたらよいのでしょうか?
そのプログラムの中で優先度を下げてループを実行させることなんてできるのでしょうか?

今までこういうこと考えたことなかったので・・・
ご存じの方いらっしゃいましたら、教えてください。

よろしくお願いいたします。

編集 削除
Ban  2007-02-03 01:16:01  No: 64347  IP: [192.*.*.*]

SetThreadPriority(スレッド単位)
SetPriorityClass(プロセス単位)

使い方はMSDNで上記の説明を熟読してください。

このあたりも参照。Scheduling Priorities
http://msdn2.microsoft.com/en-us/library/ms685100.aspx

編集 削除
夏みかん  2007-02-03 14:20:15  No: 64348  IP: [192.*.*.*]

ループ内でメッセージを処理すれば CPU 使用率 100% にならなくてすみますが…。
次の関数を作成して、ループ内で呼び出せばよい。

VOID PumpMessage( HWND hWnd )
{
  MSG msg;
  
  while ( PeekMessage(&msg,hWnd,0,0,PM_REMOVE) ){
    if ( !IsDialogMessage(hWnd,&msg) ){
      TranslateMessage( &msg );
      DispatchMessage( &msg );
    }
  }
}

使用例:

while ( 条件式 ){
  :
  処理
  :
  PumpMessage( hWnd );
}

編集 削除
PATIO  2007-02-05 14:54:39  No: 64349  IP: [192.*.*.*]

基本的に重い処理はワーカースレッドにして実行。
そのスレッドの優先度を適度に設定すれば、それでよいと思います。
重い処理が走って困る事の筆頭はUIが効かなくなる事だと思うので
ワーカースレッド化してしまえば、メインスレッドはメッセージ処理が
できますからそこまで不便は無いのではないかと思います。

後は、ワーカースレッドの負荷がどの程度か次第でしょうねぇ。
基本的には時間が掛かっても良いのであれば、優先度を下げれば、
OSが良しなにやってくれると思います。
ただ、下げすぎると処理時間が長くなってしまうと思うので
さじ加減は必要でしょうねぇ。

編集 削除
どら  2007-02-07 11:59:33  No: 64350  IP: [192.*.*.*]

皆さん、たくさんのアドバイス、ありがとうございました!!
今回のプログラムでは、重いループ処理をスレッドで実行していたので

  SetThreadPriority

を使わせていただきました(実行時に優先度を下げるかどうかのフラグを設定して、どちらでも出来るようにしました)。

ありがとうございました!!

編集 削除