13

私のライブラリは、特定のファイル (テキスト ファイル、サイズ 326 kb) の解析が 30 倍以上遅すぎるという報告を受けました。std::ifstreamユーザーは、私が(おそらく の代わりに)を使用している可能性があると示唆しましたFILE

やみくもに書き直すのは嫌なので、最初にここを確認しようと思いました。私の推測では、ボトルネックは別の場所にあると思われます。私は文字ごとに読んでいるので、使用している関数はget()peek()、およびtellg()/seekg().

アップデート:

プロファイリングを行ったところ、紛らわしい出力が得られました。gprof は、それほど時間がかかったとは考えていないようです。最初にファイル全体をバッファーに読み込むようにプログラムを書き直したところ、約 100 倍高速化されました。tellg()/seekg()問題は時間がかかったことだと思いますが、何らかの理由で gprof がそれを見ることができなかったのかもしれません。いずれにせよ、このサイズであっても、ファイル全体をバッファリングするようには見えifstreamません。

4

6 に答える 6

26

私はそれが違いを生むとは思わない。特に 1 文字ずつ読み取る場合は、I/O のオーバーヘッドが他のすべてを完全に支配する可能性があります。一度に 1 バイトずつ読み取るのはなぜですか? 非常に非効率だということをご存知ですか?

326kb のファイルの場合、最速の解決策は、一度にメモリに読み込むことです。

std::ifstream と C の同等のものとの違いは、基本的に 1 つまたは 2 つの仮想関数呼び出しです。毎秒数千万回実行されれば違いが生じるかもしれませんが、それ以外の場合は現実的ではありません。ファイル I/O は一般に非常に遅いため、ファイルへのアクセスに使用する API はあまり重要ではありません。はるかに重要なのは、読み取り/書き込みパターンです。多くのシークは悪く、シーケンシャルな読み取り/書き込みは良いことです。

于 2009-01-25T06:20:26.743 に答える
4

少し遅くなるはずですが、あなたが言ったように、それはボトルネックではないかもしれません. プログラムのプロファイルを作成して、それが事実かどうかを確認してみませんか?

于 2009-01-25T06:11:33.563 に答える
3

fstream から FILE* に切り替えることで問題が解決される可能性は低いと思います。通常、どちらも C ライブラリによってバッファリングされます。また、OSは読み取りをキャッシュできます(Linuxはその点で非常に優れています)。アクセスしているファイルのサイズを考えると、完全に RAM にある可能性が高いです。

PolyThinker のように、あなたの最善の策は、プロファイラーを介してプログラムを実行し、問題がどこにあるかを判断することです。

また、seekg/tellg を使用している場合、ディスクが非常に断片化されている場合、ディスクが最初にファイルを読み取るためにヘッドを正しい位置に移動する必要があるため、これにより顕著な遅延が発生する可能性があります。

于 2009-01-25T07:02:56.080 に答える
2

すべてのベンチマークは悪です。期待するデータのコードをプロファイリングするだけです。

Ruby、Python、Perl、C++ の I/O パフォーマンス比較を 1 回実行しました。私のデータ、言語のバージョンなどでは、C++ のバリアントは数倍遅くなりました (当時は大きな驚きでした)。

于 2009-01-25T06:47:27.220 に答える
1

プロファイリングすることに同意します。しかし、一度に 1 文字ずつファイルを読み取る場合は、メモリ マップト ファイルを作成するのはどうでしょうか。そうすれば、ファイルを文字の配列のように扱うことができ、OS がすべての低レベルのバッファリングを処理する必要があります。最も簡単でおそらく最速の解決策は、私の本の勝利です。:)

于 2009-02-01T23:43:44.810 に答える