2017-02-15 119 views
1

我想在python 2.7中使用一個工作者池和一個管理器在進程間共享一個隊列的代碼多進程遞歸算法。python遞歸算法多進程

條帶化了所有的算法細節的代碼看起來像以下之一:

from functools import partial 
from multiprocessing import Pool, Manager 

def pulse(l, c, accOut, v): 
    print l, c, v 
    if c < 3: 
     c = c + 1 
     l.append((v,c)) 
     pulse(l, c, accOut, v) 
    else:   
     accOut.put(l) 
     return 

if __name__ == "__main__": 
    pool = Pool(processes=1) 
    manager = Manager() 
    accOut = manager.Queue() 
    lNodes = manager.list(range(1, 7)) 
    partialCall = partial(pulse, list(), 0, accOut) 
    pool.map(partialCall, lNodes) 
    pool.close() 
    pool.join() 
    print "--- Lists in the queue: " 
    while not accOut.empty(): 
     print accOut.get() 

我在游泳池的sakeof簡單隻用一個工人。這與更多的工人一樣,但更加混亂。 我希望像這樣的輸出:

[] 0 1 
[(1, 1)] 1 1 
[(1, 1), (1, 2)] 2 1 
[(1, 1), (1, 2), (1, 3)] 3 1 
[] 0 2 
[(2, 1)] 1 2 
[(2, 1), (2, 2)] 2 2 
[(2, 1), (2, 2), (2, 3)] 3 2 
[] 0 3 
[(3, 1)] 1 3 
[(3, 1), (3, 2)] 2 3 
[(3, 1), (3, 2), (3, 3)] 3 3 
[] 0 4 
[(4, 1)] 1 4 
[(4, 1), (4, 2)] 2 4 
[(4, 1), (4, 2), (4, 3)] 3 4 
[] 0 5 
[(5, 1)] 1 5 
[(5, 1), (5, 2)] 2 5 
[(5, 1), (5, 2), (5, 3)] 3 5 
[] 0 6 
[(6, 1)] 1 6 
[(6, 1), (6, 2)] 2 6 
[(6, 1), (6, 2), (6, 3)] 3 6 
--- Lists in the queue: 
[(1, 1), (1, 2), (1, 3)] 
[(2, 1), (2, 2), (2, 3)] 
[(3, 1), (3, 2), (3, 3)] 
[(4, 1), (4, 2), (4, 3)] 
[(5, 1), (5, 2), (5, 3)] 
[(6, 1), (6, 2), (6, 3)] 

相反,我得到這樣的:

[] 0 1 
[(1, 1)] 1 1 
[(1, 1), (1, 2)] 2 1 
[(1, 1), (1, 2), (1, 3)] 3 1 
[(1, 1), (1, 2), (1, 3)] 0 2 
[(1, 1), (1, 2), (1, 3), (2, 1)] 1 2 
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2)] 2 2 
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3)] 3 2 
[] 0 3 
[(3, 1)] 1 3 
[(3, 1), (3, 2)] 2 3 
[(3, 1), (3, 2), (3, 3)] 3 3 
[(3, 1), (3, 2), (3, 3)] 0 4 
[(3, 1), (3, 2), (3, 3), (4, 1)] 1 4 
[(3, 1), (3, 2), (3, 3), (4, 1), (4, 2)] 2 4 
[(3, 1), (3, 2), (3, 3), (4, 1), (4, 2), (4, 3)] 3 4 
[] 0 5 
[(5, 1)] 1 5 
[(5, 1), (5, 2)] 2 5 
[(5, 1), (5, 2), (5, 3)] 3 5 
[(5, 1), (5, 2), (5, 3)] 0 6 
[(5, 1), (5, 2), (5, 3), (6, 1)] 1 6 
[(5, 1), (5, 2), (5, 3), (6, 1), (6, 2)] 2 6 
[(5, 1), (5, 2), (5, 3), (6, 1), (6, 2), (6, 3)] 3 6 
--- Lists in the queue: 
[(1, 1), (1, 2), (1, 3)] 
[(1, 1), (1, 2), (1, 3), (2, 1), (2, 2), (2, 3)] 
[(3, 1), (3, 2), (3, 3)] 
[(3, 1), (3, 2), (3, 3), (4, 1), (4, 2), (4, 3)] 
[(5, 1), (5, 2), (5, 3)] 
[(5, 1), (5, 2), (5, 3), (6, 1), (6, 2), (6, 3)] 

我不明白。爲什麼這個輸出?我究竟做錯了什麼?爲什麼當用v = 2調用脈衝函數時不會將新列表作爲輸入?我應該以不同的方式在部分函數中傳遞列表嗎?

我可以很容易地獲得預期的結果,在第一次調用脈衝函數時重置列表l,但我認爲它並不乾淨,並且必須有另一種方式來做到這一點。

我正在使用Windows 10 64位,並且無法更改python版本。 我已經在線尋找解決方案,但我還沒有找到任何東西。

任何幫助將不勝感激。

+0

,如果你使用的變量而不是C說名字您的代碼可能會更容易推理, v和l。 – MKesper

+1

不確定這是否與http://docs.python-guide.org/en/latest/writing/gotchas/一致,但它可能是相關的。我建議將'None'傳遞給函數,並且如果'l是None'來構造一個新列表來檢查。 – Adirio

+0

@MKesper我同意。我的結論是:「l」代表'list','c'代表'count','v'代表'value'。 – Adirio

回答

0

multiprocessing或functools模塊正在進行某種批處理,並將相同的可變list實例發送給兩個單獨的調用(link)。應該進行更深入的檢查,以通知相應的實體該beahaviour。同時,使用None作爲參數,並在迭代的第一個pulse中生成list的實例。

from functools import partial 
from multiprocessing import Pool, Manager 

def pulse(l, c, accOut, v): 
    if l is None: 
     l = [] 
    print l, c, v 
    if c < 3: 
     c = c + 1 
     l.append((v,c)) 
     pulse(l, c, accOut, v) 
    else:   
     accOut.put(l) 
     return 

if __name__ == "__main__": 
    pool = Pool(processes=1) 
    manager = Manager() 
    accOut = manager.Queue() 
    lNodes = manager.list(range(1, 7)) 
    partialCall = partial(pulse, None, 0, accOut) 
    pool.map(partialCall, lNodes) 
    pool.close() 
    pool.join() 
    print "--- Lists in the queue: " 
    while not accOut.empty(): 
     print accOut.get() 

你實際上可能要交換的說法爲了給默認值,其中一些:

from functools import partial 
from multiprocessing import Pool, Manager 

def pulse(accOut, v, l=None, c=0): 
    if l is None: 
     l = [] 
    print l, c, v 
    if c < 3: 
     c = c + 1 
     l.append((v,c)) 
     pulse(accOut, v, l, c) 
    else:   
     accOut.put(l) 
     return 

if __name__ == "__main__": 
    pool = Pool(processes=1) 
    manager = Manager() 
    accOut = manager.Queue() 
    lNodes = manager.list(range(1, 7)) 
    partialCall = partial(pulse, accOut) 
    pool.map(partialCall, lNodes) 
    pool.close() 
    pool.join() 
    print "--- Lists in the queue: " 
    while not accOut.empty(): 
     print accOut.get()