30

返回的迭代器的结果的排序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)
4

2 回答 2

45

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

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

尝试让你的工作函数休眠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循环通常不会一次暂停那么长时间。它将有更频繁但更短的暂停,并且其输出将趋于平滑。

于 2013-09-28T05:47:09.227 回答
10

随着时间的推移,imap_unordered 似乎也比 imap 使用更少的内存。至少那是我使用迭代器处理数百万事物时所经历的。

于 2014-09-03T01:04:35.863 回答