28

C++ のファイル I/O 操作は、C スタイルの I/O よりもはるかに遅いといつも聞いています。しかし、実際の速度が比較的遅いという実用的な参考文献が見つからなかったため、自分のマシン (Ubuntu 12.04、GCC 4.6.3、ext4 パーティション形式) でテストすることにしました。

まず、ディスクに ~900MB のファイルを書き込みました。

C++ ( ofstream): 163 秒

ofstream file("test.txt");
    
for(register int i = 0; i < 100000000; i++) 
    file << i << endl;

C ( fprintf): 12 秒

FILE *fp = fopen("test.txt", "w");
    
for(register int i = 0; i < 100000000; i++) 
    fprintf(fp, "%d\n", i);

私はそのような出力を期待していました.ファイルへの書き込みがCよりもC++ではるかに遅いことを示しています.次に、CおよびC++ I / Oを使用して同じファイルを読み取りました. ファイルからの読み取り中にパフォーマンスにほとんど違いがないことを私が叫んだ理由.

C++ ( ifstream): 12 秒

int n;
ifstream file("test.txt");

for(register int i = 0; i < 100000000; i++) 
    file >> n;

C ( fscanf): 12 秒

FILE *fp = fopen("test.txt", "r");
    
for(register int i = 0; i < 100000000; i++) 
    fscanf(fp, "%d", &n);

では、ストリームを使用した書き込みの実行に時間がかかるのはなぜですか? または、ストリームを使用した読み取りが書き込みに比べて非常に高速なのはなぜですか?

結論:std::endl答えとコメントが指摘しているように、犯人はです。file << i << endl; ラインを 変更すると、 file << i << '\n';実行時間が 163 秒から 16 秒に短縮されました。

4

3 に答える 3

29

endl改行を印刷するために使用しています。ここでの問題は、改行を出力するだけでなく 、高価endlな操作であるバッファーもフラッシュするためです (反復ごとに行う場合)。

\nあなたがそうする場合に使用してください:

file << i << '\n';

また、コードをリリース モードでコンパイルする必要があります (つまり、最適化をオンにします)。

于 2013-07-04T10:44:32.933 に答える
22

いいえ、C++ の入力/出力は C よりも大幅に遅くはありません。どちらかといえば、最新の実装は、フォーマット文字列を解析する必要がなく、代わりにコンパイル時にストリーム演算子の連鎖。

ベンチマークで考慮すべきいくつかの注意事項を次に示します。

  • -O3公正な比較を行うには、完全な最適化 ( ) でコンパイルします。
  • 適切なベンチマークでは、バイアスを推定する必要があります。実際には、これは、テストを繰り返してインターリーブする必要があることを意味します。現時点では、コードはバックグラウンド プロセスからの障害に対して堅牢ではありません。また、反復実行の要約統計量を報告して、推定を歪める外れ値を検出する必要があります。
  • C ストリームとの C++ ストリーム同期を無効にする ( std::ios_base::sync_with_stdio(false);)
  • '\n'(フラッシング)の代わりに使用std::endl
  • 宣言を使用しないでくださいregister。単に違いはなく、最近のコンパイラはおそらくそれを無視します。
于 2013-07-04T10:47:04.990 に答える
1

で大きなファイルを扱う場合はfstream、必ずストリーム バッファ >0 を設定してください。

直感に反して、ストリーム バッファリングを無効にすると、パフォーマンスが大幅に低下します。少なくとも、MSVC 2015 の実装では、バッファが設定されていないときに一度に1 文字を にコピーします (「参考文献」を参照)。これにより、アプリケーションが CPU バウンドになり、I/O レートが低下する可能性があります。filebufstreambuf::xsputn

const size_t bufsize = 256*1024;
char buf[bufsize];
mystream.rdbuf()->pubsetbuf(buf, bufsize);

完全なサンプル アプリケーションは、ここにあります

于 2016-08-23T10:06:36.553 に答える