web-dev-qa-db-ja.com

Python:マルチプロセッシングプールで値と配列を使用する方法

multiprocessingProcessの場合、argsparamを設定することでValue, Arrayを使用できます。

multiprocessingPoolを使用して、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)
    print(arr[:])

以下のコードスニペット内でValue, Arrayを使用しようとしています。

import multiprocessing


def do_calc(data):
    #  access num or 
    #  work to update arr
    newdata =data * 2
    return newdata

def start_process():
    print 'Starting', multiprocessing.current_process().name

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

    pool_size       = multiprocessing.cpu_count() * 2
    pool            = multiprocessing.Pool(processes=pool_size,initializer=start_process, )
    pool_outputs    = pool.map(do_calc, inputs)
    pool.close() # no more tasks
    pool.join()  # wrap up current tasks

    print 'Pool    :', pool_outputs
7
Merlin

私はこれの「理由」を知りませんでしたが、multiprocessingmp)は、ほとんどのPoolメソッドに渡される関数に異なるピッカー/アンピッカーメカニズムを使用します。 _mp.Value_、_mp.Array_、_mp.Lock_、...などで作成されたオブジェクトは、そのようなメソッドに引数として渡すことはできませんが、できます _mp.Process_に引数として渡されますおよびmp.Pool()のオプションのinitializer関数に渡されます。後者のため、これは機能します。

_import multiprocessing as mp

def init(aa, vv):
    global a, v
    a = aa
    v = vv

def worker(i):
    a[i] = v.value * i

if __name__ == "__main__":
    N = 10
    a = mp.Array('i', [0]*N)
    v = mp.Value('i', 3)
    p = mp.Pool(initializer=init, initargs=(a, v))
    p.map(worker, range(N))
    print(a[:])
_

そしてそれは印刷します

_[0, 3, 6, 9, 12, 15, 18, 21, 24, 27]
_

これがプラットフォーム間でこれを機能させるために私が知っている唯一の方法です。

Linux-yプラットフォーム(mpfork()を介して新しいプロセスを作成する場合)では、代わりに_mp.Array_および_mp.Value_(etc)オブジェクトをモジュールグローバルとして作成できます。時間mp.Pool()を実行します。 fork()によって作成されたプロセスは、mp.Pool()の実行時にモジュールのグローバルアドレス空間にあるものをすべて継承します。

しかし、それはfork()をサポートしないプラットフォーム(「Windows」と読みます)ではまったく機能しません。

7
Tim Peters