如何在python中并行化大for循环

如何在python中并行化大for循环,第1张

如何在python中并行化大for循环

看来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)


欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5508445.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-13
下一篇2022-12-13

发表评论

登录后才能评论

评论列表(0条)

    保存