假设我这样做:
import multiprocessing as mp
def f(x):
print x
raise OverflowError
if __name__ == '__main__':
pool = mp.Pool(processes=1)
pool.map(f, range(10))
pool.close()
pool.join()
输出:
0
3
6
9
Traceback (most recent call last):
File "test1.py", line 9, in <module>
pool.map(f, range(10))
File "/Users/usualme/anaconda/lib/python2.7/multiprocessing/pool.py", line 251, in map
return self.map_async(func, iterable, chunksize).get()
File "/Users/usualme/anaconda/lib/python2.7/multiprocessing/pool.py", line 558, in get
raise self._value
OverflowError
现在我将 map 替换为 imap_unordered:
import multiprocessing as mp
def f(x):
print x
raise OverflowError
if __name__ == '__main__':
pool = mp.Pool(processes=1)
for _ in pool.imap_unordered(f, range(10)):
pass
pool.close()
pool.join()
输出:
0
1
2
3
4
5
Traceback (most recent call last):
File "test0.py", line 9, in <module>
6
7
for _ in pool.imap_unordered(f, range(10)):
8
File "/Users/usualme/anaconda/lib/python2.7/multiprocessing/pool.py", line 659, in next
9
raise value
OverflowError
我的问题:
- 对于
map:为什么它从 0 跳到 3、6 和 9? - 对于
imap_unordered:为什么这次一直到9?有什么不同?
请您参考如下方法:
map、imap 和 imap_unordered 在 block 中处理数据。就其本质而言,他们准备好将这些 block 并行提交给多个进程。
for imap_unordered: why does it go all the way to 9 this time? What's different?
对于 imap(可能还有 imap_unordered),the default chunksize is 1 .因此,f 将实际开始执行所有值。
您可以通过传递 chunksize 参数来检查此行为。如果您将 chunksize=1 提供给 map,您将获得与其他示例类似的行为。
for map: why is it jumping from 0 to 3, 6, and 9?
虽然文档中没有提到,但似乎 map 的默认 chunksize 更“聪明”。在这里, block 大小看起来是 3,所以 block 将是 [[0,1,2],[3,4,5],[6,7,8],[9]].
我不确定为什么当您只有一个进程时仍然会发生所有这一切,但我的猜测是实现会在检查之前聚合所有结果。异常,IIRC,在子进程中被捕获并通过 IPC 序列化 - 它们是任何其他结果。
