Skip to content

Pythonのマルチプロセス処理について

公開日:November 22, 2024更新日:November 23, 2024
pythoncoding📄

Pythonのマルチプロセス処理について

Pythonでは、大量のデータを処理したりCPUのリソースを最大限に活用するために「マルチプロセス処理」を使うことができます。特に、PythonのGlobal Interpreter Lock (GIL)があるため、CPUバウンドのタスクではマルチスレッドよりもマルチプロセスが適している場合があります。ここでは、Pythonのmultiprocessingライブラリを使ったマルチプロセス処理について詳しく説明します。

1. マルチプロセス処理の基礎

Pythonのmultiprocessingライブラリを使うと、複数のプロセスを並行して実行することができます。各プロセスは独立してメモリ空間を持つため、PythonのGILの影響を受けません。

プロセスの作成と実行

以下は、multiprocessingライブラリを使ってプロセスを作成する基本的な例です。

python
from multiprocessing import Process
import time

def task(name):
    print(f"{name} 開始")
    time.sleep(2)
    print(f"{name} 終了")

if __name__ == "__main__":
    process1 = Process(target=task, args=("プロセス1",))
    process2 = Process(target=task, args=("プロセス2",))

    process1.start()
    process2.start()

    process1.join()
    process2.join()

このコードでは、2つのプロセスが並行して実行されます。start()でプロセスを開始し、join()でプロセスの終了を待ちます。

マルチプロセスの利点

  • GILの回避: 各プロセスは独立したPythonインタープリタを持つため、GILの制約を受けずに並列実行が可能です。
  • CPUバウンドタスクに適している: 複数のCPUコアを使用することで、計算負荷の高い処理を効率よく実行できます。

2. プロセス間の通信

マルチプロセスでは、複数のプロセス間でデータを共有したり通信することが必要になる場合があります。multiprocessingライブラリには、プロセス間通信を行うためのさまざまな仕組みが用意されています。

キューを使ったプロセス間通信

Queueを使って、プロセス間でデータをやり取りすることができます。

python
from multiprocessing import Process, Queue

def producer(queue):
    for i in range(5):
        queue.put(i)
        print(f"生産者: {i} をキューに追加しました")


def consumer(queue):
    while not queue.empty():
        item = queue.get()
        print(f"消費者: {item} を取り出しました")

if __name__ == "__main__":
    queue = Queue()
    p1 = Process(target=producer, args=(queue,))
    p2 = Process(target=consumer, args=(queue,))

    p1.start()
    p1.join()

    p2.start()
    p2.join()

このコードでは、producerプロセスがキューにデータを追加し、consumerプロセスがそのデータを取り出して処理しています。

Pipeを使ったプロセス間通信

Pipeもプロセス間通信のための便利な手段です。Pipeは双方向の通信チャネルを提供し、データをプロセス間で送受信できます。

python
from multiprocessing import Process, Pipe

def sender(pipe):
    pipe.send("Hello from sender!")
    pipe.close()

def receiver(pipe):
    message = pipe.recv()
    print(f"受信者: {message}")

if __name__ == "__main__":
    parent_conn, child_conn = Pipe()
    p1 = Process(target=sender, args=(child_conn,))
    p2 = Process(target=receiver, args=(parent_conn,))

    p1.start()
    p2.start()

    p1.join()
    p2.join()

このコードでは、senderプロセスがメッセージを送信し、receiverプロセスがそのメッセージを受信しています。

3. プロセスプール(Pool

Poolを使うことで、複数のプロセスを簡単に管理し、大量のタスクを効率的に並列処理することができます。以下は、Poolを使って数値の2乗を計算する例です。

python
from multiprocessing import Pool

def square(x):
    return x * x

if __name__ == "__main__":
    with Pool(4) as pool:
        numbers = [1, 2, 3, 4, 5]
        results = pool.map(square, numbers)
        print(results)

このコードでは、Poolを使ってリスト内の数値の2乗を並列に計算しています。map()メソッドを使うことで、関数をリスト内の各要素に適用できます。

まとめ

マルチプロセス処理は、PythonでCPUバウンドのタスクを効率的に処理するために非常に有用です。multiprocessingライブラリを使うことで、プロセスの作成、プロセス間通信、そしてプロセスプールを活用した並列処理が簡単に行えます。マルチスレッドとは異なり、GILの制約を受けないため、CPUリソースを最大限に活用できるのが特徴です。

次に、非同期処理、マルチスレッド、マルチプロセスの違いを理解した上で、実際のシステムにおいてどの方法が最適かを選択するためのパフォーマンスチューニングについて学ぶのもおすすめです。これらの知識を駆使して、効率的でスケーラブルなプログラムを書いていきましょう!