2015-05-18 64 views
14

我有多個3GB製表符分隔的文件。每個文件中有2000萬行。所有的行都必須獨立處理,任何兩行之間沒有關係。 我的問題是,什麼會更快使用`Python:處理大文件的最快方法

with open() as infile: 
      for line in infile: 

或者B.把文件讀入內存塊,並對其進行處理線A.讀線,一次說250 MB?

處理不是很複雜,我只是在列1中將值List1,列2中的值轉換爲List2等。可能需要將某些列值添加到一起。

我在一個有30GB內存的Linux機器上使用python 2.7。 ASCII文本。

任何方式來並行加速東西?現在我正在使用前一種方法,這個過程非常緩慢。是否使用任何CSVReader模塊來幫助? 我不必在python中做任何其他語言或數據庫使用想法。 謝謝。

`

+0

multiprocessing;分塊迭代閱讀。在每個文件3GB的時候,你不會**想完全讀入內存;你可能會吹掉你的內存資源。 –

+0

這聽起來像一個數據庫將幫助你取決於你正在處理的類型。 – squiguy

+0

如果這是一次性拋棄任務,則不需要;數據中;處理;數據輸出;刪除源數據。 –

回答

23

這聽起來像你的代碼是I/O綁定。這意味着多處理不會對你有幫助 - 如果你花費90%的時間從磁盤讀取數據,那麼在下一次讀取時等待下一個額外的7個進程是無助於任何事情的。

而且,使用CSV閱讀模塊(無論stdlib的csv還是類似NumPy或Pandas的內容)可能是一個簡單的好主意,它不太可能在性能上有很大的不同。

不過,值得檢查一下,你真的 I/O綁定,而不是隻是猜測。運行你的程序,看你的CPU使用率是接近0%還是接近100%或核心。做Amadan在評論中建議的內容,然後運行程序pass進行處理,看看它是否會削減5%或70%的時間。你甚至可以試着比較一下os.openos.read(1024*1024)之類的循環,看看它是否更快。


由於您使用Python 2.x中,Python是依靠C STDIO庫猜測多少在一個時間緩衝,所以它可能是值得迫使緩衝更多。最簡單的方法是對bufsize使用readlines(bufsize)。 (您可以嘗試不同的數字並測量它們以查看峯值的位置。根據我的經驗,通常64K-8MB的任何數值都差不多,但根據您的系統可能會有所不同 - 尤其是如果您閱讀關閉以極大的吞吐量,但可怕的延時的網絡文件系統,沼澤實際的物理驅動器和OS做緩存的吞吐量與延遲)

因此,舉例來說:

bufsize = 65536 
with open(path) as infile: 
    while True: 
     lines = infile.readlines(bufsize) 
     if not lines: 
      break 
     for line in lines: 
      process(line) 

同時,假設您使用的是64位系統,則可能需要嘗試使用mmap而不是首先讀取該文件。這當然不是保證要好一些,但它可能會更好,這取決於您的系統。例如:

with open(path) as infile: 
    m = mmap.mmap(infile, 0, access=mmap.ACCESS_READ) 

一個Python mmap是排序一個奇怪的物體,它像一個str和像file在同一時間,這樣就可以,例如,用於換行手動迭代掃描,或者可以調用readline就好像它是一個文件一樣。這兩種方法都需要從Python進行更多的處理,而不是像批處理文件那樣迭代文件或執行批處理readlines(因爲循環將在C中現在處於純Python中......雖然也許您可以通過re或簡單的Cython擴展?)...但是,操作系統的I/O優勢知道你在映射中做什麼可能會縮小CPU的劣勢。

不幸的是,Python並沒有公開調用madvise調用來嘗試在C中優化它(例如,明確設置MADV_SEQUENTIAL而不是猜測內核,或者強制透明的巨大頁面) - 但你實際上可以在libc之外的功能​​。

+1

感謝您抽出寶貴的時間回覆此問題:) +1 –

+0

我在Linux上有30 GB的內存。是否有任何問題正在執行readlines()將整個文件存入內存? – Reise45

+0

@ Reise45:這取決於你所說的「問題」。它應該_work_; 3GB文件上的readlines應該低於4GB,如果你還預處理所有行到內存中的值列表中,這應該不會超過12GB,所以你仍然處於舒適的限制之內。但是這意味着你必須事先做好所有的閱讀工作,所以操作系統無法幫助管理你的I/O等待和你的CPU工作;你浪費時間在malloc和緩存錯誤上;等等。如果有一些好處(例如,它可以讓你使用NumPy來加速緩慢的處理循環),那可能是值得的,但是如果沒有,爲什麼呢? – abarnert

相關問題