簡體   English   中英

如何在 Python 中並行化生成器/迭代器的管道?

[英]How can I parallelize a pipeline of generators/iterators in Python?

假設我有一些 Python 代碼,如下所示:

input = open("input.txt")
x = (process_line(line) for line in input)
y = (process_item(item) for item in x)
z = (generate_output_line(item) + "\n" for item in y)
output = open("output.txt", "w")
output.writelines(z)

此代碼從輸入文件中讀取每一行,通過幾個函數運行它,並將輸出寫入輸出文件。 現在知道函數process_lineprocess_itemgenerate_output_line永遠不會相互干擾,我們假設輸入和輸出文件在不同的磁盤上,這樣讀取和寫入不會相互干擾。

但是 Python 可能對此一無所知。 我的理解是Python會讀取一行,依次應用每個函數,將結果寫入輸出,然后只有將第一行發送到輸出才會讀取第二行,這樣第二行就不會進入直到第一個管道退出。 我是否正確理解該程序將如何運行? 如果這是它的工作方式,是否有任何簡單的方法可以使多行可以同時在管道中,以便程序並行讀取、寫入和處理每個步驟?

你不能真正並行讀取或寫入文件; 最終,這些將成為您的瓶頸。 確定你的瓶頸是 CPU,而不是 I/O?

由於您的處理不包含任何依賴項(根據您的說法),因此使用Python 的 multiprocessing.Pool 類非常簡單。

有幾種方法可以編寫它,但更簡單的 wrt 調試是找到獨立的關鍵路徑(代碼中最慢的部分),我們將使其並行運行。 讓我們假設它是 process_item。

……事實上,就是這樣。 代碼:

import multiprocessing.Pool

p = multiprocessing.Pool() # use all available CPUs

input = open("input.txt")
x = (process_line(line) for line in input)
y = p.imap(process_item, x)
z = (generate_output_line(item) + "\n" for item in y)
output = open("output.txt", "w")
output.writelines(z)

我還沒有測試過,但這是基本思想。 池的 imap 方法確保以正確的順序返回結果。

有沒有什么簡單的方法可以使多條線路可以同時在管道中

我寫了一個庫來做到這一點: https : //github.com/michalc/threaded-buffered-pipeline ,它在一個單獨的線程中迭代每個迭代。

那是什么

input = open("input.txt")

x = (process_line(line) for line in input)
y = (process_item(item) for item in x)
z = (generate_output_line(item) + "\n" for item in y)

output = open("output.txt", "w")
output.writelines(z)

變成

from threaded_buffered_pipeline import buffered_pipeline

input = open("input.txt")

buffer_iterable = buffered_pipeline()
x = buffer_iterable((process_line(line) for line in input))
y = buffer_iterable((process_item(item) for item in x))
z = buffer_iterable((generate_output_line(item) + "\n" for item in y))

output = open("output.txt", "w")
output.writelines(z)

這增加了多少實際並行度取決於每個迭代中實際發生的事情,以及您擁有多少 CPU 內核/它們有多忙。

經典的例子是 Python GIL:如果每個步驟都相當占用 CPU,並且只使用 Python,那么不會添加太多並行性,並且這可能不會比串行版本快。 另一方面,如果每個網絡 IO 都很重,那么我認為它可能會更快。

暫無
暫無

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

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