プロが教える店舗&オフィスのセキュリティ対策術

引数で渡した値だけ待つ関数を作っているのですが、うまくいきません。

OS:WindowsXP Professional (SP1)
プラットホーム:Visual C++ Ver7
アプリケーション:コンソールタイプ

失敗例1:Sleep()関数を用いた。
結果:15msec以下の設定が出来なかった。
(1/64secの整数倍でないとズレが生じた)

失敗例2:Clock()関数を使って以下のルーチンを作成

void WaitTimer( clock_t wait )
{
register clock_t goal;
goal = clock() + wait;
while( goal > clock());
}
結果:失敗例1と同じ結果。

どうやら(スレッドか何かはわかりませんが)64Hz周期の何かがあるようです。
 
何方か10msec単位(±1msec)のWaitTimerを作ったことがある方、是非ノウハウを教えてください!

A 回答 (4件)

既に2の方が回答されていますが



QueryPerformanceCounterとQueryPerformanceFrequencyが
最も高い時間精度を持つ測定用のAPIです。
(GetTickCount等に比べると1回の処理自体は重いです。)

http://homepage1.nifty.com/aok2/04oldpage/win01. …

あと少しでもパフォーマンスをよくするなら
inline展開してはどうでしょう。
inline void WaitTimer( DWORD wait )
{
(略)
}

QueryPerformanceCounter自体にも処理がかかるので
事前にそれらの処理にかかる時間を計算しておき
その値を差し引くとより厳密になるかもしれません。


http://www14.big.or.jp/~ken1/tech/tech19.html

参考URL:http://homepage1.nifty.com/aok2/04oldpage/win01.html,http://www14.big.or.jp/~ken1/tech/tech19.html

この回答への補足

以下のような関数を作って14.3msec(70Hz)で動作させて見ました。
Xeon 2.8GHzのパソコンの場合、変動幅0.5msecで動作しています。(外部出力をオシロで計測)


//-----------------------------------------------
// Nameint WaitMillisec( int wait )
// Parameter(s)wait:Wait time(msec)
// Return void
// Description
//-----------------------------------------------
int WaitMillisec( int wait )
{
int r, ret;
register LONGLONG goal, freq, cnt;

r = QueryPerformanceFrequency( (LARGE_INTEGER *)&freq );
if( r == 0 ){
ret = V_Error;
}
else{
QueryPerformanceCounter( (LARGE_INTEGER *)&goal );
goal += freq * (LONGLONG)wait /1000;
ret = V_Ok;
do{
QueryPerformanceCounter( (LARGE_INTEGER *)&cnt );
}while(goal>cnt);
}
return(ret);
}

補足日時:2005/02/02 12:23
    • good
    • 0
この回答へのお礼

早速inline展開を試してみましたが、効果はありませんでした。
次にQueryPerformanceCounter関数を使ったところ、予想以上に上手くいっています。
有難うございました。

お礼日時:2005/02/02 12:16

まず、通常のWindowsはms単位での時間精度は確保できないOSであることを覚えておいてください。


それとマルチスレッドで同時に複数動いてますから、他によりプライオリティの高いスレッドが動作すると待たされるということも。(例えば通常のスレッドはマウスの移動で待ちが発生する)
また、スレッドのスイッチ等は確か10msか1msの単位です。
Sleepはスレッドのスイッチになりますから、この時間以下の精度は出せません。

時間の計測ならQueryPerformanceCounter等で高精度にできますが、msecの精度で処理をさせるのは多種のテクニックを使ってもあまり高精度にはできません。
通常はリアルタイム処理可能なOSを使うとか、Windowsならリアルタイム処理をさせるためのソフトを組み込む等になります。

管理者特権でリアルタイムプライオリティを使うとある程度改善します。
また、某所の仕事で時間精度を要求される時には拡張ボードでハードウェアによるタイマ割り込みを使い
精度を得てました。

この回答への補足

アドバイス有難うございました。
私も元は組込み用ソフトの開発者ですのでスレッドは気にしていたのですが、今回の制御は100Hz以下の周期であまり精度も求めていなかったので、速いPCならスレッドの影響を受けないだろうという考えがそもそも間違えでした。
f^_^;10msec以上のぶつ切りスレッドとは思いませんでした。

やはり定石どおり、今後は速い制御についてはハードを組みます。

補足日時:2005/02/02 12:25
    • good
    • 0

マルチメディアタイマーとかパフォーマンスカウンタってのはどうですか?

    • good
    • 0
この回答へのお礼

MetalKingさんのアドバイスは調べる手助けになりました。
有難うございました。

お礼日時:2005/02/02 12:14

ここら辺に参考になるのがあるかも

http://www.cybernet.co.jp/matlab/support/helpdes …
TICカウンタ使ったり、base clkとcpu倍率とって周波数測定したり、ですかね

この回答への補足

私はMatlabを良く知らないのですが、この方法はダメなようでした。
ありがとうございました。

補足日時:2005/02/02 12:06
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!