簡體   English   中英

如何在python中並行化大的for循環

[英]how to parallelize big for loops in python

我剛接觸Python,我仍處於學習曲線的陡峭階段。 感謝您提前發表任何意見。

我有一個很大的for循環運行(在很多迭代的意義上很大),例如:

for i in range(10000)
    for j in range(10000)
        f((i,j))

我認為這是一個常見的問題,如何對它進行並行化,並且在谷歌搜索了幾個小時后,我使用“多處理”模塊到達了解決方案,如下所示:

pool=Pool()
x=pool.map(f,[(i,j) for i in range(10000) for j in range(10000)])

這在循環很小時有效。 但是,如果循環很大,它實際上很慢,或者如果循環太大,有時會發生內存錯誤。 似乎python首先生成參數列表,然后將列表提供給函數“f”,甚至使用xrange。 那是對的嗎?

因此,這種並行化對我不起作用,因為我不需要將所有參數存儲在列表中。 有一個更好的方法嗎? 我感謝任何建議或參考。 謝謝。

似乎python首先生成參數列表,然后將列表提供給函數“f”,甚至使用xrange。 那是對的嗎?

是的,因為您正在使用列表推導,它明確要求它生成該列表。

(注意xrange在這里並不重要,因為你一次只有兩個范圍,每個10K長;與參數列表的100M相比,這沒什么。)

如果您希望它根據需要動態生成值,而不是一次生成100M,則需要使用生成器表達式而不是列表推導。 這幾乎總是將括號括起來的問題:

x=pool.map(f,((i,j) for i in range(10000) for j in range(10000)))

但是,正如你可以從源代碼中看到的那樣 ,如果你給它一個生成器, map最終會只列出一個列表,所以在這種情況下,這不會解決任何問題。 (文檔沒有明確說明這一點,但很難看出它如何能夠選擇一個好的chunksize來切斷迭代,如果它沒有長度...)。

而且,即使這不是真的,你仍然會再次遇到與結果相同的問題,因為pool.map返回一個列表。

要解決這兩個問題,可以使用pool.imap 它懶惰地使用迭代,並返回結果的惰性迭代器。

有一點需要注意的是,如果你沒有傳遞一個, imap不會猜測最好的chunksize,但是默認為1 ,所以你可能需要一些思考或試驗和錯誤來優化它。

此外, imap在進入時仍會排隊一些結果,因此它可以按照與參數相同的順序將它們反饋給您。 在病理情況下,它可能最終排隊(poolize-1)/ poolize你的結果,雖然在實踐中這是非常罕見的。 如果要解決此問題,請使用imap_unordered 如果您需要知道排序,只需使用args和結果來回傳遞索引:

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM