それぞれ2GBの250以上のファイルがあるフォルダがあります。これらのファイルで文字列/パターンを検索し、結果をoutput
に出力する必要があります ファイル。次のコマンドを実行できることはわかっていますが、遅すぎます!!
grep mypattern * > output
スピードアップしたいです。 Javaのプログラマーである私は、プロセスを高速化するためにマルチスレッドを使用できることを知っています。 grep
を開始する方法に固執しています 「マルチスレッドモード」で、出力を単一のoutput
に書き込みます ファイル。
承認された回答:
これには2つの簡単な解決策があります。基本的に、xargs
を使用します またはparallel
。
xargsアプローチ:
xargs
を使用できます find
を使用 次のように:
find . -type f -print0 | xargs -0 -P number_of_processes grep mypattern > output
number_of_processes
を置き換える場所 起動するプロセスの最大数によって。
ただし、パフォーマンスがI / Oに制限されている場合、これによって大きなパフォーマンスが得られるとは限りません。その場合、I / Oの待機で失われた時間を補うために、より多くのプロセスを開始しようとする可能性があります。
また、findを含めることで、変更時間など、ファイルパターンだけでなく、より高度なオプションを指定できます…
Stéphaneのコメントで説明されているように、このアプローチで考えられる問題の1つは、ファイルが少ない場合、xargs
それらのために十分に多くのプロセスを開始しない可能性があります。 1つの解決策は、-n
を使用することです。 xargs
のオプション パイプから一度にいくつの引数を取る必要があるかを指定します。 -n1
の設定 xargs
を強制します 単一のファイルごとに新しいプロセスを開始します。これは、ファイルが非常に大きく(この質問の場合のように)、ファイルの数が比較的少ない場合に望ましい動作になる可能性があります。ただし、ファイル自体が小さい場合、新しいプロセスを開始するオーバーヘッドが並列処理の利点を損なう可能性があります。その場合、-n
が大きくなります。 値が良くなります。したがって、-n
オプションは、ファイルのサイズと数に応じて微調整される場合があります。
並列アプローチ:
これを行う別の方法は、Ole TangeGNUParallelツールparallel
を使用することです。 、(ここで入手可能)。これにより、並列処理をより細かく制御でき、複数のホストに分散することもできます(たとえば、ディレクトリが共有されている場合に役立ちます)。
並列を使用する最も簡単な構文は次のとおりです。
find . -type f | parallel -j+1 grep mypattern
ここで、オプション-j+1
マシン上のコアの数を超えて1つのプロセスを開始するように並列に指示します(これはI / Oが制限されたタスクに役立つ場合があり、数を増やしてみる場合もあります)。
Parallelには、xargs
よりも優れた利点もあります。 各プロセスからの出力の順序を実際に保持し、連続した出力を生成します。たとえば、xargs
、プロセス1がp1L1
という行を生成する場合 、プロセス2は行p2L1
を生成します 、プロセス1は別の行p1L2
を生成します 、出力は次のようになります:
p1L1
p2L1
p1L2
一方、parallel
では 出力は次のようになります:
p1L1
p1L2
p2L1
これは通常、xargs
よりも便利です 出力。