2015-06-28 207 views
1

我試圖運行一個函數與多處理。這是代碼:蟒蛇多處理找不到錯誤

import multiprocessing as mu 

output = [] 
def f(x): 
    output.append(x*x) 


jobs = [] 
np = mu.cpu_count() 

for n in range(np*500): 
    p = mu.Process(target=f, args=(n,)) 
    jobs.append(p) 


running = [] 

for i in range(np): 
    p = jobs.pop() 
    running.append(p) 
    p.start() 

while jobs != []: 
    for r in running: 
     if r.exitcode == 0: 
      try: 
       running.remove(r) 
       p = jobs.pop() 
       p.start() 
       running.append(p) 
      except IndexError: 
       break 

print "Done:" 
print output 

輸出是[],而它應該是[1,4,9,...]。有人看到我犯了一個錯誤?

+0

Cursory瞥了一下代碼,你在哪裏等待工作完成? 'jobs.join()'在哪裏?似乎也缺乏鎖定,但我還沒有弄清楚你的邏輯。 – cdarke

+0

用while和if if r.exitcode == 0,我認爲 –

+0

@cdarke是什麼? 'None!= 0' – jonrsharpe

回答

0

編輯: 感謝@羅蘭史密斯指出。 主要問題是功能f(x)。當子進程調用這個函數時,它無法爲它們修改output變量(因爲它不是共享)。

編輯: 正如@cdarke說,在多處理你要仔細控制共享對象,子進程可以訪問(也許鎖),這是相當複雜和難以調試。

我個人建議爲此使用Pool.map方法。

舉例來說,我認爲你直接運行這個代碼,而不是作爲一個模塊,那麼你的代碼將是:

import multiprocessing as mu 

def f(x): 
    return x*x 

if __name__ == '__main__': 
    np = mu.cpu_count() 
    args = [n for n in range(np*500)] 

    pool = mu.Pool(processes=np) 
    result = pool.map(f, args) 
    pool.close() 
    pool.join() 
    print result 

但有些事情你必須知道

  1. 如果你只是運行這個文件但不能導入模塊,if __name__ == '__main__':是很重要的,因爲python會加載這個文件作爲其他進程的模塊,如果你不把函數'f'放在if __name__ == '__main__':之外,子進程將無法找到你的函數'f' **編輯:** th anks @Roland史密斯指出的是,我們可以使用元組
  2. ,如果你有一個以上args作爲函數f,那麼你可能需要一個元組這樣做,例如

     
    def f((x,y)) 
        return x*y 
    
    args = [(n,1) for n in range(np*500)] 
    result = pool.map(f, args) 
    

    或檢查here爲更詳細的討論

+0

關於2,你可以把所有參數放在一個'tuple'中。 –

+0

是的,你是對的,我與其他需要lamdba功能的方法混淆,我會編輯這個。 – Jkm

+1

並且使用多處理,問題代碼中的輸出列表* *不共享。 –

1

您正在使用multiprocessing而不是threading。所以你的output列表是而不是之間共享的進程。

有幾種可能的解決方案;

  1. 保留大部分程序,但使用multiprocessing.Queue而不是列表。讓工人把他們的結果放在隊列中,並從主程序中讀取。它會將數據從流程複製到流程,因此對於大數據量的數據來說,這會產生很大的開銷。
  2. 您可以使用multiprocessing.Array的形式共享內存。如果處理的數據很大,這可能是最好的解決方案。
  3. 使用Pool。這爲您處理所有流程管理。就像使用隊列一樣,它將數據從流程複製到流程。這可能是最容易使用的。如果發送給每個工作人員的數據很小,那麼IMO是最好的選擇。
  4. 使用threading,以便output列表在線程之間共享。 CPython中的線程有一個限制,一次只有一個線程可以執行Python字節碼,因此可能不會獲得與預期相同的性能優勢。與多處理解決方案不同,它不會利用多核。