PYTHON MEBY

Pythonでプロセスを使う(multiprocessing)

この記事では、Pythonの`multiprocessing`モジュールを使って並列処理を行う方法を説明します。複数のCPUコアを効果的に活用し、プログラムの処理速度を向上させるための様々な手法を紹介します。

目次

プロセスとは?

プログラムの実行単位。OSは複数のプロセスを同時に実行することで並列処理を実現します。Pythonでは、`multiprocessing`モジュールを使用することで、複数のプロセスを生成し、並列処理を行うことができます。

マルチプロセスは、マルチスレッドと異なり、各プロセスは独立したメモリ空間を持つため、グローバル変数の共有による問題が発生しません。ただし、プロセス間の通信には工夫が必要です。

multiprocessingモジュールの基本

Pythonの`multiprocessing`モジュールは、マルチプロセスプログラミングを簡素化するための様々な機能を提供します。代表的なクラスとして、`Process`、`Pool`、`Queue`、`Lock`などがあります。

プロセス間通信

プロセス間でデータのやり取りを行うには、`Queue`、`Pipe`、`Manager`などの機構を利用します。`Queue`は、複数のプロセス間でデータの送受信を行うためのキューを提供します。`Pipe`は、2つのプロセス間で双方向の通信を行うためのパイプを提供します。`Manager`は、共有メモリを用いてプロセス間でデータ共有を行うための機能を提供します。

Processクラスによるプロセス生成

`Process`クラスは、新しいプロセスを生成するためのクラスです。`target`引数には実行する関数を、`args`引数には関数の引数を指定します。

import multiprocessing

def worker(num):
    print(f'Worker {num}: {num * 2}')

if __name__ == '__main__':
    processes = []
    for i in range(5):
        p = multiprocessing.Process(target=worker, args=(i,)) 
        processes.append(p)
        p.start()
    for p in processes:
        p.join()

Poolクラスによるプロセスプール

`Pool`クラスは、複数のプロセスをプールとして管理し、タスクを効率的に処理するためのクラスです。`map`メソッドを用いることで、複数のデータに対して関数を並列実行することができます。

import multiprocessing

def worker(num):
    return num * 2

if __name__ == '__main__':
    with multiprocessing.Pool(processes=5) as pool:
        results = pool.map(worker, range(10))
        print(results)

Queueクラスによるプロセス間データ共有

`Queue`クラスは、プロセス間でデータの送受信を行うためのキューを提供します。`put`メソッドでデータを追加し、`get`メソッドでデータを取得します。

import multiprocessing

def producer(queue):
    for i in range(5):
        queue.put(i)

def consumer(queue):
    while True:
        try:
            item = queue.get()
            print(f'Consumed: {item}')
        except queue.Empty:
            break

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    producer_process = multiprocessing.Process(target=producer, args=(queue,))
    consumer_process = multiprocessing.Process(target=consumer, args=(queue,))
    producer_process.start()
    consumer_process.start()
    producer_process.join()
    consumer_process.join()

ロックによる排他制御

複数のプロセスが共有資源に同時にアクセスすると、データの破損が発生する可能性があります。`Lock`クラスは、排他制御を行うためのロックを提供します。`acquire`メソッドでロックを取得し、`release`メソッドでロックを解放します。

マネージャーによる共有データ管理

`multiprocessing.Manager`を使うと、プロセス間で安全に共有できるオブジェクトを作成できます。これにより、`Queue`や`Lock`をより簡単に使用できるようになります。

例外処理

マルチプロセス処理では、例外処理が重要になります。`try...except`ブロックを使用して、予期しないエラーが発生した場合に適切に処理を行う必要があります。

関連記事