2010-11-01 77 views
14

我想知道是否有辦法連接unix文本文件在一起更快 比運行cat什麼是捕捉多個文件的最快方法?

這是我面臨的問題。我正在處理一個文本文件〜100G的字符串,大小爲 。我試圖通過將文件分成幾百個小文件並並行處理它們來改善運行時間。最後,我將所得到的 文件依次整理在一起。文件讀/寫時間本身需要幾個小時。我 會想找到一種方法,以改善以下:

cat file1 file2 file3 ... fileN >> newBigFile 
  1. 這就需要雙倍的磁盤空間爲file1 ... fileN佔據了100G,並 然後newBigFile另需100Gb的,然後file1。 .. fileN得到 去除

  2. 的數據已經在file1 ... fileN,做cat >>即被讀 ,寫的時候我真正需要的是爲幾百個文件到 重新出現1個文件...

+0

。 – 2010-11-01 19:31:11

+0

我不知道我在說什麼,但有可能操縱文件記錄或什麼?由於我需要做的不是複製數據,而是將多個文件串在一起回到1? – Wing 2010-11-01 19:37:52

回答

4

快,但不是免費的解決方案?獲取SSD驅動器或基於閃存PCIe的存儲。如果這是必須定期完成的事情,那麼提高磁盤IO速度將是您可以獲得的最具成本效益和最快的加速。

+0

謝謝,但不幸的是,我無法更改公司的文件服務器和硬件...... – Wing 2010-11-01 19:34:17

+2

當然,您的情況可能會禁止此操作,但如果它作爲現有服務器磁盤存儲(而不是替代品)的附加功能呈現給管理層,可以考慮。如果您可以擁有僅用於此任務的SSD,並且每天可以節省2小時的處理時間,我認爲他們會相信節省的成本。 – 2010-11-01 21:25:54

4

也許dd會更快,因爲您不必在cat和shell之間傳遞內容。喜歡的東西:

mv file1 newBigFile 
dd if=file2 of=newBigFile seek=$(stat -c %s newBigFile) 
+1

我絕對認爲dd與刪除文件一起復製爲Robie Basak所建議的文件,將會構成最重組的解決方案,而不是使用mmap實現自定義cp/unlink命令。然而,我相信沒有什麼比完全消除分裂更有效率。 – frankc 2010-11-01 21:59:06

1

我真正需要的是對數百個文件,再度出山擔任1個文件...

的原因,它是不實際的剛剛加入的文件這樣的文件系統因爲文本文件通常不會精確地填充磁盤塊,所以後續文件中的數據將不得不向上移動以填補空白,導致一堆讀取/寫入無論如何

4

是否可以簡單地不分割文件?通過在每個並行工作者中設置文件指針,而不是通過塊來處理文件。如果文件需要以面向行的方式進行處理,這會使其更加棘手,但仍然可以完成。每個工作人員都需要理解這一點,而不是從你給出的偏移量開始,它必須首先逐字節地尋找下一個新行+1。每個工作人員還必須明白,它不會處理您設置的字節數量,但必須在分配給它處理的設置字節量之後處理第一個換行符。

文件指針的實際分配和設置非常簡單。如果有n個工人,則每個人處理n /文件大小字節,並且文件指針從工人編號* n/file_size開始。

是否有某種原因,這種計劃是不夠的?

+0

而不是修改工作人員,shell可以爲工作人員提供一個「stdin」,它已經只是它應該工作的部分,例如使用sed來選擇一個行範圍。如果需要協調輸出,GNU Parallel可以爲此提供幫助。 – 2010-11-01 21:28:41

+0

這整個事情都是在perl中完成的,原始腳本試圖通過整個100G文件串行地進行字符串操作。現在我已經分裂了文件並通過fork()處理塊,但是現在讀/寫時間瓶頸了運行時。我不需要像你說的那樣進行初始分割,但是我仍然必須寫出已處理的塊,然後將它們放回到一個文件中,對吧? – Wing 2010-11-01 21:54:31

+0

如果我沒有拆分文件並讓每個子進程讀取在不同行上工作的原始100G文件,我是否會遇到嘗試讀取同一文件的200個進程的瓶頸? – Wing 2010-11-01 22:00:09

6

當文件串聯到一起,你可以刪除小文件,因爲他們得到附加:

for file in file1 file2 file3 ... fileN; do 
    cat "$file" >> bigFile && rm "$file" 
done 

這將避免需要雙倍的空間。

沒有其他方式神奇地使文件神奇連接。文件系統API根本沒有這樣的功能。

6

如果您不需要隨機訪問最終的大文件(即從頭到尾只讀一遍),則可以讓數百個中間文件顯示爲一個。在這裏你通常會做

$ consume big-file.txt 

,而不是做

$ consume <(cat file1 file2 ... fileN) 

它使用Unix的process substitution,有時也被稱爲 「匿名命名管道」。

您還可以通過拆分輸入和同時進行處理來節省時間和空間; GNU Parallel有一個--pipe switch這將做到這一點。它還可以將輸出重新組合爲一個大文件,可能使用較少的暫存空間,因爲它只需要一次性將個數個磁盤保留在磁盤上。如果您真正在同時運行數百個進程,Parallel可以讓您調整並行機器的數量,從而大大提高效率。我強烈推薦它。

+0

我還沒有測試過這個,但它聽起來像是最有用的建議 – Michael 2012-02-22 14:56:13

+0

流程替換看起來很棒,因爲它不會把東西放在磁盤上。所以你可以做「消耗<(cmd1 file1)<(cmd2 file2)<(cmd3 file3)」。但是,這裏相當於更傳統的「cat file1 file2 ... | consume」。 – dfrankow 2012-05-18 21:30:00

1

有太多的併發性。

這樣做的一個更好的方法是在所需範圍內使用對文件的隨機讀取讀取,並且不會實際將其分割並僅將文件數量作爲機器中物理CPU /內核的數量進行處理。那除非是用IOPS淹沒磁盤,那麼你應該削減,直到磁盤不是瓶頸。

你正在做的事情是產生大量的IOPS,而且它沒有辦法解決它的物理問題。

2

我相信這是最快的方式貓都包含在同一文件夾中的文件:這聽起來像你應該使用一些具有比Unix外殼多一點肌肉

$ ls [path to folder] | while read p; do cat $p; done 
+0

不錯=)這工作桃色。需要回聲;在完成之前。 – Kieveli 2017-07-06 18:11:18

相關問題