HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2008
1015
kenawaitについて15解決


ken

リンク

2008/10/15(Wed) 12:51:32|NO.20178

以下はawaitにかかる時間を計測しようとするものですがawaitのパラメーターを変化させても
結果は10ms単位にしか変わらないのは何故ですか?

repeat 21,1 s= gettime(7) await cnt ss=gettime(7)-s if ss<0 :ss=ss+1000 mes ss loop



この記事に返信する


ヒカリ

リンク

2008/10/15(Wed) 16:38:48|NO.20185

mesで表示した結果が2桁しかないということですか?
それなら、4行目で差を求めているからではないでしょうか。



M

リンク

2008/10/15(Wed) 19:24:43|NO.20194

ウィンドウズの仕様です。

モジュールかプラグインを探してください。



AziO

リンク

2008/10/15(Wed) 22:40:15|NO.20208

Windows XP以外ではそのようになるようです。



ken

リンク

2008/10/17(Fri) 12:13:42|NO.20283

回答ありがとうございます。

>Windows XP以外ではそのようになるようです。
XPでもなります。

awaitのHelpには p1=0〜(0) : 待ち時間(1ms単位) とありますが
どう解釈すれば良いのでしょう?
1msの単位まで指定できるけど実際は10ms単位なのですか?



SYAM

リンク

2008/10/17(Fri) 14:12:23|NO.20285

await命令が利用しているであろう、Windowsのタイマー機能はそんなに精度は高くないです。

それと、計測プログラムにも微妙ーに間違いがあります。結果にほとんど影響はしてないと思いますが、await命令の動作を考えると、これでは正しい時間を測れていません。
loopの直前にたとえば a=1 を10万回繰り返すとか大きな画像を読み込むとかして、少し時間のかかる処理(wait,await以外)を入れてみてください。
関係ないはずのawait命令の所要時間が変化してしまうはずです。
理由はawait命令のヘルプをよく読んでみれば分かると思います。



ken

リンク

2008/10/17(Fri) 15:15:16|NO.20286

時間のかかる処理を入れてみました。

repeat 20 s= gettime(7) await cnt ss=gettime(7)-s if ss<0 :ss=ss+1000 mes "await"+cnt+"="+ss repeat 200 title ""+cnt loop loop
ますます分からなくなりました。
await 3までは前回のawaitからは間に合わないので0になってawait 4からは時間が余って数値が
多くなると思うのですが?



ヒカリ

リンク

2008/10/17(Fri) 21:51:28|NO.20292

ちょっと調べものしてみました。

kenさんのコードを実行した結果、私のPCでもawait 4以上のssの値はほぼ0でした。
awaitが利用しているタイマーは起動直後の取得に問題があるように思います。

解決策として、kenさんのプログラムの先頭にwait 300などを入れて、
起動後に数秒待機させてみてください。
ssの値がすべて0になるはずです。
ss=0というのはawaitで指定した時間がrepeat 200〜loopの処理で
すでに超えてしまっているためです。

repeat 200〜loopの処理は平均で47msでした。await 47に相当します。
ですので、await cntの部分をawait cnt+40に変更すれば
だいたい8ループ目からssが変化してきます。


ちなみにwait 1は10ms待ち。await 1は1ms待ちです。
以下を実行してみてください。

mes ""+gettime(6)+":"+gettime(7) wait 100 mes ""+gettime(6)+":"+gettime(7) await 1000 mes ""+gettime(6)+":"+gettime(7) await 1000 mes ""+gettime(6)+":"+gettime(7)
うまくいけばかなり精度よく動作しているはずです。

月並な調査ですが参考にしてみてください。



naznyark

リンク

2008/10/18(Sat) 02:59:54|NO.20296

> 結果は10ms単位にしか変わらないのは何故ですか?

時間計測に gettime を使っているからです。

そもそも gettime の分解能は環境依存の値であって、
なおかつ大抵の場合 1ms 単位での計測を行えるほど高くはありません。
(つまり gettime(7) で取得できる値は 1ms ごとに 1 ずつ増えるのではなく
例えば 12ms ごとにまとめて 12 増える、といった感じで動作します。)

このため gettime(7) を使って 1ms 単位での計測を行おうとしても
正確な結果にはなりません



YOYO

リンク

2008/10/18(Sat) 12:11:28|NO.20298

>時間計測に gettime を使っているからです
それはそうだけど、根本的にはSYAMさんの言うように
>await命令が利用しているであろう、Windowsのタイマー機能はそんなに精度は高くないです。
です。
awaitは待機時間の計算にGetTickCount、実際の待機処理にMsgWaitForMultipleObjectsを
つかっているのでawaitの精度はこの二つの関数の精度に影響され、GetTickCountの精度は
XPでは10ms、98やMeでは5ms程度なのでawaitの精度もほぼそれと同じくらいの精度になる。
どうしても1msの精度で制御したければtimeGetTime + timeBeginPeriodかQueryPerformanceCounter
を使って自分で制御すればいい。
ただQueryPerformanceCounterは使うPCによっては信用できないのでtimeGetTimeが無難かな。



SYAM

リンク

2008/10/18(Sat) 12:18:45|NO.20300

ここまでで、精度が低いことについてはたくさん説明がついたと思います。
ですから、そもそも要求したことが
「awaitにかかる時間の計測」
というのであれば、15msくらいを単位とした値が取れる…という結果で「正しい」といえます。

んで、最初のスクリプトは

repeat 21,1 await 1 s= gettime(7) await cnt ss=gettime(7)-s if ss<0 :ss=ss+1000 mes ss loop

…こうしないと、if以降の処理にかかった時間が誤差になりますね。



ken

リンク

2008/10/19(Sun) 09:47:32|NO.20313

皆さんありがとございます。

>時間計測に gettime を使っているからです。
そうですか、測る物差しが精度がないということですね。

ようするにawaitもgettimeも単位はmsだが分解能はせいぜい10数msということですね。

ただ
>起動後に数秒待機させてみてください。
>ssの値がすべて0になるはずです。
確かにすべて0になりますが理由が分りません。



ヒカリ

リンク

2008/10/19(Sun) 23:42:02|NO.20340

>確かにすべて0になりますが理由が分りません。
なにやら混乱を招いてしまったようで申し訳ないです。
起動直後の命令の実行にかかる時間が不安定なようなので。
まだ教える側は難しいかな。
waitとawaitの違いがわかっていれば失礼かもしれませんが、一応過程を書いておきます。

 最初にawait 1で待機
    ↓
 repeat 200〜loopでだいたい50msかけて描画
    ↓
 次にawait 2で2ms待機するはずだけど、描画で2ms以上かかっているので待ち時間は0ms



ken

リンク

2008/10/20(Mon) 12:45:38|NO.20342

gettime(7)の代わりにtimeGetTimeにしました。
repeat 100 〜loopは自分の環境では約100msです。(P4 1.7GHz winXP)

約100msのloopの中にあるawait1〜20は間に合わないから全て0になるはず。
以下が現在の疑問点です。
wait 100をコメントアウトするとawait1〜await4までは0以外の数値になるのは何故か?
wait 100を含めると状況が変わるのは何故か?


#uselib "winmm.dll" #func timeBeginPeriod "timeBeginPeriod" int #func timeEndPeriod "timeEndPeriod" int #cfunc timeGetTime "timeGetTime" onexit *exit timeBeginPeriod 1 wait 100;状況が変わる repeat 21 s= timeGetTime() await cnt ss=timeGetTime()-s mes "await"+cnt+"="+ss repeat 100 ;このloop約100ms title ""+cnt loop loop stop *exit timeEndPeriod 1 end



naznyark

リンク

2008/10/22(Wed) 03:19:09|NO.20358

> wait 100をコメントアウトするとawait1〜await4までは0以外の数値になるのは何故か?
> wait 100を含めると状況が変わるのは何故か?

まず前提として await の動作の概略を説明しておくと以下のようになります。

1. 前回からの経過時間に応じて実際の待ち時間を計算。
2. 待ち時間を指定してシステムに制御(プログラムの実行権)を渡す。
3. (システム)システム内部や他アプリの処理。
4. (システム)指定した待ち時間が過ぎていればプログラムに制御を返す。
でなければ3に戻る。
5. プログラムの実行再開。

この流れの中の 3 で指定した待ち時間より時間のかかる処理が行われた場合は
指定した待ち時間より余分に時間がたってからプログラムに制御が返されます。
つまり待ち時間なしでシステムに制御を渡してもシステム内部(や他アプリ)の
処理に時間がかかればその分待ち時間が発生してしまいます。
(多くの処理は余分な待ち時間が発生しないような短い時間で処理されますが、
ある程度長い時間を必要とする処理もどうしても存在します。)


またプログラムの実行開始と同時にプログラムの実行に伴う
システム内部での処理が発生します。


以下は推測になりますが上記の説明を踏まえて

・プログラムの実行開始と同時にプログラムの実行に伴う
 システム内部での処理が発生する。
 (待ち時間 0 指定の await で余分な待ち時間が発生するような処理を含む。)

・wait なしの場合はプログラム内での計測処理とシステム内部での処理が
 並行して行われることになり、それが await の実際の待ち時間に影響を及ぼす。

・wait 100 がある場合はその間にシステム内部での処理はすべて完了し
 その後の await の待ち時間には影響を及ぼさない。

といったことなのではないかと思います。



ken

リンク

2008/10/23(Thu) 12:21:01|NO.20396

なるほど!
naznyarkさんありがとうございます。

awaitの動作まだ完全に理解したとはいえませんがだいぶスッキリしました。
数msのawaitでは原理的に誤差が大きくなるのも納得がいきますね。

皆さんありがとうございました。



ONION software Copyright 1997-2021(c) All rights reserved.