2010-12-03 405 views
6

我正在寫一個大型數值2維數組到二進制文件(最終大小〜75 MB)。fwrite和寫入大小的性能

我在linux系統上這樣做。首先,除了fwrite之外,還有更好的方法或系統調用來儘可能快地寫入文件嗎?其次,如果我應該使用fwrite,那麼我應該只將整個文件寫爲1個連續的行嗎?

fwrite(buf, sizeof(float), 6700*6700, fp); 

或寫爲一系列塊

fwrite(buf, sizeof(float), 8192, fp); 
fwrite(*(buf+8192), sizeof(float), 8192, fp); 
.... 

,如果我要一塊寫的,有多大應該每塊呢?

回答

5

只需使用fwrite(不需要進入較低級別的系統調用)並將其作爲一個塊執行。較低級別的系統調用將找出如何緩衝並最好地分割該寫入命令。我從來沒有能夠在這樣的事情上擊敗fwrite的表現 - 大量的順序寫入。

+0

我同意。我見過的唯一比標準fwrite()更好的文件是fwrite()到/ dev/shm上的一個文件:-) – Christoffer 2010-12-03 23:38:34

1

一個塊更快。這有幾個原因:

1)寫入硬盤意味着還保持「最新」文件系統中的所有附加信息(時間戳,文件大小,使用的羣集,鎖等),所以有一些與每個文件訪問相關的開銷(尤其是寫訪問)。

2)磁盤I/O速度很慢,因此操作系統通常會嘗試在其一側實施一些緩存。這意味着每次使用文件I/O時,如果它被緩存,它應該被緩存等等,會有額外的檢查。

1

你可以找到

http://sourceware.org/git/?p=glibc.git;a=blob;f=libio/iofwrite.c;hb=HEAD

FWRITE源正如你所看到的,這反過來要求IO_sputn,最終在

http://sourceware.org/git/?p=glibc.git;a=blob;f=libio/fileops.c;hb=HEAD

(具體_IO_new_file_xsputn結束)。正如你所看到的,這總是通過stdio緩衝區。

所以我建議不要使用stdio;直接使用write(2)寫入將繞過這個額外的副本。

+0

或者用glibc提交bug報告。當數據大於緩衝區時通過緩衝區寫入是荒謬的。 – 2010-12-04 03:54:52

+0

5年過去了,這仍然是真的嗎? – 2015-11-02 18:17:57

2

通過使用nmap(),您可能會獲得更高的性能,爲您的數組創建空間(虛擬地址空間),然後寫入「內存」而不是磁盤。

讓系統爲你做:它可能會分配儘可能少的頁面,而這對於fwrite()轉儲的75 MB緩衝區不會發生。在一個CPU緩存受限的世界中,玩大緩衝區是一個不行(這就是爲什麼malloc()使用nmap()進行大分配的原因)。通過在設置nmap()時將緩衝區附加到文件中 - 在填充緩衝區之前,您可以將大量工作保存到系統中。

6

我同意miked和傑羅姆的大部分,但是...只適用於現代操作系統。如果您正在嵌入閃存文件系統,則有一些主要的例外。在這種環境下,如果您懷疑fwrite(),請使用write()與大塊進行快速測試。

今天,我發現移動到write()的速度提高了4倍。這是由於嵌入式操作系統中的一個posix層,它將fwrite()轉換爲fputc()s ...在這種情況下,SYNC的底層flash文件就會出現亂碼。 write()是由更靠近OS(Nucleus)的例程實現的,在這些例程中,塊寫入沒有被分解爲字節。

只是說......如果你質疑兩個變種,可能最好還是try'em出來。