[英]How to use a generator as an iterable with Multiprocessing map function
當我使用生成器作為 multiprocessing.Pool.map 函數的可迭代參數時:
pool.map(func, iterable=(x for x in range(10)))
似乎在func
之前生成器已完全耗盡。
我想產生每個項目並將其傳遞給每個進程,謝謝
multiprocessing.map
在處理之前將沒有__len__
方法的迭代轉換為列表。 這樣做是為了幫助計算塊大小,池使用它來對工作參數進行分組並減少調度作業的往返成本。 這不是最優的,尤其是當 chunksize 為 1 時,但由於map
必須以一種或另一種方式耗盡迭代器,所以它通常不是一個重要的問題。
相關代碼在pool.py
。 注意它對len
使用:
def _map_async(self, func, iterable, mapper, chunksize=None, callback=None,
error_callback=None):
'''
Helper function to implement map, starmap and their async counterparts.
'''
if self._state != RUN:
raise ValueError("Pool not running")
if not hasattr(iterable, '__len__'):
iterable = list(iterable)
if chunksize is None:
chunksize, extra = divmod(len(iterable), len(self._pool) * 4)
if extra:
chunksize += 1
if len(iterable) == 0:
chunksize = 0
唉,這不是很好的定義。 這是我在 Python 3.6.1 下運行的測試用例:
import multiprocessing as mp
def e(i):
if i % 1000000 == 0:
print(i)
if __name__ == '__main__':
p = mp.Pool()
def g():
for i in range(100000000):
yield i
print("generator done")
r = p.map(e, g())
p.close()
p.join()
您看到的第一件事是“生成器完成”消息,並且峰值內存使用量高得不合理(正如您懷疑的那樣,這正是因為生成器在執行任何工作之前已耗盡)。
但是,像這樣替換map()
調用:
r = list(p.imap(e, g()))
現在內存使用量仍然很小,並且“生成器完成”出現在輸出端。
但是,您不會等待足夠長的時間才能看到它,因為它非常慢:-( imap()
不僅將該可迭代對象視為可迭代對象,而且一次僅有效地跨進程邊界傳遞 1 個項目。為了恢復速度,這有效:
r = list(p.imap(e, g(), chunksize=10000))
在現實生活中,我更有可能迭代imap()
(或imap_unordered()
)結果,而不是將其強制放入列表中,然后內存使用量仍然很小,用於循環結果。
以 Tim Peters 的回答為基礎,這里有一個 jupyter notebook 展示了 imap 和 chunksize 之間的相互作用:
https://gist.github.com/shadiakiki1986/273b3529d3ff7afe2f2cac7b5ac96fe2
它有2個例子:
示例 1 使用 chunksize=1 並具有以下執行:
On CPU 1, execute item 1 from generator
On CPU 2, execute item 2 from generator
When CPU 1 done with item 1, execute item 3 from generator
When CPU 2 done with item 2, execute item 4 from generator
etc
示例 2 的 chunksize=3 執行以下操作
On CPU 1, execute items 1-3 from generator
On CPU 2, execute items 4-6 from generator
When CPU 1 done with items 1-3, execute on 7-9
When CPU 2 done with items 4-6, execute on 10
請注意,在示例 2 中,第 10 項在 CPU 2 上執行,然后在 CPU 1 上執行第 8 項和第 9 項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.