次のシナリオを考えてみましょう。 A、B 2つのプログラムがあります。プログラムAは文字列行をstdoutとして出力し、プログラムBはstdinの文字列を処理します。もちろん、これら2つのプログラムの使い方は次のとおりです。
foo@bar:~$ A |B
これで1つのコアしか消費しないことがわかったので、次の質問があります。
プログラムAとBは同じコンピューティングリソースを共有していますか?可能であれば、AとBを同時に実行する方法はありますか?
私が気づいたもう一つのことは、AがBよりはるかに速く実行されることです。したがって、Bプログラムをさらに実行し、Aの出力ラインを並列に処理できるかどうか疑問に思います。
つまり、Aはその行を印刷し、その行を読み取るプログラムBのNインスタンス(誰が最初に読んでも関係なく)を処理し、stdoutとして印刷します。
だから私の最後の質問は次のとおりです。
競合状態やその他の不一致の可能性を心配することなく、複数のBプロセス内で出力をAにパイプする方法はありますか?
答え1
1つの問題split --filter
は、出力が混在する可能性があるため、プロセス1で半分のラインを取得し、次にプロセス2で半分のラインを取得することです。
GNU Parallelは混乱を保証しません。
だからあなたがしたいと仮定しましょう:
A | B | C
しかし、Bは非常に遅いので、並列化しようとしています。これにより、次のことができます。
A | parallel --pipe B | C
GNUパラレルは、デフォルトでブロックサイズが1MBの\ nに分割されます。 --recend と --block を使って調整できます。
GNU Parallelの詳細については、以下で確認できます。http://www.gnu.org/s/parallel/
わずか10秒でGNU Parallelをインストールできます。
$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh
紹介ビデオを見るhttp://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
答え2
を作成すると、A | B
2つのプロセスが発生します。すでに並列に実行します。 1つのコアしか使用していないと思われる場合は、CPUアフィニティの設定によるものであるか(別のアフィニティを持つプロセスを作成するツールがあるかもしれません)、1つのプロセスがコア全体を収容するのに十分な大きさではないためです。 「は分散コンピューティングではありません。
1つのAで複数のBを実行するには、次のオプションをsplit
含むツールが必要です。--filter
A | split [OPTIONS] --filter="B"
ただし、これは、B ジョブが同じ速度で実行されないため、出力の行の順序を妨げる可能性があります。これが問題になった場合は、Bi出力を中間ファイルにリダイレクトして最後に使用する必要がありますcat
。これにより、かなりのディスク容量が必要になることがあります。
他のオプションもあります。たとえば、Bの各インスタンスをバッファリングされた出力の1行に制限し、Bの完全な「回転」が完了するのを待ってから、次の操作を実行できます。減らすsplit
到着地図、一時出力も含むcat
)、効率レベルが異なります。たとえば、先ほど説明した「ラウンド」オプションは、Bの最も遅いインスタンス[m]buffer
したがって、タスクが何であるかに応じて、役に立つかもしれないしそうでないかもしれないBの利用可能なバッファリングに大きく依存します。
はい
最初の1000個の数字を生成し、行数を並列に計算します。
seq 1 1000 | split -n r/10 -u --filter="wc -l"
100
100
100
100
100
100
100
100
100
100
行を「表示」すると、最初の行がプロセス#1に送信され、5番目の行がプロセス#5に送信される方法がわかります。さらに、第2のプロセスを生成するのにかかる時間の間、第1のsplit
プロセスは既にクォータを確保するのに適している。
seq 1 1000 | split -n r/10 -u --filter="sed -e 's/^/$RANDOM - /g'" | head -n 10
19190 - 1
19190 - 11
19190 - 21
19190 - 31
19190 - 41
19190 - 51
19190 - 61
19190 - 71
19190 - 81
2コアシステムで実行されると、プロセスはコアを共有しますが、seq
詳しく見ると、システムは最初の2つのプロセスをCPU0に残し、CPU1をワーカープロセスに割り当てます。split
wc
%Cpu0 : 47.2 us, 13.7 sy, 0.0 ni, 38.1 id, 1.0 wa, 0.0 hi, 0.0 si, 0.0 st
%Cpu1 : 15.8 us, 82.9 sy, 0.0 ni, 1.0 id, 0.0 wa, 0.3 hi, 0.0 si, 0.0 st
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
5314 lserni 20 0 4516 568 476 R 23.9 0.0 0:03.30 seq
5315 lserni 20 0 4580 720 608 R 52.5 0.0 0:07.32 split
5317 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.86 wc
5318 lserni 20 0 4520 572 484 S 14.0 0.0 0:01.88 wc
5319 lserni 20 0 4520 576 484 S 13.6 0.0 0:01.88 wc
5320 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.85 wc
5321 lserni 20 0 4520 572 484 S 13.3 0.0 0:01.84 wc
5322 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.86 wc
5323 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.86 wc
5324 lserni 20 0 4520 576 484 S 13.3 0.0 0:01.87 wc
特にsplit
CPUを多用することに注意してください。これは、Aの要件に比例して減少します。つまり、AがAより重いプロセスの場合、seq
Aの相対的なオーバーヘッドがsplit
減少します。しかし、Aが非常に軽いプロセスでBが非常に速い場合(したがって、Aとの整合性を維持するために2-3B以上は必要ありません)、次のようにsplit
並列化します(または通常パイプライン)。可能そんな価値がない。