【Python】Python ~ 非同期 / マルチスレッド ~

■ はじめに

https://dk521123.hatenablog.com/entry/2023/04/19/232949

で、非同期処理について扱ったが、
今回は、非同期処理の基本、マルチスレッドを扱う。

後、現場で、GIL(Global Interpretation Lock)がでてきたので
とりあえず、メモる。

目次

【1】並列処理
 1)マルチスレッド
 2)マルチプロセス
【2】GIL(Global Interpretation Lock)
【3】サンプル
 例1:実験コード

【1】並列処理

* 並列処理には、以下の2つの方式がある。
1)マルチスレッド
2)マルチプロセス

1)マルチスレッド

* 1CPUに対して複数のスレッド(作業単位)が動く
* 同じメモリを共有

2)マルチプロセス

* 複数のCPUがそれぞれのプロセスで動く
* メモリもそれぞれのプロセスが管理

【2】GIL(Global Interpretation Lock)

* Pythonインタプリタの中で動作するプログラムが、
 1CPUで1つだけ実行されることを保証する仕組み
 => そのため、複数スレッド下でもロックを持つ単一スレッドでしか実行されず、
  その他のスレッドは待機状態になる

cf. 別にPythonだけの用語ではなく、
 Rubyでもある(グローバルVMロックと呼ばれている)

https://qiita.com/ttiger55/items/5e1d5a3405d2b3ef8f40
https://qiita.com/fumitoh/items/bfc9dcec90c2a4bbcb6c
https://pydocument.hatenablog.com/entry/2023/03/21/153732

メモ

* ひとまず、以下を頭に置いておくといいかも
 + Pythonでマルチスレッド処理を実装した場合、
 1スレッドでしか実行できず、並列処理が制限されるため
 このGILが、パフォーマンスの問題を引き起こす可能性がある
 + 回避としては、マルチプロセスで処理させるなど高じる

【3】サンプル

例1:実験コード

import logging
import time
import threading

logging.basicConfig(
  level=logging.DEBUG,
  format='%(threadName)s: %(message)s'
)

def worker(x, y):
  logging.debug("start")
  time.sleep(5)
  result = x + y
  logging.debug(f"Done, {result}")
  return result

if __name__ == "__main__":
  t1 = threading.Thread(target=worker, kwargs={'x': 1, 'y': 2})
  t2 = threading.Thread(target=worker, kwargs={'x': 3, 'y': 4})
  t1.start()
  t2.start()
  print("started")

出力結果例

Thread-1 (worker): start
Thread-2 (worker): start
started (←ここまで出力し、Sleepのため、数秒まつ)
Thread-1 (worker): Done, 3
Thread-2 (worker): Done, 7

参考文献

https://kosuke-space.com/python-parallel-processing
https://zenn.dev/forrep/articles/5da59f28a7732b

関連記事

Python ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2014/08/07/231242
Python ~ 基本編 / 文字列 ~
https://dk521123.hatenablog.com/entry/2019/10/12/075251
Python ~ 非同期 / concurrent.futures ~
https://dk521123.hatenablog.com/entry/2023/04/19/232949