2016-11-14 39 views
1

私は時間遅延1msで1000回ループし、合計時間を計算しています。 Google Chromeを開いていくつかのウェブサイトを閲覧したとき、合計1秒で正しく実行されました。また、それはMacbookでもうまくいきました。 私はこの問題を解決するためにどのような解決策を講じなければならないのでしょうか?違いを見るためにChromeを開いた状態でChromeを再起動してみてください。 QuoraやRedditやStackoverflowが私のシステムで開かれたときに正常に動作しました。Windowsでtime.sleep()が遅いのはなぜですか?

from timeit import default_timer as timer 
import time 
start = timer() 
for i in range(1000): 
    time.sleep(0.001) 

end = timer() 
print ("Total time: ", end - start) 

編集:私はPythonでそれを実行しませんでした。私はちょうどクロームを開き、いくつかのウェブサイトを閲覧して時間の遅延を早める。

更新日:Windowsからのタイマーの解像度です。基本的にChromeはタイマーの解像度を15.6msから1msに変更しました。この記事では、非常によく説明しています:https://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/

+0

どのようにpythonをChromeで実行していますか?これは非常に混乱しています。 –

+2

あなたの間違いは、 'sleep(0.001)'がちょうど*少なくとも* 1msではなく、ちょうどミリ秒間スリープ状態になると仮定しています。 http://stackoverflow.com/questions/9518106 –

+0

Eliに:私はPython上でそれを実行しませんでした。私はちょうどクロームを開き、いくつかのウェブサイトを閲覧して時間の遅延を早める。混乱させて申し訳ありません。 –

答えて

2

私はそれを最後に理解しました。コメントいただきありがとうございます。それらは私にそれを解決するためのヒントを与えました。これがなぜ起こったのか説明するために、Windows OSのデフォルトのタイマー分解能は15.625 msまたは64 Hzに設定されています。これはほとんどのアプリケーションで十分です。しかし、非常に短いサンプリングレートまたは時間遅延を必要とするアプリケーションでは、15.625msで十分ではありません。したがって、自分自身でプログラムを実行した場合、1000ポイントで15.6秒になってしまいます。しかし、Chromeを開くと、高解像度のタイマーが起動され、15.6ではなく1 msに変更され、プログラムが正常に動作するようになりました。

したがって、解決するために、解像度タイマを変更するには、timeBeginPeriod(period)というWindows関数を呼び出す必要がありました。幸いにも、Pythonは​​ライブラリを提供することで簡単に修正することができました。

from time import perf_counter as timer 
import time 
from ctypes import windll #new 

timeBeginPeriod = windll.winmm.timeBeginPeriod #new 
timeBeginPeriod(1) #new 

start = timer() 
for i in range(1000): 
    print (i) 
    time.sleep(0.001) 

end = timer() 
print ("Total time: ", end - start) 

警告:この高いタイマーの分解能が全体的な性能とバッテリにどのように影響するかについてお読みいただきました。私はまだ何も起こっていないと見ています、そして、Windowsタスク管理上のCPU使用量は圧倒的には見えません。しかし、あなたのアプリケーションが何らかの奇妙な振る舞いを起こす場合は、そのことを念頭に置いてください。

+1

[クリーナー実装](http://stackoverflow.com/a/38488544/205580)エラーチェックとコンテキスト管理。もちろん、これはシステム上で実行されている他のソフトウェアの恩恵を受けているため、重大なことは本当に信頼できません。重要なタイミングが必要な場合は、システムスケジューラに頼るのではなく、 'time.perf_counter()'を使ってループする方が良いでしょう。 – eryksun

+0

@eryksun:こんにちはeryksun、あなたの提案に感謝します。あなたの方法はサイクルごとの正確な時間遅延を保証するでしょうか?鉱山はまだ0.1ミリ秒または0.2ミリ秒遅れています。私の用途は一定の割合でポイントをプロットすることなので、悪いことです。率からちょっと離れていると、プロットは本当に悪くなるでしょう。 –

+0

Windowsでは、 'timer.perf_counter'は少なくとも1マイクロ秒の分解能を持つ単調時計である[' QueryPerformanceCounter'](https://msdn.microsoft.com/en-us/library/ms644904)を呼び出します。 'time.get_clock_info( 'perf_counter')'をチェックしてください。 – eryksun

関連する問題