web-dev-qa-db-ja.com

中間ファイルなしで複数のファイルを1つにまとめるにはどうすればよいですか?

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

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

ファイルの読み取り/書き込み時間自体は数時間かかるため、以下を改善する方法を見つけたいと思います。

cat file1 file2 file3 ... fileN >> newBigFile
  1. file1 ... fileNが100Gを消費し、次にnewBigFileがさらに100Gbを消費し、次にfile1... fileNが削除されます。

  2. データはすでにfile1 ... fileNにあります。cat >>を実行すると、何百ものファイルを1つのファイルとして再現するために本当に必要なのは、読み取りと書き込みの時間です。 。

21
Wing

最終的な大きなファイルにランダムにアクセスする必要がない場合(つまり、最初から最後まで一度だけ読み取る)、何百もの中間ファイルを1つに見せることができます。あなたが通常行う場所

$ consume big-file.txt

代わりに

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

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

入力を分割して同時に処理を行うことで、時間とスペースを節約することもできます。 GNU Parallel には、これを正確に行う -pipe switch があります。また、出力を1つの大きなファイルに再構成することもできます。ディスク上のnumber-of-cores個を保持するだけでよいので、スクラッチ領域が少なくて済みます。一度。文字通り同時に何百ものプロセスを実行している場合、Parallelはマシンの並列処理の量を調整できるようにすることで効率を大幅に向上させます。私はそれを強くお勧めします。

12
Jay Hacker

多分ddは猫とシェルの間で物を渡す必要がないのでより速いでしょう。何かのようなもの:

mv file1 newBigFile
dd if=file2 of=newBigFile seek=$(stat -c %s newBigFile)
5
thejh

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

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

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

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

5
Robie Basak

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

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

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

4
frankc

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

3
Robert P

これは、同じフォルダに含まれるすべてのファイルを分類する最も速い方法だと思います。

$ ls [path to folder] | while read p; do cat $p; done
3
barbaric_pug

何百ものファイルを1つのファイルとして再現するために本当に必要なのは...

テキストファイルは通常ディスクブロックを正確に埋めないため、ファイルシステムレベルでファイルをそのまま結合するのが現実的ではない理由は、ギャップを埋めるために後続のファイルのデータを上に移動する必要があるためです。読み取り/書き込みの束とにかく

2
Kevin Stricker

同時実行性が高すぎるなどの問題があります。

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

すべての単純な分割/コピー/削除を使用してどちらの方法を実行しても、大量のIOPSが生成され、その物理学を回避する方法はありません。

これが日常的な問題である場合を除いて、おそらく価値があるよりも透過的な解決策は、単一のファイルを複数のファイルとして表すカスタムFuseファイルシステムを作成することです。これを行う方法の基本を示す個別のファイルとしてアーカイブファイルのコンテンツを処理する例はたくさんあります。

2
user177800