Skip to content

multiprocessing#

multiprocessing パッケージは、ローカルとリモート両方の並行処理を提供します。また、このパッケージはスレッドの代わりにサブプロセスを使用することにより、グローバルインタープリタロック の問題を避ける工夫が行われています。

構文
from multiprocessing import Process

if __name__ == "__main__":
    p1 = Process(name="プロセス名", target=実行する関数, args=(関数の引数,))

Warnig

if name == 'main':がないとエラーとなります。

Process クラス#

multiprocessing モジュールでは、はじめに Process のオブジェクトを作成し、続いて start() メソッドを呼び出します。

from multiprocessing import Process

def f(name):
    print('hello', name)

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()

プロセス間での状態の共有#

プロセス間のデータ共有が必要な場合のために multiprocessing モジュールには2つの方法が用意されている。

共有メモリ (Shared memory)#

データを共有メモリ上に保持するために Value クラス、もしくは Array クラスが用意されている。

from multiprocessing import Process, Value, Array

def f(n, a):
    n.value = 3.1415927
    for i in range(len(a)):
        a[i] = -a[i]

if __name__ == '__main__':
    num = Value('d', 0.0)
    arr = Array('i', range(10))

    p = Process(target=f, args=(num, arr))
    p.start()
    p.join()

    print(num.value) 
    # 3.1415927

    print(arr[:])
    # [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]

num と arr を生成するときに使用されている、引数 'd' と 'i' は array モジュールにより使用される種別の型コードです。 ここで使用されている 'd' は倍精度浮動小数、 'i' は符号付整数を表します。これらの共有オブジェクトは、プロセスセーフでありスレッドセーフです。

サーバープロセス (Server process)#

Manager() 関数により生成されたマネージャーオブジェクトはサーバープロセスを管理します。 マネージャーオブジェクトは Python のオブジェクトを保持して、 他のプロセスがプロキシ経由でその Python オブジェクトを操作することができます。

Manager() 関数が返すマネージャは list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value, Array を サポートします。 以下にサンプルコードを示します。

from multiprocessing import Process, Manager

def f(d, l):
    d[1] = '1'
    d['2'] = 2
    d[0.25] = None
    l.reverse()

if __name__ == '__main__':
    with Manager() as manager:
        d = manager.dict()
        l = manager.list(range(10))

        p = Process(target=f, args=(d, l))
        p.start()
        p.join()

        print(d)
        print(l)

戻り値#

Python 3では、multiprocessingモジュールを使用してマルチプロセス処理を実行することができます。マルチプロセス処理によって、並列処理による高速化が可能になります。

マルチプロセスで戻り値を取得するには、multiprocessingモジュールのProcessクラスを使用します。以下は、戻り値を取得するための簡単な例です。

from multiprocessing import Process, Queue

def worker(queue):
    result = "This is the result"
    queue.put(result)

if __name__ == '__main__':
    queue = Queue()
    p = Process(target=worker, args=(queue,))
    p.start()
    p.join()
    result = queue.get()
    print(result)

この例では、worker関数が新しいプロセスで実行されます。worker関数は、Queueオブジェクトを受け取り、結果をQueueに入れます。 親プロセスは、子プロセスを開始し、終了するまで待機し、Queueから結果を取得して表示します。

注意すべき重要な点として、上記のコードはif name == 'main':以下に置かれています。 これは、マルチプロセス処理を行う場合に必要なもので、Windowsなどの環境で実行する場合は必要になることがあります。