外部マージソートを書いています。それは次のように機能します: 大きなファイルから k 個のチャンクを読み取り、それらをメモリ内でソートし、k-way マージを実行して完了します。そのため、k-way マージ フェーズ中にファイルのさまざまな部分から順番に読み取る必要があります。それを行う最善の方法は何ですか: 複数の ifstream または 1 つの ifstream とシーク? また、簡単な非同期 IO 用のライブラリはありますか?
2 に答える
ifstream
同じファイルで一度に1 つずつ使用します。複数のリソースが無駄になり、とにかくシークする必要があります (デフォルトでは、ifstream
のファイル ポインターはファイルの先頭から始まるため)。
C++ 非同期 IO ライブラリについては、この質問を確認してください。
編集:私はもともとあなたがやろうとしていることを誤解していました(このウィキペディアの記事でいっぱいになりました)。デフォルトでどれだけのバッファが使用されるかはわかりませんが、ここで説明する方法ifstream
を使用してバッファリングをオフにしてから、独自のバッファリングを行うことができます。ただし、これは自動バッファリングで複数の を使用するよりも遅くなる可能性があります。いくつかのベンチマークは順調です。pubsetbuf(0, 0);
ifstream
必ず複数のストリームを試してください。シークすると、おそらく内部的にバッファリングされたデータが破棄されます (OS がキャッシュに保持していても、少なくともプロセス内では)。並べ替えているアイテムが小さい場合、実際には非常にコストがかかる可能性があります。
とにかく、2 つの fstream 戦略のパフォーマンスを比較するのはそれほど難しくありません。k = 2 で簡単な実験を行います。
1 つのプロセスが同時に開くことができるファイルの数には制限がある場合があることに注意してください ( ulimit -n
)。それに到達した場合は、単一のストリームを使用することを検討することをお勧めしますが、k 個のチャンクのそれぞれから手動でデータをバッファリングします。
ファイルが十分に小さい場合 (同等に、アドレス空間が十分に大きい場合)、ファイルを mmap し、複数のポインターを使用する価値があるかもしれません。