CPU負荷をかけないで時間稼ぎをしたい

[戻る]
ひろ 2002/09/10(火) 17:53:40
Sleep関数より正確な時間で、時間稼ぎが出来る関数など
何か良いものはありますでしょうか?
whileのどのループで回すとCPU負荷が大きくなってしまうのですが・・
よろしくお願いします。

アイススケーター 2002/09/10(火) 18:15:01
環境がよくわかりませんが、

SetTimerでタイマーを起動し、OnTimerでカウントする方法があります。
但し、10ms以下のタイマーはあまりあてになりませんので、100ms程度
のタイマーにしたほうがいいですよ。

あと、スタート時に起動時間を保存して、確認時に再度現在の時間から補正
すると性格な時間が計測できます。

dairygoods 2002/09/10(火) 18:43:53
どの程度の精度を求めているのでしょうか?
多分Sleepより正確なものは無いと思います。

ひろ 2002/09/10(火) 18:48:41
環境等を詳しく書かなくて申し訳ありませんでした。
詳しく申しますと・・

while(1){
    
  //**************ループ時間計測開始部*****************//
  LONGLONG  freq, cnt1, cnt2;
  int r;
  r=QueryPerformanceFrequency( (LARGE_INTEGER *)&freq ) ;
  if(r != 0){            
  QueryPerformanceCounter( (LARGE_INTEGER *)&cnt1 );        
  }
  //***************************************************//
        

   ここにログファイル書き込み処理部があります(200ms以内に終わる)
 

   float lopTime=0;
   while(1){

 ★このままの記述だと、CPUの負荷が100%になってしまうのでここに
  ちょっと待つ処理がほしいのですが何か良い案は無いでしょうか。
  ちなみにSleep(1)にするとsleep関数のバラツキがひどくて
  正確(ほぼでいいのですが)に200msで全体のループが回りません。

     QueryPerformanceCounter( (LARGE_INTEGER *)&cnt2 );
     lopTime = (float)((((double)(cnt2-cnt1)) / freq * 1000.0));
     if(lopTime < 0 || lopTime >= 200.0) break;//200ms以上で抜ける
   }

}

開発環境
os:windowsXp
開発ソフト:VC.NET
 

ひろ 2002/09/10(火) 18:53:24
すいません、ループの精度ですが最大で2msくらい。
多少我慢はできますが、これぐらいに抑えたいです。

dairygoods 2002/09/10(火) 20:31:32
・SetThreadPriorityでスレッドの優先度を上げる
・timeBeginPeriodでタイマーの分解能を上げる
しかし、精度を上げればそれだけCPUへの負荷は高まります。

dairygoods 2002/09/10(火) 20:38:52
・SetPriorityClassでプロセスの優先度を上げる
がまず先でした。

アイススケーター 2002/09/10(火) 22:43:45
ちなみに、どういった用途にお使いなのでしょうか。

ベンチマーク等に利用されるのであればかまわないのですが、Sleepで1msを指定
すること自体無理があると思います。

Windowsのタスクスイッチングの処理能力を考えるとやっぱり数十msのタイマ値は
最低限必要だと思います。

Windowsはアプリケーションを起動していなくても数十個のタスクが動いています。
これらのタスクスイッチングを行うことを考えると2msの精度は非常にきびしいと
思います。

ひろ 2002/09/11(水) 22:22:24
みなさんご回答ありがとうございます。
今日一日HP見れなくて返事かかけませんでした。

アイススケーターさんの質問についてですが
用途は、パソコンにデジタル入力信号を取り込むPCIボードを実装し
そのデジタル信号を200ms単位で監視したいのです。
今の処理方法だと、200msをカウントするループでCPUの負荷がかかっちゃう
みたいです。

dairygoods さんのtimeBeginPeriodを試してみたいと思います。

もう少し頑張ってみます。・・

アイススケーター 2002/09/12(木) 08:04:10
 200ms単位で監視するのであれば、タイマー割り込みのほうがいいと思いますよ。
 他のアプリケーションを動かしていなければ2〜5msの誤差で動かせるでしょう。
 SetTimerで20msのタイマーをセットして、OnTimerで監視し、時刻データを読み
取って、補正をかければ、あまり問題ないのでは・・・

ひろ 2002/09/12(木) 10:21:07
SetTimerについてですが、
自アプリケーションは、Win32コンソールプログラムでMFCを使わないで組んでいるので
すが、SetTimerの組み方を教えて頂きたいのですが・・
よく見るサンプルは、MFCでのプログラムばかりだったものですから。
申し訳ありませんがよろしくお願いします。

tib 2002/09/12(木) 11:43:00
SetTimer (Platform SDK)
指定されたタイムアウト値を持つタイマーを作成します。

UINT SetTimer(
  HWND hWnd, // handle of window for timer messages
  UINT nIDEvent, // timer identifier
  UINT uElapse, // time-out value
  TIMERPROC lpTimerFunc // address of timer procedure
);


パラメータ
hWnd
ウィンドウのハンドルを指定します。ウィンドウは、呼び出し側のスレッドが所有するも
のでなければなりません。このウィンドウに、タイマーが関連付けられます。NULL を指
定すると、ウィンドウには関連付けられないタイマーが作成されます。また、nIDEvent
パラメータは無視されます。

nIDEvent
タイマー ID を指定します。0 以外の値を指定してください。hWnd パラメータに NULL
を指定したときは、このパラメータは無視されます。

uElapse
タイムアウト値を、ミリ秒 (1000 分の1秒) 単位で指定します。

lpTimerFunc
uElapse パラメータで指定した時間が経過すると呼び出される関数へのポインタを指定し
ます。このコールバック関数の詳細は、TimerProc 関数の説明を参照してください。
NULL を指定すると、システムはWM_TIMER メッセージをアプリケーションキューにポスト
します。このとき、メッセージの MSG 構造体の hwnd メンバに、hWnd パラメータで指定
したハンドルが格納されます。

戻り値
関数が成功すると、新しいタイマー ID が返ります。関数がタイマーの作成に失敗する
と、0 が返ります。

解説
タイマーメッセージを処理するには、ウィンドウプロシージャに WM_TIMER メッセージ処
理ルーチンを記述するか、または、TimerProc コールバック関数を用意します。
TimerProc コールバック関数を利用する場合も、呼び出し側スレッドでメッセージをディ
スパッチ (転送) する必要があります。これは、デフォルトウィンドウプロシージャが
コールバック関数を呼び出すからです。

ひろ 2002/09/12(木) 17:48:41
[[解決]]
みなさん、ご回答ありがとうございました。
SetTimerも試みましたが、元々精度の設定が厳しいものがありました。
仕様の許容範囲を広げていただきました。
完全な解決にはなりませんでしたが、非常に勉強になりました。
ありがとうございました。
また、またのフォーラム利用時もよろしくお願いします。

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