web-dev-qa-db-ja.com

複数のファイルでのプログラムの並列実行

フォルダーのすべてのファイルをループして(通常は長時間続く)コマンドを実行する小さなスクリプトがあります。基本的には

for file in ./folder/*;
do
    ./bin/myProgram $file > ./done/$file
done

(構文エラーは無視してください。これは単なる擬似コードです)。

このスクリプトを同時に2回実行する必要がありました。 ./done/$fileが存在する場合は、明らかに実行は不要です。スクリプトを次のように変更しました

for file in ./folder/*;
do
    [ -f ./done/$file ] || ./bin/myProgram $file >./done/$file
done

つまり、基本的に問題は、両方のスクリプト(または一般に複数のスクリプト)が実際に同じポイントにあり、失敗してコマンドが2回実行されるdoneファイルの存在を確認することは可能ですか?

それは完璧だろうが、私はそれを非常に疑っている。これは簡単すぎるでしょう:D同じファイルを処理する可能性がある場合、スクリプトを何らかの方法で「同期」することは可能ですか?

7
stefan

これは可能であり、実際に発生します。この状況を回避するには、 ロックファイル を使用します。上記のページの例:

if mkdir /var/lock/mylock; then
    echo "Locking succeeded" >&2
else
    echo "Lock failed - exit" >&2
    exit 1
fi

# ... program code ...

rmdir /var/lock/mylock
4
Chris Down

スクリプトの2つのインスタンスは確かにこのように相互作用する可能性があり、コマンドが2回実行されます。これは 競合状態 と呼ばれます。

この競合状態を回避する1つの方法は、各インスタンスが入力ファイルを別のディレクトリに移動して取得した場合です。 (同じファイルシステム内の)ファイルの移動は atomic です。入力ファイルの移動は望ましくない場合があり、これはすでに少し複雑になっています。

mkdir staging-$$ making-$$
for input in folder/*; do
  name=${x#folder/}
  staging=staging-$$/$name
  output=making-$$/$name
  destination=done/$name
  if mv -- "$input" "$staging" 2>/dev/null; then
    bin/myProgram "$staging" >"$output"
    mv -- "$output" "$destination"
    mv -- "$staging" "$input"
  fi
done

広く利用可能なツールを使用してファイルを並列処理する簡単な方法は、 GNU make-j並列実行のフラグ 。このタスクのmakefileを次に示します(タブを使用してコマンドをインデントすることを忘れないでください)。

all: $(patsubst folder/%,done/%,$(wildcard folder/*))
done/%: folder/%
        ./bin/myProgram $< >[email protected]
        mv [email protected] $@

実行make -j 3 3つのインスタンスを並行して実行します。

参照 4つのタスクを並行して実行...どうすればよいですか?

あなたが本当に複数のジョブを並行して実行しようとしていると感じています。ロックファイルは単に目的を達成するための手段にすぎません。

GNU Parallel http://www.gnu.org/software/parallel/ がインストールされている場合、これを行うことができます:

parallel ./bin/myProgram ::: ./folder/*

MyProgramを各コアで並行して実行します。

GNU Parallelは、次の方法で簡単にインストールできます。

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem

GNU Parallelの紹介動画をご覧ください:詳細は https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

1
Ole Tange

ロックの問題は、中断できないロック(アトマと呼ばれることもある)を作成するメソッドが必要なことです。 Chrisが彼の回答で書いたように、mkdirはそのような中断のない操作です(ファイルの作成はそのような操作ではありません)。

高レベルのコマンドもあります-通常はprocmailパッケージに隠されています:lockfile。このコマンドにはいくつかの素晴らしい機能があり、「ホイールを再発明」する必要なく、独自のスクリプトで簡単に使用できます(たとえば、ディレクトリの作成に基づいてロックする独自の関数を書く)。

0
Nils