Python:多进程池中的Yield

6
我需要并行化一个涉及到特定“yield”的函数。这只是我要处理的整个程序的简单副本,但总结了我所面临的问题。在这里,我正在尝试理解多进程、apply_async和yield对我的项目的作用。 在这个示例中,我使用了multiprocessing.pool,并使用apply_async进行并行化。我在“parallel”函数中放置了一些打印语句,但它们没有被打印出来。 当我将yield替换为return时,打印语句得以反映。我不确定yield的性质。我知道它是一个生成器,只能在返回后使用一次。请指导如何使其正常工作。
import multiprocessing as mp
results=[]

def parallel(x, y, z):
    print "aim in parallel"
    count=0
    result=[]
    for line in range(10000):
        count+=1
    result.append(count)
    p=x**3+y+z
    print " result"
    print result
    print p
    if p > 0:
       return result
#      yield result, p
#      count += 1
#      yield p, result
#      count += 1

def collect_results(result):
   print "aim in callback"
   results.append(result)
   #print results


def apply_async_with_callback():
    pool    = mp.Pool(processes=10)
    r = range(10)
    [pool.apply_async(parallel, args=(2,5, 7),callback=collect_results) for i in r ]
    pool.close()
    pool.join()
    print "length"
    print len(results)
    print results

if __name__ == "__main__":
    apply_async_with_callback()
1个回答

5

当一个包含yield语句的函数被调用时,它实际上并不运行代码,而是返回一个生成器:

>>> p = parallel(1, 2, 3)
>>> p
<generator object parallel at 0x7fde9c1daf00>

然后,当下一个值被需要时,代码会一直运行直到产生一个yield的值:
>>> next(p)
([10000], 6)
>>> next(p)
(6, [10000])

在您的情况下,results包含10个已经异步创建的生成器,但它们从未被实际运行过。
如果您想使用一个生成器,您可以稍微改变您的代码来指向一个从生成器中创建列表的函数:
def parallel2(x, y, z):
    return list(parallel(x, y, z))

def collect_results(lst):
   results.extend(lst)

def apply_async_with_callback():
    pool = mp.Pool()
    for _ in range(10):
        pool.apply_async(parallel2, args=(2, 5, 7),
                         callback=collect_results)

1
我不明白这如何有助于我的问题,因为我的问题类似,而且我想并行化的函数实际上是生成器。如果我理解正确的话,把它转换成列表只会使它运行每个迭代,这将花费与在for循环中使用生成器相同的时间? - Veggiet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接