「「time.process_time」は精度が悪いから使うべきではない」という記事をみて気になったので.
import time num = 1000 mst = 0 for _ in range(num): t0 = time.perf_counter() while True: t1 = time.perf_counter() if t1 != t0: break mst = mst + (t1 - t0) print(f'Resolution of the time.perf_counter: {mst/num:.9f} [sec]') print(time.get_clock_info('perf_counter')) #バージョン 3.3 で撤廃: この関数の挙動はプラットフォームに依存します: #必要に応じて挙動が明確に定義されている perf_counter() または process_time() を使用してください。 #16.3. time — 時刻データへのアクセスと変換-Python3.6.1ドキュメント より mst = 0 for _ in range(num): t0 = time.clock() while True: t1 = time.clock() if t1 != t0: break mst = mst + (t1 - t0) print(f'Time of the time.clock: {mst/num:.9f} [sec]') print(time.get_clock_info('clock')) mst = 0 for _ in range(num): t0 = time.process_time() while True: t1 = time.process_time() if t1 != t0: break mst = mst + (t1 - t0) print(f'Time of the time.process_time: {mst/num:.7f} [sec]') print(time.get_clock_info('process_time')) mst = 0 for _ in range(num): t0 = time.monotonic() while True: t1 = time.monotonic() if t1 != t0: break mst = mst + (t1 - t0) print(f'Time of the time.monotonic: {mst/num:.5f} [sec]') print(time.get_clock_info('monotonic')) mst = 0 for _ in range(num): t0 = time.time() while True: t1 = time.time() if t1 != t0: break mst = mst + (t1 - t0) print(f'Time of the time.time: {mst/num:.5f} [sec]') print(time.get_clock_info('time'))
Time of the time.perf_counter: 0.000000349 [sec]
namespace(adjustable=False, implementation=’QueryPerformanceCounter()’, monotonic=True, resolution=3.4800051086474995e-07)
Time of the time.clock: 0.000000355 [sec]
namespace(adjustable=False, implementation=’QueryPerformanceCounter()’, monotonic=True, resolution=3.4800051086474995e-07)
Time of the time.process_time: 0.0156250 [sec]
namespace(adjustable=False, implementation=’GetProcessTimes()’, monotonic=True, resolution=1e-07)
Time of the time.monotonic: 0.01562 [sec]
namespace(adjustable=False, implementation=’GetTickCount64()’, monotonic=True, resolution=0.015625)
Time of the time.time: 0.00100 [sec]
namespace(adjustable=True, implementation=’GetSystemTimeAsFileTime()’, monotonic=False, resolution=0.015625)
「time.perf_counter()」は非常に高精度で,分解能と同程度の精度が期待できる.
この環境では,「time.clock()」はQueryPerformanceCounter()が使われているので高精度だけど,環境依存でどの様な結果が返ってくるか分からない以上,ドキュメントに書かれている様に使わない方が良い.
「time.process_time()」は分解能は100 [ns]だが,精度は約15.6 [ms]しかない.昔,「GetProcessTimes()」を使った時は,分解能は100 [ns]程度だけど,精度はシステムタイマに依存するので,約15 [ms]程度だった覚えがある.今も変わっていない様だ.
time.monotonicは分解能と同程度の精度が期待される.PC起動から(約50日以内)の経過時間計測等,マクロな経過時間計測に良さそう.
time.timeはmonotonic=False(負値があり得る)なので,経過時間計測に用いるべきではないし,結果も一番尤もらしくない.マクロな日時計測で用いるべき.
追記:
上記は
計測環境:
Windows 10 Home(x64)
Intel Core i3 530
の話.参考までに,Linuxの場合.
計測環境:
Ubuntu 16.04.2 LTS(x86)
Celeron SU2300
Resolution of the time.perf_counter: 0.0000019219 [sec]
namespace(adjustable=False, implementation=’clock_gettime(CLOCK_MONOTONIC)’, monotonic=True, resolution=1e-09)
Resolution of the time.clock: 0.0000014790 [sec]
namespace(adjustable=False, implementation=’clock()’, monotonic=True, resolution=1e-06)
Resolution of the time.process_time: 0.0000014588 [sec]
namespace(adjustable=False, implementation=’clock_gettime(CLOCK_PROCESS_CPUTIME_ID)’, monotonic=True, resolution=1e-09)
Resolution of the time.monotonic: 0.0000018411 [sec]
namespace(adjustable=False, implementation=’clock_gettime(CLOCK_MONOTONIC)’, monotonic=True, resolution=1e-09)
Resolution of the time.time: 0.0000018256 [sec]
namespace(adjustable=True, implementation=’clock_gettime(CLOCK_REALTIME)’, monotonic=False, resolution=1e-09)
やはり,Windowsに比べてLinuxは分解能が高い.各関数については,Windowsの場合と同じ事が云える.time.timeは実時刻を計測したい場合に用いるべきで,処理時間(経過時間)の計測に用いるべきではない.処理の実時間(経過実時間)を得たいなら「CLOCK_MONOTONIC(time.perf_counter)」だし,計算コストとか処理にかかる時間(CPU時間)を知りたい場合は「CLOCK_PROCESS_CPUTIME_ID(time.process_time)」が望ましいだろう.
それに,timeitモジュールのデフォルトタイマーが「time.perf_counter()」である事を考えても,「time.perf_counter()」がリーズナブルチョイスになるだろう.
ピンバック: disで手軽にPython バイトコードの逆アセンブル | 粉末@それは風のように (日記)
ピンバック: Python(Numpy)で近似エントロピー(ApEn;Approximate Entropy ) | 粉末@それは風のように (日記)