CPP讀取檔案速度比較

2021-07-31 16:53:44 字數 3564 閱讀 3747

[cpp]view plain

copy

探尋c++最快的讀取檔案的方案  

計算機技術  

add comments7,388 views  

在競賽中,遇到大資料時,往往讀檔案成了程式執行速度的瓶頸,需要更快的讀取方式。相信幾乎所有的c++學習者都在cin機器緩慢的速度上栽過跟頭,於是從此以後發誓不用cin讀資料。還有人說pascal的read語句的速度是c/c++中scanf比不上的,c++選手只能乾著急。難道c++真的低pascal一等嗎?答案是不言而喻的。乙個高階的方法是把資料一下子讀進來,然後再轉化字串,這種方法傳說中很不錯,但具體如何從沒試過,因此今天就索性把能想到的所有的讀資料的方式都測試了一邊,結果是驚人的。  

競賽中讀資料的情況最多的莫過於讀一大堆整數了,於是我寫了乙個程式,生成一千萬個隨機數到data.txt中,一共55mb。然後我寫了個程式主幹計算執行時間,**如下:  

view code cpp  

#include 

intmain()  

最簡單的方法就算寫乙個迴圈scanf了,**如下:  

view code cpp  

const

intmaxn = 10000000;  

intnumbers[maxn];  

void

scanf_read()  

可是效率如何呢?在我的電腦linux平台上測試結果為2.01秒。接下來是cin,**如下  

view code cpp  

const

intmaxn = 10000000;  

intnumbers[maxn];  

void

cin_read()  

出乎我的意料,cin僅僅用了6.38秒,比我想象的要快。cin慢是有原因的,其實預設的時候,cin與stdin總是保持同步的,也就是說這兩種方法可以混用,而不必擔心檔案指標混亂,同時cout和stdout也一樣,兩者混用不會輸出順序錯亂。正因為這個相容性的特性,導致cin有許多額外的開銷,如何禁用這個特性呢?只需乙個語句std::ios::sync_with_stdio(false

);,這樣就可以取消cin於stdin的同步了。程式如下:  

view code cpp  

const

intmaxn = 10000000;  

intnumbers[maxn];  

void

cin_read_nosync()  

取消同步後效率究竟如何?經測試執行時間銳減到了2.05秒,與scanf效率相差無幾了!有了這個以後可以放心使用cin和cout了。  

接下來讓我們測試一下讀入整個檔案再處理的方法,首先要寫乙個字串轉化為陣列的函式,**如下  

view code cpp  

const

intmaxs = 60*1024*1024;  

char

buf[maxs];  

void

analyse(

char

*buf,

intlen = maxs)  

把整個檔案讀入乙個字串最常用的方法是用fread,**如下:  

view code cpp  

const

intmaxn = 10000000;  

const

intmaxs = 60*1024*1024;  

intnumbers[maxn];  

char

buf[maxs];  

void

fread_analyse()  

上述**有著驚人的效率,經測試讀取這10000000個數只用了0.29秒,效率提高了幾乎10倍!掌握著種方法簡直無敵了,不過,我記得fread是封裝過的read,如果直接使用read,是不是更快呢?**如下:  

view code cpp  

const

intmaxn = 10000000;  

const

intmaxs = 60*1024*1024;  

intnumbers[maxn];  

char

buf[maxs];  

void

read_analyse()  

測試發現執行時間仍然是0.29秒,可見read不具備特殊的優勢。到此已經結束了嗎?不,我可以呼叫linux的底層函式mmap,這個函式的功能是將檔案對映到記憶體,是所有讀檔案方法都要封裝的基礎方法,直接使用mmap會怎樣呢?**如下:  

view code cpp  

const

intmaxn = 10000000;  

const

intmaxs = 60*1024*1024;  

intnumbers[maxn];  

char

buf[maxs];  

void

mmap_analyse()  

經測試,執行時間縮短到了0.25秒,效率繼續提高了14%。到此為止我已經沒有更好的方法繼續提高讀檔案的速度了。回頭測一下pascal的速度如何?結果令人大跌眼鏡,居然執行了2.16秒之多。程式如下:  

view code pascal  

const

maxn = 10000000;  

var  

numbers :array[0..maxn] of longint;  

i :longint;  

begin  

assign(input,'data.txt'

);  

reset(input);  

fori:=0 to maxn 

doread(numbers[i]);  

end.  

為確保準確性,我又換到windows平台上測試了一下。結果如下表:方法/平台/時間(秒)  

linux gcc    windows mingw  windows vc2008  

scanf      2.010       3.704          3.425  

cin   6.380     64.003    19.208  

cin取消同步2.050        6.004     19.616  

fread     0.290      0.241    0.304  

read      0.290     0.398     不支援  

mmap      0.250     不支援   不支援  

pascal read     2.160     4.668   

從上面可以看出幾個問題  

linux平台上執行程式普遍比windows上快。  

windows下vc編譯的程式一般執行比mingw(minimal gcc for

windows)快。  

vc對cin取消同步與否不敏感,前後效率相同。反過來mingw則非常敏感,前後效率相差8倍。  

read本是linux系統函式,mingw可能採用了某種模擬方式,read比fread更慢。  

pascal程式執行速度實在令人不敢恭維。  

希望此文能對大家有所啟發,歡迎與我繼續討論。  

關於資料庫讀取速度與檔案IO讀取速度的比較分析

最近看到了這個很有意思的問題,以前也沒有思考過。如果有人問,到底是在 中跟 io檔案交換速度快,還是跟資料庫交換速度快呢?這個問題還是比較複雜的,資料庫的儲存資料方式要比單純的檔案儲存複雜很多。其實,如果我們熟悉資料庫的結構,那麼很容易解決這個問題。簡單的來講,乙個執行的資料庫例項是由兩部分組成的,...

GPRS速度比較

gprs edge edge全稱enhanced data rate for gsm evolution,中文含義是 提高資料速率的gsm演進技術,可見它與gprs一樣,都是基於傳統gsm網路的產物。在3g正式投入執行之前,edge是基於gsm網路最高速的無線資料傳輸技術。該技術主要在於能夠使用寬頻...

CArray,CMap,CList 速度比較

出處 1.陣列 carray 訪問方法及效率和普通的陣列一樣,比普通陣列強大的功能是可以改變陣列的大小。array採用佇列方式儲存資料,因而其內部資料元素是以物理方式順序排列的,所以檢索 順序執行getat 等函式的速度是相當快的。但是由於每次佇列長度變化後,資料都要重新申請記憶體 拷貝記憶體 釋放...