use*_*768 3 python parallel-processing list multiprocessing
我刚接触Python,但仍处于学习曲线的艰难阶段。感谢您的任何评论。
我有一个很大的for循环要运行(在许多迭代中都很大),例如:
for i in range(10000)
    for j in range(10000)
        f((i,j))
我虽然认为这将是一个如何并行化的常见问题,但在Google上搜索了数小时后,我使用“ multiprocessing”模块找到了解决方案,如下所示:
pool=Pool()
x=pool.map(f,[(i,j) for i in range(10000) for j in range(10000)])
当循环较小时,此方法有效。但是,如果循环很大,那确实很慢;或者如果循环太大,有时会发生内存错误。看来python会首先生成参数列表,然后甚至使用xrange将列表提供给函数“ f”。那是对的吗?
所以这种并行化对我来说不起作用,因为我真的不需要将所有参数都存储在列表中。有一个更好的方法吗?我感谢任何建议或参考。谢谢。
看来python会首先生成参数列表,然后甚至使用xrange将列表提供给函数“ f”。那是对的吗?
是的,因为您使用的是列表推导,它明确要求它生成该列表。
(请注意,xrange这里并没有什么关系,因为一次只能有两个范围,每个范围都是10K;与参数列表的100M相比,这没什么。)
如果希望它根据需要动态生成值,而不是一次生成所有100M,则要使用生成器表达式而不是列表推导。几乎总是将括号变成括号的问题:
x=pool.map(f,((i,j) for i in range(10000) for j in range(10000)))
但是,正如您从源代码中看到的那样,map如果您给它提供一个生成器,它最终只会列出一个列表,因此在这种情况下,它什么也解决不了。(文档没有明确说明这一点,但是很难看到如何在没有长度的情况下如何选择合适的块大小将可迭代对象切成碎片……)。
而且,即使事实并非如此,您仍然会再次遇到与结果相同的问题,因为会pool.map返回一个列表。
要解决这两个问题,可以pool.imap改用。它懒惰地消耗可迭代,并返回结果的惰性迭代器。
需要注意的一件事是,imap如果不通过,则不会猜测最佳的块大小,而只是默认为1,因此您可能需要一些思考或反复试验来优化它。
另外,imap仍会在输入结果时将它们排入队列,因此它可以按照参数的顺序将它们反馈给您。在病理情况下,它可能最终导致结果排队(poolsize-1)/ poolsize,尽管实际上这很少见。如果要解决此问题,请使用imap_unordered。如果您需要了解顺序,只需将参数与参数和结果来回传递即可:
args = ((i, j) for i in range(10000) for j in range(10000))
def indexed_f(index, (i, j)):
    return index, f(i, j)
results = pool.imap_unordered(indexed_f, enumerate(args))
但是,我注意到在您的原始代码中,您对的结果根本不做任何事情f(i, j)。在那种情况下,为什么还要费心收集所有结果呢?在这种情况下,您可以返回循环:
for i in range(10000):
    for j in range(10000):
        map.apply_async(f, (i,j))
但是,imap_unordered可能仍然值得使用,因为它提供了一种非常简单的方法来阻止所有任务完成,同时仍使池本身处于运行状态以供以后使用:
def consume(iterator):
    deque(iterator, max_len=0)
x=pool.imap_unordered(f,((i,j) for i in range(10000) for j in range(10000)))
consume(x)
| 归档时间: | 
 | 
| 查看次数: | 1736 次 | 
| 最近记录: |