目次 †内包表記の使用 †list や dict の各要素に対して何らかの処理を行うような場合は、内包表記を使用した方が高速 確認用コード # 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) 結果確認 forループ - 0.001007080078125 内包表記 - 0.0006196498870849609 True 高階関数の使用 †TODO:
ユニバーサル関数の使用 †TODO:
グローバル変数を使用しない †ループや関数からグルーバル変数へのアクセスは控える。 ループの中で自前の関数を呼ばない †他言語(Java等)より関数呼び出しのオーバーヘッドが大きい為、ループの中で繰り返し呼ばれるような関数はべた書きした方が速く動作する。 mymodule.py def func1(num): """他モジュールで定義した関数.""" return num * 2 call_func_cost.py # 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) 確認結果 python3 call_func_cost.py 0.17288494110107422 0.1537008285522461 0.09762096405029297 大きな変数は使用後にdelする †numba(jitコンパイラ) による高速化 †リストやデータフレームに対する&color(red){数値計算}を繰り返し、大量に行なうようなケースでは Numba を使用すれば劇的に改善する場合がある。 その他 †同じ事を行う場合でも記述方法によってパフォーマンスは変わる †組み込み関数でも遅いものがあるので、別の方法で実現できないか検討する。 list や dict の参照コストも考慮する †TODO:
可読性とはトレードオフな部分がある †TODO:
マルチスレッドは要検証 †GIL問題により、マルチスレッドにした場合にかえって遅くなる場合がある。 |