簡體   English   中英

如何將結果從Multiprocessing.Pool流到csv?

[英]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

同樣,這里的變化是

  1. 直接遍歷resultset ,而不是不必要地首先將其復制到列表中。
  2. keys列表直接輸入pool.imap而不是根據它創建生成器理解。
  3. 提供了一個更大的chunksizeimap比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.

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