為什麼 C 語言的輸入輸出函數比 C++ 的輸入輸出流要快?
平時做ACM賽題時,即使選用C++語言,選手們一般也用scanf讀入大規模數據,因為實際經驗得出用C語言的輸入輸出函數比C++的輸入輸出流更快,這是為什麼?
如果是用了ios::sync_with_stdio(false)的話是可以達到近似scanf的速度的。一下該函數簡單的介紹。速度慢的主要原因是同步標準輸入輸出。static void sync_with_stdio();
Synchronizes the C++ streams with the standard I/O system. The first time this function is called, it resets the predefined streams (cin, cout, cerr, clog) to use astdiobuf object rather than a filebuf object. After that, you can mix I/O using these streams with I/O using stdin, stdout, and stderr. Expect some performance decrease because there is buffering both in the stream class and in the standard I/O file system.
After the call to sync_with_stdio, the ios::stdio bit is set for all affected predefined stream objects, and cout is set to unit buffered mode.----這似乎是一個深坑,給人挖出來了-----這類測試,總是有人做過的。探尋C++最快的讀取文件的方案,這個文章,測試的很清楚了。不過他沒有測試MAC機器的。我提供一組數據mac 10.9,XCODE5.1.1輸入,100萬個隨機數,文件大小10.5M。scanf測試
./scan_in_test &<./scan_data.txt
Cost time: 139 ms
./cin_test &<./scan_data.txt (使用sync_with_stdio(false))
Cost time: 3436 ms
./cin_test &<./scan_data.txt (不使用sync_with_stdio(false))
Cost time: 3449 ms
測試的結果是,MAC下面的XCode,用不用sync_with_stdio(false),沒有什麼區別。
懶得點擊上面的鏈接的,直接看下面附上鏈接文章中的的一些測試結果數據(測試1000萬數據)
C++ 的 iostream 是 version2.0 綜合症的集中體現
跟compiler implement os kernel有關的東西有什麼好討論的 附上icpc 2014 final 給的環境 你自己組一個環境benchmark一下,誰快就用誰
- OS:
- Ubuntu 12.04.3 LTS Linux (64-bit)
- Languages:
- C/C++
- GCC 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
- Compilation of Submissions
- C gcc -g -O2 -std=gnu99 -static $* -lm
- C++ g++ -g -O2 -std=gnu++0x -static $*
順便一提 雖然我不做ICPC 但都-std=gun++0x了 stl才是現在情況下acmer的首選
參考資料
Programming Environmenthttps://gcc.gnu.org/gcc-4.6/cxx0x_status.html·······························分割線··································
順便一吐說printf是調用os api ,cout是頭文件的。。。這個問題我以前研究過。首先說因為iostream和stdio的同步問題導致了iostream會變慢,可以通過ios::sync_with_stdio(false)手動關閉這個同步,可能有加速作用。-------------------------以下基本上是HDU和POJ的經驗,其他OJ暫時不明根據我曾經大約100多題的測試,ios::sync_with_stdio(false)只對C++ 有用,G++基本上無用,而且很多時候如果用了ios::sync_with_stdio(false)再加上cout和printf的混用,輸出順序會有不同。-------------------所以一般的建議是scanf最好,printf可以格式化,對acm要求按照格式輸出來說最方便。PS:現場賽教練會議的時候有時候會說iostream的事情
原因上面的大大們都說完了,我再補充幾個小點。
1. sync_with_stdio(false),有可能會導致RE(在a+b problem裡面)。具體原因不詳,問題貌似還不能復現。所以一直不敢用這個。
2. cout的輸出格式比較麻煩,還是用printf來的比較爽。
3. cout 有個小坑,例如:cout &<&< 123456.7 &<&< endl;
輸出結果:
正式比賽中萬一手一抖寫出這樣的代碼真的會被自己坑的欲哭無淚。cin &>&> 需要進行自動檢測類型,內部執行的代碼很長。
這就好比兩個函數,其中一個為了適應外界各種差異,碼了100行,還有一個函數只處理了一種情況,碼了5行,然後有人開始比較這兩個函數的快慢,我想說這有意義嗎?
就是快。。。不要信樓上的sync_with_stdio, 有時它照樣會另你的程序超時。。。
至於原因,我覺得是因為scanf, printf是直接調用OS的API, 而cin/cout是頭文件中的代碼實現。
對了,有人可能發現fin/fout比fscanf/fprintf快。我個人覺得是因為default buffer大小不一樣。endl會flush..這個在那本user guide就說過...
推薦閱讀: