プログラミング/python の履歴(No.3)
更新プロファイリング†
python は普通に書くと思った以上に遅いことになる場合が多いので、 プロファイリングの結果を基に重い処理を numpy 側に移したりするのが役に立つ
いろいろ試した結果、特に並列処理を使ったバッチ処理が走るライブラリを使う場合には jupyter 上でのプロファイリングするとライブラリ関数の実行中に UI スレッドが動いて プロファイル結果が無茶苦茶になるようです。
したがって面倒でもプロファイルは Jupyter 外で行った方が間違いない。
前処理結果を dump する†
jupyter 上で計算した結果を引き継ぎつつ jupyter 外で処理を回すには、前処理で得られたデータ(プロファイリングしたい処理への入力)を pickle.dump しておき、外部で動かす処理ではそれを呼んで動作を行う
Jupyter セル内で実行
LANG:python
import pickle
payload = {
"param1": param1,
"param2": param2,
"param3": param3,
}
with open("payload.pkl", "wb") as f:
pickle.dump(payload, f, protocol=pickle.HIGHEST?PROTOCOL)
で(通常の python データであれば)書き出せる
読み込んで動かす .py ファイル†
do_profile.py
LANG:python
import pickle
import cProfile
import pstats
from my_module import func_to_profile
def main():
with open("payload.pkl", "rb") as f:
payload = pickle.load(f)
prof = cProfile.Profile()
prof.enable()
refined = func_to_profile(**payload)
prof.disable()
prof.dump_stats("prof.out")
if __name__ == "__main__":
main()
実行する†
LANG:console $ python do_profile.py
解析する†
LANG:console $ python -m pstats prof.out Welcome to the profile statistics browser. prof.out% strip # strip directory names prof.out% sort cumtime # sort by cumtime prof.out% stats 40 # show first 40 items
これで、
my_module.py:1234(my_function)
みたいな関数ごとに
LANG:console ncalls tottime percall cumtime percall filename:lineno(function) 呼び出し 自前処理 呼び出し 子も含む 呼び出し ファイル名:行番号(関数名) 回数 時間 あたり 全時間 あたり
のリストが出ます
特定の関数内から呼ばれている分だけを調べたければ、
LANG:console prof.out% sort time prof.out% callees my_module.py:1234(my_function)
などとします。
Counter: 456 (from 2010/06/03),
today: 2,
yesterday: 4