web-dev-qa-db-ja.com

時間を正確に測定するpython関数は

プログラムの特定の部分にかかる時間を測定する必要があります(デバッグではなく、出力の機能として)。合計時間が数分の1秒になるため、精度は重要です。

私は time module を使用するつもりでした timeit に遭遇したとき、これは実行時間を測定するための多くの一般的なトラップを回避すると主張しています。残念ながらそれはひどいインターフェースを持ち、文字列を入力として受け取り、それを評価します。

では、このモジュールを使用して時間を正確に測定する必要がありますか、それとも時間で十分でしょうか?そしてそれが言及する落とし穴は何ですか?

ありがとう

42
hoju

Python documentation によると、それは異なるオペレーティングシステムでの時間関数の精度と関係があります:

デフォルトのタイマー機能はプラットフォームに依存します。 Windowsでは、time.clock()の精度はマイクロ秒ですが、time.time()の精度は1/60秒です。 Unixでは、time.clock()の精度は1/100秒で、time.time()の方がはるかに正確です。どちらのプラットフォームでも、デフォルトのタイマー機能はCPU時間ではなく実時間を測定します。これは、同じコンピューター上で実行されている他のプロセスがタイミングに干渉する可能性があることを意味します... Unixでは、time.clock()を使用してCPU時間を測定できます。

_timeit.py_のコードから直接プルするには:

_if sys.platform == "win32":
    # On Windows, the best timer is time.clock()
    default_timer = time.clock
else:
    # On most other platforms the best timer is time.time()
    default_timer = time.time
_

さらに、ランタイムコードの設定も直接処理します。 timeを使用する場合は、自分で行う必要があります。もちろん、これは時間の節約になります

Timeitのセットアップ:

_def inner(_it, _timer):
    #Your setup code
    %(setup)s
    _t0 = _timer()
    for _i in _it:
        #The code you want to time
        %(stmt)s
    _t1 = _timer()
    return _t1 - _t0
_

Python 3:

Python 3.3なので、 time.perf_counter() (システム全体のタイミング)または time.process_time() を使用できます(プロセス全体のタイミング)、time.clock()の使用方法と同じです。

_from time import process_time

t = process_time()
#do some stuff
elapsed_time = process_time() - t
_

新しい関数_process_time_には、スリープ中に経過した時間は含まれません。

Python 3.7以降:

Python 3.7なので、 process_time_ns() を使用することもできます。これはprocess_time()に似ていますが、ナノ秒単位で時間を返します。

30
Sean Vieira

タイミングコンテキスト( PEP 34 を参照)を作成して、コードのブロックを簡単に測定できます。

from __future__ import with_statement
import time

class Timer(object):
    def __enter__(self):
        self.__start = time.time()

    def __exit__(self, type, value, traceback):
        # Error handling here
        self.__finish = time.time()

    def duration_in_seconds(self):
        return self.__finish - self.__start

timer = Timer()

with timer:
    # Whatever you want to measure goes here
    time.sleep(2)

print timer.duration_in_seconds()    
28
Corey Porter

Timeitモジュールは、アプリケーションの単純な監視ではなく、アルゴリズムのパフォーマンステストを行うために設計されているように見えます。最良のオプションは、おそらくtimeモジュールを使用し、関心のあるセグメントの最初と最後でtime.time()を呼び出し、2つの数値を引くことです。得られる数値は、システムタイマーの実際の分解能よりも小数点以下の桁数が多い場合があることに注意してください。

8
qid

機能が提供するプロファイルまたはcProfileを確認しましたか?

http://docs.python.org/library/profile.html

これは、関数呼び出しの前後の時刻を出力するだけではなく、より詳細な情報を提供します。一見の価値があるかもしれません...

4
AJ.

私もtimeitのひどいインターフェースに悩まされていたので、このためのライブラリを作成しました。


from pythonbenchmark import compare, measure
import time

a,b,c,d,e = 10,10,10,10,10
something = [a,b,c,d,e]

def myFunction(something):
    time.sleep(0.4)

def myOptimizedFunction(something):
    time.sleep(0.2)

# comparing test
compare(myFunction, myOptimizedFunction, 10, input)
# without input
compare(myFunction, myOptimizedFunction, 100)

https://github.com/Karlheinzniebuhr/pythonbenchmark

4
karlpy

ドキュメントには、time.clock()とtime.time()の解像度がプラットフォームによって異なることも記載されています。 Unixでは、time.clock()は実時間ではなくCPU時間を測定します。

timeitはまた、テストの実行時にガベージコレクションを無効にします。これは、おそらくプロダクションコードでは必要ありません。

ほとんどの場合、time.time()で十分だと思います。

2
Chris AtLee

Python 2.6から:もはや入力文字列に限定されません。引用 ドキュメント

バージョン2.6で変更:stmtおよびsetupパラメータは、引数なしで呼び出し可能なオブジェクトも取得できるようになりました。これにより、timeit()によって実行されるタイマー関数にそれらの呼び出しが埋め込まれます。この場合、余分な関数呼び出しのために、タイミングのオーバーヘッドが少し大きくなることに注意してください。

2
jgosmann