3

のための並列化機能を作成するには:次のエラーPythonのマルチプロセッシング - どのようにあなたがJupyterノートブックを開いて、これを実行するとループ

Process ForkPoolWorker-1: 
Traceback (most recent call last): 
    File "/Users/me/anaconda3/lib/python3.5/multiprocessing/process.py", line 249, in _bootstrap 
    self.run() 
    File "/Users/me/anaconda3/lib/python3.5/multiprocessing/process.py", line 93, in run 
    self._target(*self._args, **self._kwargs) 
    File "/Users/me/anaconda3/lib/python3.5/multiprocessing/pool.py", line 108, in worker 
    task = get() 
    File "/Users/me/anaconda3/lib/python3.5/multiprocessing/queues.py", line 345, in get 
    return ForkingPickler.loads(res) 
AttributeError: Can't get attribute 'g' on <module '__main__'> 

とIよを取得します

import multiprocessing 
def f(x): 
    a = 3 * x 
    pool = multiprocessing.Pool(processes=1) 
    global g 
    def g(j): 
     return a * j 
    return pool.map(g, range(5)) 
f(1) 

これがバグか機能かどうかを理解しようとしています。

私の実際のケースでは、fは基本的にforループを簡単に並列化できます(各繰り返しで1つのパラメータを変更するだけです)が、これはうまくいくようにしようとしていますが、それは各繰り返しで多くの時間がかかります!問題に正しく近づいているのですか、それとも簡単な方法がありますか? (注:ノートブックfはさまざまなパラメータで何回か呼び出されます)

答えて

2

gfの外に定義するとうまくいきます。

import multiprocessing 

def g(j): 
    return 4 * j 

def f(): 
    pool = multiprocessing.Pool(processes=1) 
    return pool.map(g, range(5)) 

f() 

編集: 例では、あなたの質問呼び出し可能オブジェクトに入れては、多少のようになります。

class Calculator(): 
    def __init__(self, j): 
     self.j = j 

    def __call__(self, x): 
     return self.j*x 

とあなたの関数fはこのようなものになり:

def f(j): 
    calculator = Calculator(j) 
    pool = multiprocessing.Pool(processes=1) 
    return pool.map(calculator, range(5)) 

私はこの場合、それはうまく動作します。それが助けてくれたらと思います。機能および任意の数の引数を取ることです、何functools.partial

import multiprocessing 
import functools 

def g(a, j): 
    return a * j 

def f(x): 
    a = 3 * x 
    pool = multiprocessing.Pool(processes=1) 
    g_with_a = functools.partial(g, a) 
    return pool.map(g_with_a, range(5)) 

f(1) 

+0

しかし、問題は、 'g'は' f'の本体で計算される変数値を使用するため、外部では定義できないということです。この状況を反映した私の編集された質問を参照してください – gota

+1

この場合、私はこれが助けになると信じています http://stackoverflow.com/questions/4827432/how-to-let-pool-map-take-a-lambda-function –

+0

私それを取得しないでください!これがバグか機能なのかどうか分かりません。 – gota

1

あなたはこのようなfunctools.partialを使用することができますpool.mapによって渡されただけイテレータ要素よりも多くの引数にgを適用する場合(位置とキーワードの両方で)、渡された関数のように動作する新しい関数を返しますが、渡さなかった引数はpartialにしかなりません。

partialによって返された関数は、問題なくiピクルスできます。 e。あなたがpython3を使っている限り、pool.mapに渡されます。

これはDarth Kotikと本質的に同じですが、は既にあなたが望むことをしているので、Calculatorクラスを自分で実装する必要はありません。

+0

うわー!!!私はこれを試してみよう! – gota