web-dev-qa-db-ja.com

bashスクリプトでのマルチスレッド/フォーク

次の形式のbashスクリプトを作成しました。

#!/bin/bash
start=$(date +%s)
inFile="input.txt"
outFile="output.csv"

rm -f $inFile $outFile

while read line
do

    -- Block of Commands

done < "$inFile"

end=$(date +%s)

runtime=$((end-start))

echo "Program has finished execution in $runtime seconds."

whileループは$inFileから読み取り、行で何らかのアクティビティを実行し、結果を$outFileにダンプします。

$inFileは3500行以上あるため、スクリプトを完全に実行するには6〜7時間かかります。この時間を最小限に抑えるために、このスクリプトではマルチスレッドまたはフォークを使用することを計画しています。 8つの子プロセスを作成すると、$inFileの8行が同時に処理されます。

これはどのように行うことができますか?

9
Mandar Shinde

GNU parallel は、この種のもののために作られています。スクリプトは一度に何回でも実行でき、入力ごとに異なるデータがパイプラインされます。

cat input.txt | parallel --pipe your-script.sh

デフォルトでは、システムのプロセッサ数に応じてプロセスを生成しますが、-j Nでカスタマイズできます。

特に巧妙なトリックは、シバンラッピング機能です。 Bashスクリプトの最初の行を次のように変更した場合:

#!/usr/bin/parallel --Shebang-wrap --pipe /bin/bash

標準入力でデータをフィードすると、すべて自動的に行われます。最後に実行する必要があるクリーンアップコードがある場合、これはあまり役に立ちません。

注意すべきことがいくつかあります。 1つは、入力を連続したチャンクに分割し、一度に1つずつ使用することです。ラインをインターリーブしません。もう1つは、レコードの数に関係なく、それらのチャンクがサイズで分割されることです。 --block Nを使用して、異なるブロックサイズをバイト単位で設定できます。あなたの場合、ファイルサイズの8分の1以下がほぼ適切です。それ以外の場合は、ファイルが1つのブロックにすべて含まれるほど小さい可能性があり、目的を達成できない可能性があります。

特定の異なるユースケースには多くのオプションがありますが、 チュートリアル はかなりうまくカバーしています。興味のあるオプションには、--round-robin--groupがあります。

10
Michael Homer