さて、世界70億人のPythonプログラマが手放せないのが、tqdmというプログレスバーを簡単に表示できるようにしてくれるライブラリです。
しかしながらtqdmは(当然と言えば当然ですが)複数のプロセスから1つのプログレスバーを管理することができるような設計にはなっていません。
たとえば高速化のためにmultiprocessingを用いて並列処理をしながらプログレスバーを出したいとき、tqdmはそのままでは使えないことになります。
例えば、下記のようなコードで単にtqdmのインスタンスを子プロセスに渡して中でupdateをすると…
import tqdm
import multiprocessing
def worker(pbar):
pbar.update()
ar = [i for i in range(100)]
with tqdm.tqdm(ar) as pbar:
jobs = []
for t in ar:
job = multiprocessing.Process(target=worker, args=(pbar,))
job.start()
jobs.append(job)
for job in jobs:
job.join()
実行結果はこんな感じ。
% python usage.py 1%|▉ | 1/100 [00:00<00:25, 3.89it/s]
こんなふうに、100%まで行ってくれません。
端的に説明すると、100個forkされた内部カウント0の状態をそれぞれ+1するのが100回走るだけ、だからです。
じゃあ内部カウントが常によろしく増えるために、内部カウントを無視して共有メモリで常に正しくカウントしてればいいよね、っていう単純な発想による汚いハックをしてみました。