25

これが私が直面している問題です:

  • サイズが100G以下のテキストファイルを文字列処理しています。
  • ファイルを何百もの小さなファイルに分割し、それらを並行して処理することで、ランタイムを改善しようとしています。
  • 最後に、結果のファイルを順番にまとめます。

ファイルの読み書き時間自体に何時間もかかるので、以下の点を改善する方法を見つけたいです。

cat file1 file2 file3 ... fileN >> newBigFile
  1. これには、file1...fileNが 100G をnewBigFile占有し、さらに 100Gb を消費し、さらにfile1...fileNが削除されるため、2 倍のディスク容量が必要になります。

  2. データはすでにfile1...fileNcat >>あり、何百ものファイルを 1 つのファイルとして再表示するだけで本当に必要なときに、読み取りと書き込みの時間がかかります...

4

8 に答える 8

14

最終的な大きなファイルにランダム アクセスする必要がない場合 (つまり、最初から最後まで 1 回読み通すだけでよい場合)、数百の中間ファイルを 1 つのファイルとして表示することができます。普段やっているところ

$ consume big-file.txt

代わりに

$ consume <(cat file1 file2 ... fileN)

これは、「匿名の名前付きパイプ」とも呼ばれるUnixプロセス置換を使用します。

入力を分割して同時に処理を行うことで、時間とスペースを節約できる場合もあります。GNU Parallelには、まさにこれを行う--pipe スイッチがあります。また、出力を 1 つの大きなファイルに再構築することもできます。一度にディスク上に保持する必要があるのはコアの数だけであるため、使用するスクラッチ スペースが少なくなる可能性があります。文字通り何百ものプロセスを同時に実行している場合、Parallel を使用すると、マシンの並列処理の量を調整できるため、効率が大幅に向上します。強くお勧めします。

于 2011-06-27T19:03:57.617 に答える
7

ファイルを連結して戻す場合、小さなファイルが追加されたときにそれらを削除できます。

for file in file1 file2 file3 ... fileN; do
  cat "$file" >> bigFile && rm "$file"
done

これにより、スペースを 2 倍にする必要がなくなります。

ファイルを魔法のように連結する方法は他にありません。ファイルシステム API には、それを行う関数がありません。

于 2010-11-01T21:24:52.813 に答える
5

dd猫とシェルの間で物を渡す必要がないので、おそらくもっと速いでしょう。何かのようなもの:

mv file1 newBigFile
dd if=file2 of=newBigFile seek=$(stat -c %s newBigFile)
于 2010-11-01T19:30:16.680 に答える
4

ファイルを単純に分割しないことは可能ですか? 代わりに、各並列ワーカーでファイル ポインターを設定して、ファイルをチャンクで処理します。ファイルを行指向の方法で処理する必要がある場合、それはより複雑になりますが、それでも実行できます。各ワーカーは、与えられたオフセットから開始するのではなく、最初にバイトごとに次の改行 +1 までシークする必要があることを理解する必要があります。各ワーカーは、指定された設定バイト数を処理するのではなく、処理に割り当てられた設定バイト数の後に最初の改行を処理する必要があることも理解する必要があります。

ファイル ポインタの実際の割り当てと設定は非常に簡単です。n 個のワーカーがある場合、それぞれが n/file size バイトを処理し、ファイル ポインターはワーカー番号 * n/file_size から始まります。

そのような計画では不十分な理由がありますか?

于 2010-11-01T21:18:19.633 に答える
4

本当に必要なのは、何百ものファイルが 1 つのファイルとして再表示されることだけです...

通常、テキスト ファイルはディスク ブロックを正確に満たすわけではないため、ファイル システム レベルでファイルを結合するだけでは実用的ではないため、ギャップを埋めるために後続のファイルのデータを上に移動する必要があり、とにかくたくさんの読み書き。

于 2010-11-01T19:41:43.063 に答える
3

高速ですが、無料のソリューションではありませんか? SSD ドライブまたはフラッシュ PCIe ベースのストレージを入手してください。これを定期的に行う必要がある場合は、ディスク IO 速度を向上させることが、最も費用対効果が高く、最速のスピードアップになります。

于 2010-11-01T19:27:42.253 に答える
2

同時実行が多すぎるということもあります。

これを行うためのより良い方法は、目的の範囲でファイルへのランダムアクセス読み取りを使用し、実際にはファイルを分割せず、マシンの物理 CPU/コアの数としてファイルの数のみを処理することです。つまり、それが IOPS でディスクを圧倒している場合を除き、ディスクがボトルネックでなくなるまで削減する必要があります。

ナイーブな分割/コピー/削除のいずれかで行っていることは、大量の IOPS を生成しており、その物理を回避する方法はありません。

これが継続的な日常の問題/問題でない限り、おそらく価値があるよりも多くの作業になる透過的なソリューションは、単一のファイルを複数のファイルとして表すカスタム FUSE ファイルシステムを作成することです。アーカイブ ファイルの内容を個々のファイルとして扱う例がたくさんあり、これを行う方法の基本を示しています。

于 2011-06-27T19:16:43.883 に答える