圧縮されたテキストファイルですべての一致を検索するとします。
$ gzcat file.txt.gz | pv --rate -i 5 | grep some-pattern
pv --rate
ここではパイプスループットの測定に使用されます。私のマシンでは、約420Mb/s(解凍後)です。
現在、GNU parallelを使用して並列grepを実行しようとしています。
$ gzcat documents.json.gz | pv --rate -i 5 | parallel --pipe -j4 --round-robin grep some-pattern
現在、スループットは約260Mb/sに低下しています。そして、より興味をそそるparallel
プロセス自体は、多くのCPUを使用しています。 grep
プロセスより多い(ただしgzcat
未満)。
EDIT 1:さまざまなブロックサイズ(--block
)と、-N
/-L
オプションのさまざまな値を試しました。現時点では何も助けになりません。
私は何が間違っているのですか?
GNU Parallelの--pipe
を使用して270MB/sを取得できることに本当に驚いています。私のテストは通常約100MB/sで最大になります。
あなたのボトルネックはGNU Parallel:--pipe
はあまり効率的ではありません。ただし、--pipepart
は次のようになります:1 GB /秒のオーダーで取得できます。 CPUコアごと。
残念ながら、--pipepart
の使用にはいくつかの制限があります。
例:
parallel --pipepart -a bigfile --block 100M grep somepattern
grepは非常に効果的です-それを並行して実行する意味はありません。あなたのコマンドでは、解凍だけがより多くのCPUを必要としますが、これを並列化することはできません。
入力を並列で分割するには、grepで一致する行を取得するよりも多くのCPUが必要です。
Grepの代わりに、各行にはるかに多くのCPUが必要なものを使用したい場合は、状況が変化します。並列処理の方が意味があります。
この操作を高速化したい場合は、ボトルネックがどこにあるかを調べてください。おそらく、解凍(他の解凍ツールまたはより優れたCPUの使用に役立ちます)または-ディスクからの読み取り(他の解凍ツールまたはより優れたディスクシステムの使用に役立ちます)です。
私の経験から(たとえば、lzma(-2など)を使用してファイルを圧縮/解凍する方が良い場合があります)、gzipよりも圧縮率が高いため、ディスクから読み取る必要のあるデータがはるかに少なく、速度は同等です。
ここでのボトルネックは減圧です。解凍が内部的に並列化されていない場合、自分でそれを達成することはできません。そのようなジョブが複数ある場合は、もちろんそれらを並行して起動しますが、パイプライン自体を並列化するのは困難です。 1つのストリームを並列ストリームに分割することは、ほとんど価値がなく、同期とマージで非常に苦痛になる可能性があります。複数のコアが実行中のすべてのタスクに役立つとは限らないことを受け入れる必要がある場合があります。
一般に、シェルでの並列化は、ほとんどの場合、独立したプロセスのレベルで行う必要があります。