Flat lay of business concept
Pythonを使っていると、「もっと処理を速くしたい」「複数の作業を同時に実行したい」と思うことはありませんか?
そんなときに活用できるのが「並列処理」です。Pythonでは、threading
や multiprocessing
などの標準モジュールを使うことで、比較的簡単に並列処理を取り入れることができます。この記事では、並列処理の基本概念から、代表的なモジュールの使い方、実践的なコード例までを初心者にもわかりやすく解説します。
並列処理とは、複数の処理を同時に実行することを指します。これにより、時間のかかる処理を短縮し、プログラム全体のパフォーマンスを向上させることができます。
ただし、Pythonには「GIL(Global Interpreter Lock)」と呼ばれる制約があり、1つのインタプリタで複数スレッドが同時に実行できないという特徴があります。これが、Pythonの並列処理を少しややこしくしている理由です。
Pythonにおける並列処理は主に以下の2つに分けられます。
スレッドは処理を同時に見せかけることが得意ですが、CPU処理を多く行う場合はプロセスの方が効率的です。
Pythonの標準ライブラリであるthreading
を使えば、簡単にマルチスレッドを実装できます。以下はその基本例です。
import threading
import time
def task(name):
print(f"{name}開始")
time.sleep(2)
print(f"{name}終了")
thread1 = threading.Thread(target=task, args=("スレッド1",))
thread2 = threading.Thread(target=task, args=("スレッド2",))
thread1.start()
thread2.start()
thread1.join()
thread2.join()
print("すべてのスレッドが完了しました")
上記のように、Thread
オブジェクトを生成し、start()
メソッドで実行します。join()
を使えば、すべてのスレッドが終了するまで待機できます。
CPUをフル活用したいときはmultiprocessing
モジュールが効果的です。以下に基本例を示します。
import multiprocessing
import time
def task(name):
print(f"{name}開始")
time.sleep(2)
print(f"{name}終了")
if __name__ == '__main__':
process1 = multiprocessing.Process(target=task, args=("プロセス1",))
process2 = multiprocessing.Process(target=task, args=("プロセス2",))
process1.start()
process2.start()
process1.join()
process2.join()
print("すべてのプロセスが完了しました")
マルチプロセスの場合、各プロセスは独立したメモリ空間を持つため、データの共有にはQueue
やPipe
などを使う必要があります。
並列処理には便利な点がある一方で、以下のような注意点もあります。
Python3.2以降では、concurrent.futures
モジュールを使うことで、スレッドもプロセスもシンプルに書けるようになりました。
from concurrent.futures import ThreadPoolExecutor
import time
def task(n):
print(f"タスク{n}開始")
time.sleep(2)
print(f"タスク{n}終了")
with ThreadPoolExecutor(max_workers=3) as executor:
for i in range(5):
executor.submit(task, i)
同様に、ProcessPoolExecutor
を使えばプロセスベースの並列処理も行えます。
from concurrent.futures import ProcessPoolExecutor
def heavy_task(x):
return x * x
with ProcessPoolExecutor() as executor:
results = executor.map(heavy_task, range(10))
for r in results:
print(r)
並列処理は万能ではありませんが、以下のような場面では非常に効果を発揮します。
ただし、処理が依存し合うようなタスクでは並列化しても効果が出にくいため、状況に応じて適切な手法を選ぶことが重要です。
Pythonでの並列処理は、処理の高速化において非常に強力な手段です。threading
や multiprocessing
を使う基本から、concurrent.futures
での簡易的な実装まで幅広く紹介しました。
あなたのプログラムにどのような並列処理が最適かを見極めて、ぜひ活用してみてください。正しく使えば、今まで何倍もの時間がかかっていた処理が、驚くほどスピードアップするはずです!