3

1つの大きなファイルのハードディスクからデータを処理していて(処理は高速で、多くのオーバーヘッドはありません)、結果を書き戻す必要があります(数十万のファイル)。

結果をすぐにファイルに1つずつ書き始めましたが、これが最も遅いオプションでした。一定量のファイルのベクトルを作成し、それらを一度にすべて書き込んでから、ハードディスクがそれに注いだすべてのものを書き込むために占有されている間に処理に戻ると、はるかに高速になると思いました(少なくとも何が起こるかと思われます)。

私の質問は、ハードウェアの制約から書き込む必要のあるデータ量の収束値をどうにかして見積もることができるかということです。私にはそれはハードディスクバッファのもののように見えます、私はそのハードディスクに16MBのバッファを持っていて、これらの値を取得します(すべて〜100000ファイルの場合):

Buffer size      time (minutes)
------------------------------
no Buffer        ~ 8:30
 1 MB            ~ 6:15
10 MB            ~ 5:45
50 MB            ~ 7:00

それともこれは単なる偶然ですか?

また、書き込みパフォーマンスを一般的に最適化する方法についての経験/経験則にも興味があります。たとえば、より大きなハードディスクブロックが役立つなどです。

編集:

ハードウェアはかなり標準的な消費者向けドライブです(私は学生であり、データセンターではありません)WD 3,5 1TB / 7200 / 16MB / USB2、HFS +ジャーナル、OSはMacOS10.5です。すぐにExt3/Linuxと外部ではなく内部ディスクで試してみます)。

4

4 に答える 4

4

ハードウェアの制約から書き込む必要のあるデータ量の収束値をどうにかして見積もることができますか?

長期的ではありません。問題は、書き込みパフォーマンスが少なくとも4つのことに大きく依存することです。

  • 使用しているファイルシステム

  • カーネルが使用しているディスクスケジューリングアルゴリズム

  • ディスクのハードウェア特性

  • 使用しているハードウェア相互接続

たとえば、USBはSATAよりも遅いIDEよりも低速です。XFSが多くの小さなファイルを書き込むためにext2よりもはるかに高速であったとしても、私は驚かないでしょう。そして、カーネルは常に変化します。したがって、ここには単純な予測を容易にするための要素が多すぎます。

もし私があなただったら、私はこれらの2つのステップを踏むでしょう:

  • プログラムを複数のスレッド(またはプロセス)に分割し、1つのスレッドを使用して、システムコール、、をOSにできるだけ早く配信openwriteますclose。スレッド数を実行時パラメーターにできる場合はボーナスポイント。

  • ハードウェアの特性からパフォーマンスを見積もる代わりに、多数の代替案を試し、その日のハードウェアとソフトウェアの特定の組み合わせに対して最速のものを見つけるプログラムを作成します。最速の代替案をファイルに保存するか、コードにコンパイルすることもできます。この戦略は、 FFTWのためにMatteo Frigoによって開拓されたものであり、非常に効果的です。

次に、ディスク、相互接続、カーネル、またはCPUを変更するときに、構成プログラムを再実行してprestoするだけです。コードは、最高のパフォーマンスが得られるように最適化されます。

于 2010-01-02T00:30:56.343 に答える
2

ここで重要なことは、OSがハードディスクアクセスを最適化できるように、できるだけ多くの未処理の書き込みを取得することです。これは、非同期I / Oを使用するか、タスクプールを使用して新しいファイルを実際にディスクに書き込むことを意味します。

そうは言っても、読み取りアクセスの最適化を検討する必要があります。OS(少なくともWindows)は、「内部」でバッファリングを介して書き込みアクセスを支援するのにすでに非常に優れていますが、シリアルでの読み取りがそれほど多くない場合は、支援することができます。非同期I/Oまたは(再び)タスクプールを使用してファイルの複数の部分を一度に処理/読み取ると、パフォーマンスが向上する可能性があります。

于 2010-01-01T23:15:02.883 に答える
1

XMLの解析は、実質的にディスクの読み取り速度である数十MB/秒で実行できるはずです。SAX実装はそれを行っていない可能性があります。

あなたはいくつかの汚いトリックを使いたいかもしれません。書き込む100.000のファイルは、通常のAPIでは効率的ではありません。

これをテストするには、100.000ではなく、最初に1つのファイルに順番に書き込みます。パフォーマンスを比較します。違いがおもしろい場合は、読み進めてください。

書き込んでいるファイルシステムを本当に理解している場合は、後でディレクトリ構造内の複数のファイルに分割する連続したブロックを書き込んでいることを確認できます。

この場合、ファイルが小さくなるため、大きなブロックではなく、小さなブロックが必要になります。ブロック内のすべての空き領域がゼロになります。

[編集]これらの100Kファイルに対する外部のニーズは本当にありますか?インデックスを持つ単一のファイルで十分な場合があります。

于 2010-01-02T00:16:09.490 に答える
0

Normanの答えを拡張する:ファイルがすべて1つのファイルシステムに入る場合は、1つのヘルパースレッドのみを使用します。

読み取りスレッドと書き込みヘルパーの間の通信は、std::vectorヘルパーごとに2つのダブルバッファーで構成されます。(1つのバッファーは書き込みプロセスによって所有され、もう1つは読み取りプロセスによって所有されます。)読み取りスレッドは、指定された制限がブロックされるまでバッファーをいっぱいにします。書き込みスレッドに書き込み速度をgettimeofday掛けて、制限を調整します。書き込みが前回より速くなった場合は、バッファをX%増やします。遅くなった場合は、–X%調整します。Xは小さくすることができます。

于 2010-01-14T00:42:17.027 に答える