3

如果你打開一個Jupyter筆記本電腦並運行此:Python的多 - 如何創建一個並行化功能的for循環

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) 

您將獲得以下錯誤

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__'> 

和我試圖瞭解這是一個錯誤還是一個功能。

我試圖得到這個工作,因爲在我的真實案例中f基本上是一個for循環,很容易並行化(每次迭代只更改一個參數),但是每次迭代需要很多時間!我是否正確地處理了這個問題,還是有一個更簡單的方法? (注:在整個筆記本電腦將被稱爲幾次不同的參數本身)

回答

2

它工作得很好,如果你定義之外g

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)) 

我在這種情況下,它工作得很好。希望它有幫助。

+0

但問題是'g'使用了在'f'主體中計算的變量值,所以它不能在外面定義!看到我編輯的問題反映了這種情況 – gota

+1

在這種情況下:我相信這一個將幫助 http://stackoverflow.com/questions/4827432/how-to-let-pool-map-take-a-lambda-function –

+0

我不要明白!我甚至不明白這是否意味着這是一個錯誤或功能? – gota

1

如果你想申請g更多的參數比僅由pool.map通過迭代器元素,您可以使用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) 

functools.partial做什麼,是採取功能和參數的任意數量(按位置和關鍵字),並返回一個新函數,它的行爲與您傳遞給它的函數相似,但僅將您未傳遞給partial的參數。

partial返回的函數可以在沒有問題的情況下進行酸洗i。即傳遞給pool.map,只要你使用的是python3。

這與Darth Kotik在他的回答中描述的基本相同,但您不必親自實施Calculator類,因爲partial已經做到了您想要的。

+0

哇!我要試試這個! – gota