15

Python マルチプロセッシングを使用して、プロセスごとに一時出力ファイルを生成しています。それらのサイズは数 GB になる可能性があり、私はこれらを数十個作成します。これらの一時ファイルは、目的の出力を形成するために連結する必要があり、これがボトルネック (および並列処理キラー) であることが証明されているステップです。ファイルシステムのメタデータを変更して連結ファイルを作成し、実際にはコンテンツをコピーしない Linux ツールはありますか? 私が受け入れられるLinuxシステムで動作する限り。しかし、ファイル システム固有のソリューションはあまり役に立ちません。

私はOSまたはCSのトレーニングを受けていませんが、理論的には、新しいiノードを作成し、コピー元のファイルのiノードからiノードポインター構造をコピーして、それらのiノードのリンクを解除できるはずです。これを行うユーティリティはありますか?十分に考え抜かれた UNIX ユーティリティが豊富にあることを考えると、そうなることを完全に期待していましたが、何も見つかりませんでした。したがって、SOに関する私の質問。この情報が重要な場合に備えて、ファイルシステムは実際にはハードディスクであるブロックデバイス上にあります。これまでにシステム レベルのプログラミングを行ったことがないので、これを自分で書く自信はありません。そのため、(C/Python コード スニペットへの) ポインタは非常に役立ちます。

4

6 に答える 6

15

そのようなツールがあったとしても、最後のファイルを除くファイルのサイズがファイルシステムのブロック サイズの倍数であることが保証されている場合にのみ機能します。

データが一時ファイルに書き込まれる方法を制御し、それぞれのサイズがわかって いる場合は、代わりに次の操作を実行できます。

  1. fseek()マルチプロセッシングを開始する前に、最終的な出力ファイルを作成し、最後まで ing し て最終的なサイズに 拡張すると、スパース ファイルが作成されます。

  2. マルチプロセッシングを開始し、各プロセスに FD とオフセットをファイルの特定のスライスに渡します。

このように、プロセスは共同で 1 つの出力ファイルを埋めるため、後でそれらをまとめる必要がなくなります。

編集

個々のファイルのサイズを予測できないが、最終ファイルのコンシューマーが (ランダム アクセスではなく) シーケンシャル入力を処理できる場合はcat tmpfile1 .. tmpfileN、標準入力のいずれかでコンシューマーにフィードできます。

cat tmpfile1 ... tmpfileN | consumer

または名前付きパイプ経由 (bash のプロセス置換を使用):

consumer <(cat tmpfile1 ... tmpfileN)
于 2011-05-05T06:39:42.007 に答える
5

各一時ファイルのサイズを事前に知らないことを示しています。これを念頭に置いて、あなたの最善の策は、チャンクを単一の大きなファイルとして表示するFUSEファイルシステムを作成し、それらを基礎となるファイルシステム上の個別のファイルとして保持することだと思います.

このソリューションでは、プロデュース アプリとコンシューマー アプリは変更されません。プロデューサは、FUSE レイヤーが 1 つのファイルとして表示する一連のファイルを書き出します。この仮想ファイルは、消費者に提示されます。

FUSE には、 Python を含む多数の言語のバインディングがあります。ここまたはここでいくつかの例を見ると(これらはさまざまなバインディング用です)、これには驚くほど少ないコードが必要です。

于 2011-05-05T06:47:36.877 に答える
3

4 ファイルの場合。xaa、xab、xac、xad (ルートとして) bash での高速連結:

losetup -v -f xaa; losetup -v -f xab; losetup -v -f xac; losetup -v -f xad

(loop0、loop1、loop2、loop3 が新しいデバイス ファイルの名前であるとします。)

http://pastebin.com/PtEDQH7Gを「 join_us 」スクリプト ファイルに入れます。次に、次のように使用できます。

./join_us /dev/loop{0..3}

次に (この大きなファイルが映画の場合)、その所有権を通常のユーザー (chown itsme /dev/mapper/joined) に与えると、そのユーザーは mplayer /dev/mapper/joined 経由で再生できます。

これらの後のクリーンアップ (ルートとして):

dmsetup remove joined; losetup -d /dev/loop[0123]
于 2013-09-18T08:52:57.570 に答える
2

そうは思いませんが、iノードは整列されている可能性があるため、あるファイルのフッターと別のファイルのヘッダーの間にゼロ(または不明なバイト)を残しても問題がない場合にのみ可能です。

これらのファイルを連結する代わりに、複数のファイルからのソーシングをサポートするように分析ツールを再設計することをお勧めします。ログファイルを例にとると、多くのログアナライザは、1日ごとにログファイルを読み取ることをサポートしています。

編集

@san:使用中のコードを制御できないと言うように、名前付きパイプを使用して、個別のファイルをその場で連結できます。

$ mkfifo /tmp/cat
$ cat file1 file2 ... >/tmp/cat &
$ user_program /tmp/cat
...
$ rm /tmp/cat
于 2011-05-05T06:42:00.040 に答える
0

いいえ、そのようなツールやシステムコールはありません。

各プロセスが最終ファイルに直接書き込むことができるかどうかを調査することができます。プロセス 1 がバイト 0-X を書き込み、プロセス 2 が X-2X を書き込むとします。

于 2011-05-05T06:40:18.687 に答える
0

考えられる代替手段は、すべての一時ファイルを名前付きパイプに cat し、その名前付きパイプを単一入力プログラムへの入力として使用することです。単一入力プログラムが入力を順次読み取り、シークしない限り。

于 2011-05-05T06:53:25.073 に答える