在什么情况下我们需要使用`multiprocessing.Pool.imap_unordered`?

时间:2013-09-28 04:24:12

标签: python

返回的imap_unordered迭代器的结果排序是任意的,它似乎没有imap(我使用下面的代码检查)运行得更快,所以为什么要使用这种方法?

from multiprocessing import Pool
import time

def square(i):
    time.sleep(0.01)
    return i ** 2

p = Pool(4)
nums = range(50)

start = time.time()
print 'Using imap'
for i in p.imap(square, nums):
    pass
print 'Time elapsed: %s' % (time.time() - start)

start = time.time()
print 'Using imap_unordered'
for i in p.imap_unordered(square, nums):
    pass
print 'Time elapsed: %s' % (time.time() - start)

2 个答案:

答案 0 :(得分:32)

使用pool.imap_unordered代替pool.imap不会对代码的总运行时间产生很大影响。它可能会快一点,但不会太多。

然而,它可能会使迭代中可用的值之间的间隔更均匀。也就是说,如果您的操作可能需要非常不同的时间(而不是您在示例中使用的一致0.01秒),imap_unordered可以通过提前更快计算的值来平滑事物计算速度较慢的值。常规imap将延迟产生更快的速度,直到计算出它们之前的较慢速度(但这不会延迟工作进程继续进行更多计算,只是你看到它们的时间)。 / p>

尝试让您的工作函数在i*0.1秒内休眠,改变输入列表并在循环中打印i。您将能够看到两个imap版本之间的差异。这是我的版本(main函数和if __name__ == '__main__'样板是在Windows上正确运行所必需的):

from multiprocessing import Pool
import time
import random

def work(i):
    time.sleep(0.1*i)
    return i

def main():
    p = Pool(4)
    nums = range(50)
    random.shuffle(nums)

    start = time.time()
    print 'Using imap'
    for i in p.imap(work, nums):
        print i
    print 'Time elapsed: %s' % (time.time() - start)

    start = time.time()
    print 'Using imap_unordered'
    for i in p.imap_unordered(work, nums):
        print i
    print 'Time elapsed: %s' % (time.time() - start)

if __name__ == "__main__":
    main()

imap版本会有很长的暂停,而像49这样的值正在处理(需要4.9秒),然后它会飞过一堆其他值(在我们等待时由其他进程计算出来) 49待处理)。相反,imap_unordered循环通常不会一次暂停。它会有更频繁但更短暂的停顿,并且它的输出会更顺畅。

答案 1 :(得分:5)

imap_unordered似乎也比imap使用更少的内存。至少这是我在数百万事物上使用迭代器所经历的事情。