#mynavi(Python) #setlinebreak(on); * 目次 [#ofca2ff8] #contents -- 関連 --- [[Pythonのパフォーマンス確認]] -- 参考 --- [[科学技術計算のためのPython入門 ――開発基礎、必須ライブラリ、高速化>https://www.amazon.co.jp/gp/product/4774183881]] * 内包表記の使用 [#yd5c6460] #html(<div style="padding-left:10px;">) listb や dict の各要素に対して何らかの処理を行うような場合は、内包表記を使用した方が高速 list や dict の各要素に対して何らかの処理を行うような場合は、内包表記を使用した方が高速 確認用コード #mycode2(){{ # coding: utf-8 """内包表記の処理速度確認. リストの各値に+Nする処理の速度をforループと内包表記で比較する。 """ import time def normal(list1, num): stime = time.time() result = [] for i in list1: result.append(i + num) print('forループ - {}'.format(time.time() - stime)) return result def tuning(list1, num): stime = time.time() result = [i + num for i in list1] print('内包表記 - {}'.format(time.time() - stime)) return result if __name__ == '__main__': # 確認用のリスト list1 = range(10000) # forループ result1 = normal(list1, 2) # 内包表記 result2 = tuning(list1, 2) # 一応結果が同じか確認 print(result1 == result2) }} 結果確認 #myterm2(){{ forループ - 0.001007080078125 内包表記 - 0.0006196498870849609 True }} #html(</div>) * 高階関数の使用 [#f0761493] #html(<div style="padding-left:10px;">) #TODO #html(</div>) * ユニバーサル関数の使用 [#f0761493] #html(<div style="padding-left:10px;">) #TODO #html(</div>) * グローバル変数を使用しない [#s08ba26d] #html(<div style="padding-left:10px;">) ループや関数からグルーバル変数へのアクセスは控える。 どうしても必要な場合は、ループの外でいったんローカル変数に代入して使用する。 #html(</div>) * ループの中で自前の関数を呼ばない [#s08ba26d] #html(<div style="padding-left:10px;">) 他言語(Java等)より関数呼び出しのオーバーヘッドが大きい為、ループの中で繰り返し呼ばれるような関数はべた書きした方が速く動作する。 可読性向上の為だけに切り出したような関数はべた書きにしてしまった方が速い。 ※処理にかかる時間は べた書き < 自モジュールで定義した関数の呼出 < 他モジュールで定義した関数の呼出 mymodule.py #mycode2(){{ def func1(num): """他モジュールで定義した関数.""" return num * 2 }} call_func_cost.py #mycode2(){{ # coding: utf-8 """関数の呼び出しコストを計測する.""" import time import mymodule def func1(num): """自モジュール内に定義した関数.""" return num * 2 if __name__ == '__main__': loop = 1000000 # 他モジュール内の関数呼び出し stime = time.time() counter = 0 for i in range(loop): counter += mymodule.func1(i) print(time.time() - stime) # 自モジュール内の関数呼び出し stime = time.time() counter = 0 for i in range(loop): counter += func1(i) print(time.time() - stime) # べた書き stime = time.time() counter = 0 for i in range(loop): counter += (i * 2) print(time.time() - stime) }} 確認結果 #myterm2(){{ python3 call_func_cost.py 0.17288494110107422 0.1537008285522461 0.09762096405029297 }} #html(</div>) * 大きな変数は使用後にdelする [#s08ba26d] #html(<div style="padding-left:10px;">) #html(</div>) * numba(jitコンパイラ) による高速化 [#i75595d8] #html(<div style="padding-left:10px;">) リストやデータフレームに対する&color(red){数値計算}を繰り返し、大量に行なうようなケースでは Numba を使用すれば劇的に改善する場合がある。 ただ、数値計算以外の処理は殆どパフォーマンスは変わらない。(処理によっては遅くなるケースも多々ある) #html(</div>) * その他 [#gc1329b8] #html(<div style="padding-left:10px;">) ** 同じ事を行う場合でも記述方法によってパフォーマンスは変わる [#f0761493] #html(<div style="padding-left:10px;">) 組み込み関数でも遅いものがあるので、別の方法で実現できないか検討する。 ※ [[Pythonのstrptimeが遅い]] を参照。 #html(</div>) ** list や dict の参照コストも考慮する [#x29b5ba5] #html(<div style="padding-left:10px;">) #TODO #html(</div>) ** 可読性とはトレードオフな部分がある [#f94a0034] #html(<div style="padding-left:10px;">) #TODO #html(</div>) ** マルチスレッドは要検証 [#e15696f1] #html(<div style="padding-left:10px;">) GIL問題により、マルチスレッドにした場合にかえって遅くなる場合がある。 マルチプロセスにして1プロセス:1スレッドにする方がだいたいのケースでうまくいく。 ※コア数やメモリ量によって起動するプロセス数は考慮する事。 #html(</div>) #html(</div>)