[英]How to stream results from Multiprocessing.Pool to csv?
我有一個帶鍵的python進程(2.7),進行一堆計算並返回結果列表。 這是一個非常簡化的版本。
我正在使用多處理來創建線程,以便可以更快地處理它。 但是,我的生產數據有幾百萬行,每個循環需要花費更長的時間才能完成。 我上次運行該循環的時間超過了6分鍾,而在開始時則花費了一秒鍾或更短的時間。 我認為這是因為所有線程都將結果添加到結果集中,並且一直持續增長,直到包含所有記錄為止。
是否可以使用多重處理將每個線程(列表)的結果流式傳輸到csv或批處理結果集中,以便在設置一定數量的行之后將其寫入csv?
對於加快或優化該方法的任何其他建議將不勝感激。
import numpy as np
import pandas as pd
import csv
import os
import multiprocessing
from multiprocessing import Pool
global keys
keys = [1,2,3,4,5,6,7,8,9,10,11,12]
def key_loop(key):
test_df = pd.DataFrame(np.random.randn(1,4), columns=['a','b','c','d'])
test_list = test_df.ix[0].tolist()
return test_list
if __name__ == "__main__":
try:
pool = Pool(processes=8)
resultset = pool.imap(key_loop,(key for key in keys) )
loaddata = []
for sublist in resultset:
loaddata.append(sublist)
with open("C:\\Users\\mp_streaming_test.csv", 'w') as file:
writer = csv.writer(file)
for listitem in loaddata:
writer.writerow(listitem)
file.close
print "finished load"
except:
print 'There was a problem multithreading the key Pool'
raise
這是鞏固我和伊芙提出的建議的答案
import numpy as np
import pandas as pd
import csv
from multiprocessing import Pool
keys = [1,2,3,4,5,6,7,8,9,10,11,12]
def key_loop(key):
test_df = pd.DataFrame(np.random.randn(1,4), columns=['a','b','c','d'])
test_list = test_df.ix[0].tolist()
return test_list
if __name__ == "__main__":
try:
pool = Pool(processes=8)
resultset = pool.imap(key_loop, keys, chunksize=200)
with open("C:\\Users\\mp_streaming_test.csv", 'w') as file:
writer = csv.writer(file)
for listitem in resultset:
writer.writerow(listitem)
print "finished load"
except:
print 'There was a problem multithreading the key Pool'
raise
同樣,這里的變化是
resultset
,而不是不必要地首先將其復制到列表中。 keys
列表直接輸入pool.imap
而不是根據它創建生成器理解。 chunksize
到imap
比1.較大的默認chunksize
減少了內部傳遞值所需要的進程間通信的成本keys
在你池中的子過程,它可以給大的性能提升時, keys
非常大(視您的情況而定)。 你應該有不同的價值觀實驗chunksize
(嘗試比200大很多的東西,像5000等等),看看它是如何影響性能。 我對200進行了一個瘋狂的猜測,盡管它肯定比1更好。 以下非常簡單的代碼將許多工作人員的數據收集到一個CSV文件中。 工作人員獲取密鑰並返回行列表。 父級使用多個工作程序一次處理多個密鑰。 完成每個鍵后,父級將輸出行按順序寫入CSV文件。
注意訂購。 如果每個工作人員都直接寫入CSV文件,那么他們將陷入混亂或彼此腳。 讓每個工作人員寫入自己的CSV文件很快,但是隨后需要將所有數據文件合並在一起。
import csv, multiprocessing, sys
def worker(key):
return [ [key, 0], [key+1, 1] ]
pool = multiprocessing.Pool() # default 1 proc per CPU
writer = csv.writer(sys.stdout)
for resultset in pool.imap(worker, [1,2,3,4]):
for row in resultset:
writer.writerow(row)
1,0
2,1
2,0
3,1
3,0
4,1
4,0
5,1
我敢打賭,使用追加立即處理大型結構的原因是它使速度變慢。 我通常要做的是打開與核心一樣多的文件,並使用modulo立即寫入每個文件,這樣,與將它們全部定向到同一文件(寫入錯誤)相比,流不會造成麻煩,而且也不要試圖存儲海量數據 可能不是最好的解決方案,但確實很容易。 最后,您只需要合並結果即可。
在運行開始時定義:
num_cores = 8
file_sep = ","
outFiles = [open('out' + str(x) + ".csv", "a") for x in range(num_cores)]
然后在key_loop函數中:
def key_loop(key):
test_df = pd.DataFrame(np.random.randn(1,4), columns=['a','b','c','d'])
test_list = test_df.ix[0].tolist()
outFiles[key % num_cores].write(file_sep.join([str(x) for x in test_list])
+ "\n")
之后,別忘了關閉: [x.close() for x in outFiles]
改進:
遍歷注釋中提到的塊。 一次寫入/處理1行將比寫入塊慢得多。
處理錯誤(關閉文件)
重要說明:我不確定“ keys”變量的含義,但是那里的數字將不允許模以確保您將每個進程寫入每個單獨的流(12個鍵,模8將使2個進程寫入相同的流文件)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.