62 views
【1】気になったこと
Pythonでマルチスレッド処理を書いたが、全然高速化しない。
なぜ?
普段、並列処理が必要なプログラムは C++, Javaで書いているので、全然気づかなかった・・・
【2】原因調査
GIL(Global Interpreter Lock)による制約のため。
Python(特にCPython)には、GILという仕組みがある。
GILは、Pythonインタプリタ全体をロック する仕組みであり、
1つのスレッドだけがPythonバイトコードを実行できる ようにして、
メモリ管理(特にガベージコレクション)を安全にしている。
このため…
複数スレッドが同時に Pythonコードを実行することはできない。
ただし…
現在進行形で GIL制約を取り払うための取り組みが進められている とのこと。
開発者の皆さま、宜しくお願いいたします!
心の声・・・
これだけメジャーな言語になっているのに、マルチスレッドが並列実行できない状態だったんだ・・・
マルチプロセスで似たようなことは出来るが、共有メモリ管理に手間がかかるし、プロセス生成のオーバーヘッドが大きい。
早く実現してくれるといいなぁ・・・
【3】実験してみる。
(1) 4スレッドで同じ処理を実行する。
import threading import time def cpu_task(): # 1スレッドが実行する処理 count = 0 for _ in range(10**8): count += 1 time_start = time.perf_counter() threads = [] for _ in range(4): # スレッドを 4個起動する。 t = threading.Thread(target=cpu_task) threads.append(t) t.start() for t in threads: # 全スレッドの終了待ち。 t.join() time_end = time.perf_counter() print(f"{time_end - time_start:.3f} 秒かかりました。")
実行した結果は?
$ python main_4th.py
4.911 秒かかりました。
(2) 1スレッドで逐次的に処理を 4回繰り返す。
import time def cpu_task(): # 1スレッドが実行する処理 count = 0 for _ in range(10**8): count += 1 time_start = time.perf_counter() for _ in range(4): # 同じ処理を直列に 4回実行 cpu_task() time_end = time.perf_counter() print(f"{time_end - time_start:.3f} 秒かかりました。")
実行した結果は?
$ python main_1th.py
4.832 秒かかりました。
ん~ やっぱり同じ処理時間だ・・・
つまり、並列処理で高速化していないということ。
普通に考えれば、4並列で処理をしたら処理時間は 1/4近くまで縮むはず。
cpu_task()の中の処理負荷を上げても同じ結果だったので、マルチスレッドのオーバーヘッドが理由ではない。
【4】まとめ
CPythonでは、並列処理による高速化を目的に、マルチスレッド処理を使えない。
現在 GIL制約を取り払うための取り組みが進められているので、これに期待しよう。
これが解消されると、Pythonを採用できる現場が益々増えるだろう。
【5】参考情報
有用な情報をありがとうございます。 m(_ _)m
https://note.com/inagobot/n/n216193054100
https://gihyo.jp/article/2022/09/europython2022-02
https://zenn.dev/yasudakn/articles/7020cfa554e5a9
https://qiita.com/wooooo/items/827d76bddae14ca3b9d0
https://qiita.com/Toyo_m/items/992b0dcf765ad3082d0b
https://qiita.com/yusuke_hrsm/items/ded8c7c67bd704e91cf5