2017-02-15 120 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()