はじめに
pythonの処理時間計測ツールの定番、line_profilerだけど、マルチプロセスなプログラムで動かすのにちょい苦労したのでメモ。
どれどれ
そもそも公式ドキュメントって
https://github.com/rkern/line_profiler の下の方にあるのくらいだよね? 不親切!
で、
from multiprocessing import Process
def child(num):
...
def main():
for i in range(5):
p = Process(target=child, args=(i,))
p.start()
みたいなプログラムでボトルネックを探そうと思ってcProfileやline_profilerを使うわけだが、
from multiprocessing import Process
@profile
def child(num):
...
@proile
def main():
for i in range(5):
p = Process(target=child, args=(i,))
p.start()
なんてやってもchildの中までは計測してくれないのよね。普通の関数ならもちろんいけるよ? でも別プロセスにしちゃうとダメっぽい。cProfileも同様。で、いろいろググったり公式ドキュメント見たりしながらもサクっと正解は転がっておらず試行錯誤。(stackOverflowのQAがとても参考に)
お願い、できて
結論、子プロセスに wrap をかませることにより成功。
from multiprocessing import Process
from line_profiler import LineProfiler
def child(num):
...
def wrap(num):
prof = LineProfiler()
prof.add_function(child)
prof.runcall(child, num)
prof.print_stats()
prof.dump_stats('xxx%d.prof'%num)
def main():
for i in range(5):
p = Process(target=wrap, args=(i,))
p.start()
dump でファイル名をプロセスごとに分けてあげないと最後に終了したので上書きされてしまう模様。
おわりに
もっといい方法がありそう。