Python並行処理: 徹底比較と実践
はじめに
Pythonの並行処理を徹底比較し、最適な手法を選べるようにします。マルチスレッド、マルチプロセス、asyncioの違い、具体的な使用例、パフォーマンス比較を通じて、効率的な並行処理を実装しましょう。
並行処理とは
並行処理とは、複数のタスクを同時に実行するように見せかける技術です。これにより、プログラムの実行効率を向上させることができます。Pythonでは、主に以下の3つの方法で並行処理を実現します。
- マルチスレッド
- マルチプロセス
- asyncio
マルチスレッド
概要
マルチスレッドは、一つのプロセス内で複数のスレッドを生成し、並行にタスクを実行します。Pythonのthreadingモジュールを使用します。
使用例
import threading
def task(name):
print(f"Thread {name}: starting")
# 何らかの処理
print(f"Thread {name}: finishing")
threads = []
for i in range(3):
t = threading.Thread(target=task, args=(i,))
threads.append(t)
t.start()
for t in threads:
t.join()
print("All threads finished")
注意点
PythonのGIL(Global Interpreter Lock)により、CPUバウンドな処理では実際には並列実行されません。I/Oバウンドな処理に適しています。
GILによる制限があるため、CPUバウンドな処理には不向きです。
マルチプロセス
概要
マルチプロセスは、複数のプロセスを生成し、並行にタスクを実行します。Pythonのmultiprocessingモジュールを使用します。
使用例
import multiprocessing
def task(name):
print(f"Process {name}: starting")
# 何らかの処理
print(f"Process {name}: finishing")
processes = []
for i in range(3):
p = multiprocessing.Process(target=task, args=(i,))
processes.append(p)
p.start()
for p in processes:
p.join()
print("All processes finished")
利点
GILの影響を受けないため、CPUバウンドな処理でも並列実行が可能です。
asyncio
概要
asyncioは、シングルスレッドで並行処理を実現するフレームワークです。イベントループを使用して、複数のコルーチンを切り替えながら実行します。
使用例
import asyncio
async def task(name):
print(f"Task {name}: starting")
await asyncio.sleep(1) # I/O待ちをシミュレート
print(f"Task {name}: finishing")
async def main():
tasks = [task(i) for i in range(3)]
await asyncio.gather(*tasks)
if __name__ == "__main__":
asyncio.run(main())
利点
I/Oバウンドな処理に非常に適しており、少ないリソースで高い並行性を実現できます。
パフォーマンス比較
各手法のパフォーマンスは、タスクの種類によって異なります。一般的に、I/Oバウンドな処理ではasyncioが、CPUバウンドな処理ではマルチプロセスが有利です。
| 手法 | 得意な処理 | 苦手な処理 |
|---|---|---|
| マルチスレッド | I/Oバウンド | CPUバウンド (GILによる制限) |
| マルチプロセス | CPUバウンド | プロセス生成のオーバーヘッド |
| asyncio | I/Oバウンド | CPUバウンド (シングルスレッド) |
まとめ
Pythonの並行処理には、マルチスレッド、マルチプロセス、asyncioの3つの主要な手法があります。タスクの特性に応じて最適な手法を選択することで、効率的な並行処理を実現できます。
並行処理の手法を選ぶ際は、タスクの種類(I/OバウンドかCPUバウンドか)を考慮しましょう。



コメント