2017-04-01 48 views
0

我的代碼執行以下操作寫後讀文件和關閉在C

  1. 做的
    打開一個新的文件,100次;寫10M數據;關閉
  2. 打開100個文件一起,讀取,其數據合併到一個更大的文件
  3. 執行步驟1個2在循環

我想很多次,如果我能保持100開放W¯¯/o打開和關閉太多次。我能做的是fopen他們與w+。在寫完之後,我設置位置開始讀取,讀取後我將位置設置爲開始寫入,依此類推。

的問題是:

  1. ,如果我寫後讀W/O關閉,我們總是讀取所有寫入的數據
  2. 將這個節省一些開銷?文件打開和關閉必須有一些開銷,但是這個開銷足夠大以至於節省?

基於評論和討論我會談論爲什麼我需要在我的工作中做到這一點。這也與我的其他職位

how to convert large row-based tables into column-based tables efficently

我有一個生成結果的流計算。到目前爲止,結果被保存在一個行存儲表中。該表具有1M列,每列可以有10M長。實際上,每列是計算產生的一個屬性。在計算運行時,我轉儲並追加表格的中間結果。中間結果可以是每列2或3個雙值。我想盡快轉儲它,因爲它已經消耗了大於16M的內存。而計算需要更多的記憶。這結束瞭如下的表格

aabbcc...zzaabbcc..zz.........aabb...zz 

將一行數據存儲在一起。當我想按列分析數據列時,會發生問題。所以我必須讀取16個字節,然後尋找下一行讀取16個字節,然後繼續。搜索次數太多,比起所有列都存儲在一起的速度要慢很多,所以我可以順序讀取它們。

我可以減少計算轉儲次數。但要讓後期閱讀更有效率。我可能希望將4K數據存儲在一起,因爲我假設每個fread都默認爲4K,即使我只讀取了16個字節也是如此。但是,這意味着我需要緩存1M * 4K = 4G內存...

所以這樣的帖子裏說

how to convert large row-based tables into column-based tables efficently

所以我就在想,如果我可以合併片段DATAS成更大的塊我想要使用文件作爲離線緩衝區。如果每個文件包含1M個2個雙打,我可能需要256個文件才能獲得合併後的4K連續數據。就主要計算而言,這項工作可以以異步方式完成。但是我想確保合併開銷很小,所以當它並行運行時,它可以在主計算完成之前完成。所以我想出了這個問題。

我想這與如何構建基於列的數據庫非常相關。當人們創造它們時,他們是否也有類似的問題?有沒有關於它如何在創作上工作的描述?

+0

爲什麼不嘗試呢?我懷疑這會造成很大的變化,是的。您將不得不倒退文件指針,但這比關閉/打開快。 – ThingyWotsit

+0

是的。避免不必要的打開/關閉會節省一些開銷,但與讀取和寫入相比,開銷可能可以忽略不計,尤其是如果數據以兆字節計數(IO操作對文件系統通常非常慢,並且可能會阻止CPU的進程)。您的結果可能因您的操作系統而異。在Linux上,完成的寫入應該立即可見。 – PSkocik

+0

你的機器有多少內存?如果您擁有多個千兆字節的主內存(2 GiB或更多),您應該考慮將1 GiB的數據讀入內存,對它進行處理(如果這非常關鍵,請處理10 MiB塊),然後合併,然後再寫入輸出文件。如果你在嵌入式環境中沒有這麼多的內存,那麼你可能需要通過文件,但如果你沒有,它會讓生活更輕鬆(更快)。通常,打開文件是更昂貴的系統調用之一;幕後有很多工作要做。減少打開次數有助於。 –

回答

0

是的。您可以保持100個文件不打開或關閉打開循環。儘管大多數系統對打開的文件數量有限制。

,如果我寫後讀的w/o最後,我們總是讀取所有寫入的數據

這取決於你。你可以在文件中的任何位置執行fseek goto並從那裏讀取數據。這一切都是你和你的邏輯。

這會節省一些開銷嗎?文件打開和關閉必須有一些開銷,但是這個開銷足夠大以至於節省?

這肯定會節省一些開銷,如額外的不必要的I/O操作,並且在某些系統中,您寫入文件的內容不會立即刷新到物理文件,它可能會被緩衝並定期刷新或完成在fclose的時候。

所以,這些開銷被保存了,但真正的問題是你通過節省這些開銷獲得了什麼?它如何適合你的應用程序的整體情況?這是在決定邏輯之前必須要做的調用。

2

只要系統上打開文件的最大數量允許,您可以使用w+;這通常是255或1024,並且可以設置(例如,在Unix上由ulimit)。

但我不太確定這將是值得的努力。

另一方面,每個10M的100個文件是1千兆字節;您可能想要嘗試使用RAM磁盤。或者使用大型文件系統緩存。

我懷疑可以通過分析您的具體問題結構來獲得更大的儲蓄。爲什麼是100個文件?爲什麼10 M?你在做什麼樣的「合併」?這100個文件是否總是以相同的順序和相同的頻率訪問?有些數據可以保存在RAM中,永遠不會被寫入?

更新

所以,你有一個像一些大的緩衝區,

ABCDEFG... 
ABCDEFG... 
ABCDEFG... 

,並要轉動他們,讓他們讀

AAA... 
BBB... 
CCC... 

如果你已經擁有了總規模(即,你知道你將寫入10GB的數據),你可以用兩個文件來完成這個工作,預先分配文件並使用fseek()來寫入輸出文件。對於內存映射文件,這應該是非常有效的。在實踐中,Y行X列的1,000,000行已經在文件Y.dat的地址16 * X處被轉儲;你需要將它寫入地址16 *(Y * 1,000,000 + X)到largeoutput.dat

實際上,即使在第一次計算時也可以寫入數據。或者你可以有兩個進程通過管道進行通信,一個計算,一個寫入行列和列行文件,這樣你就可以監視每個文件的執行情況。坦白地說,我認爲增加更多的內存和/或快速I/O層(SSD可能?)可以讓你在同樣的壓力下獲得更大的回報。你的時間成本也是如此,並且在完成一項工作後,內存仍然可用。

+0

我更新了我的問題,並解釋了爲什麼我有這個問題。 –