並列実行のための Python マルチプロセッシング

PythonBeginner
オンラインで実践に進む

はじめに

Python のマルチプロセッシングは、高い処理能力が必要な Python プログラムの実行速度を大幅に向上させる強力なツールです。この実験では、Python のマルチプロセッシングとそれを使って並列処理を行う方法について学びます。まずは簡単な例から始め、徐々に複雑な例に向かっていきます。

単純なマルチプロセッシングプログラムの作成

Python におけるマルチプロセッシングを学ぶ最初のステップは、それがどのように機能するかを示す簡単なプログラムを作成することです。このプログラムでは、単一の引数を受け取り、その数の二乗を返す関数を作成します。その後、マルチプロセッシングを使ってこの関数を複数のプロセスで実行します。

square.pyを完成させてください。

import multiprocessing

def square(x):
    return x * x

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=4)
    results = pool.map(square, range(10))
    print(results)

このコードは 4 つのプロセスのプールを作成し、map()関数を使ってsquare()関数を 0 から 9 までの範囲の各数字に適用します。その結果をコンソールに出力します。

マルチプロセッシングを使って処理速度を向上させる

Python におけるマルチプロセッシングの仕組みが理解できたので、もう少し複雑な例に移りましょう。この例では、マルチプロセッシングを使って、非常に大きな数のリストの処理速度を向上させます。

complex_square.pyを完成させてください。

import multiprocessing

def square(x):
    return x * x

if __name__ == '__main__':
    with multiprocessing.Pool(processes=4) as pool:
        results = pool.map(square, range(1000000))
    print(results[:10])

このコードは 4 つのプロセスのプールを作成し、map()関数を使ってsquare()関数を 0 から 999999 までの範囲の各数字に適用します。処理が完了したときにプロセスのプールが適切にクローズされるように、with文を使っています。その後、最初の 10 個の結果をコンソールに出力します。

プロセス間通信

Python でマルチプロセッシングを使用する場合、プロセス間で通信する必要がある場合があります。この例では、multiprocessing.Queue()関数を使用してプロセス間で共有キューを作成します。

multiprocessing_queue.pyを完成させてください。

import multiprocessing

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

def consumer(queue):
    while True:
        item = queue.get()
        if item is None:
            break
        print(item)

if __name__ == '__main__':
    queue = multiprocessing.Queue()
    process_producer = multiprocessing.Process(target=producer, args=(queue,))
    process_consumer = multiprocessing.Process(target=consumer, args=(queue,))
    process_producer.start()
    process_consumer.start()
    process_producer.join()
    queue.put(None)
    process_consumer.join()

このコードはmultiprocessing.Queue()関数を使用して共有キューqueueを作成します。その後、2 つのプロセスを作成し、それぞれがproducer()関数とconsumer()関数を呼び出します。producer()関数は 0 から 9 までの数字をキューに入れ、consumer()関数はキューから各項目を取得してコンソールに出力します。

Pool.apply_async() を使った非同期タスク

map() に加えて、multiprocessing.Pool() クラスは並列でプロセスを実行するための別のメソッドである apply_async() を提供します。このメソッドを使用すると、関数呼び出しをプロセスのプールに送信し、結果を待たずに即座に実行を続けることができます。代わりに、関数呼び出しの結果が準備できたときにコールバック関数を使用して結果を取得することができます。

slow_square.py を完成させてください。

import multiprocessing
import time

def slow_square(x):
    time.sleep(1)
    return x * x

def callback(result):
    print(result)

if __name__ == '__main__':
    pool = multiprocessing.Pool(processes=4)
    results = [pool.apply_async(slow_square, (x,), callback=callback) for x in range(10)]
    for result in results:
        result.wait()
    print("All tasks completed.")

この例では、数 x を受け取り、1 秒待った後に x の二乗を返す関数 slow_square() を定義します。また、利用可能なときに結果を単に表示するコールバック関数 callback() も定義します。

その後、4 つのプロセスのプールを作成し、apply_async() を使用して 0 から 9 までの範囲の各数に対して関数呼び出しをプールに送信します。args パラメータを使用して slow_square() 関数と引数 x を渡し、結果が準備できたときに呼び出すコールバック関数も指定します。

その後、結果のリストをループして result.wait() を呼び出して、結果が準備できるまでメインスレッドをブロックします。最後に、すべてのタスクが完了したことを示すメッセージを表示します。

まとめ

この実験では、Python のマルチプロセッシングを使って並列でプロセスを実行する方法を学びました。まず、マルチプロセッシングがどのように機能するかを示す簡単なプログラムから始め、その後、マルチプロセッシングを使って処理速度を向上させ、プロセス間でメモリを共有し、apply_async()を使って非同期タスクを実行するようなより複雑な例に移りました。この実験が終わるまでに、自分自身の Python プログラムでマルチプロセッシングをどのように使うかを十分に理解しており、より大きな処理能力と効率を達成し、必要に応じてプロセス間で通信することができるようになっているはずです。