自分で作成した Python ツールを使用して、いくつかのシミュレーションを実行したいと思います。問題は、異なるパラメータや引数などを使用して、複数回呼び出す必要があることです。
for
今のところ、タスクには次のように複数のループを使用しています。
for simSeed in 1 2 3 4 5
do
for launchPower in 17.76 20.01 21.510 23.76
do
python sim -a $simSeed -p $launchPower
done
done
シミュレーションを同時に実行するために、&
シミュレーターを呼び出す行の末尾に を追加します。
python sim -a $simSeed -p $launchPower &
この方法を使用すると、複数のシードを実行できます。ただし、コンピューターのメモリが限られているため、内側のfor
ループを並列に起動し、外側のfor
ループを順番に起動するように上記のスクリプトを書き直したいと思います。
たとえば、 について、に等しいsimSeed = 1
5 つの異なるプロセスを実行したいとします。この部分が完了したらすぐに、 についてスクリプトを実行し、に等しい5 つの異なる並列プロセスを再度実行します。launchPower
17.76 20.01 21.510 23.76
simSeed = 2
launchPower
17.76 20.01 21.510 23.76
このタスクを達成するにはどうすればいいでしょうか?
要約:
外側のループを順番に実行し、内側のループを並列に実行して、内側のループの最後の並列プロセスが終了すると、外側のループが次の反復に移動するようにします。
答え1
GNU parallel には、ジョブを並列で開始するときにリソースの使用を制限するオプションがいくつかあります。
2つのネストされたループの基本的な使い方は次のようになります。
parallel python sim -a {1} -p {2} ::: 1 2 3 4 5 ::: 17.76 20.01 21.510 23.76
例えば、最大5つのジョブを同時に起動したい場合は、次のようにします。
parallel -j5 python <etc.>
あるいは、--memfree
十分なメモリが空いている場合にのみ新しいジョブを開始するオプションを使用することもできます(例:少なくとも256 MByte)。
parallel --memfree 256M python <etc.>
最後のオプションでは、メモリが指定された「予約」値の 50% を下回ると、最後に開始されたジョブが強制終了されることに注意してください (ただし、キャッチアップのために自動的に再キューに入れられます)。
答え2
コメントで述べたように、これはまさに GNUparallel
の目的です。
for simSeed in 1 2 3 4 5
do
## Launch 5 instances in parallel
parallel -j5 python sim -a $simSeed -p {} ::: 17.76 20.01 21.510 23.76
done
答え3
それぞれのプロセス ID を保存してwait
終了させることができます。
for simSeed in {1..5}; do
pids=()
for launchPower in 17.76 20.01 21.510 23.76; do
python sim -a $simSeed -p $launchPower &
pids+=($!)
done
wait ${pids[@]}
done
pids
内部ループのバックグラウンド ジョブのプロセス ID の配列です。${pids[@]}
配列のすべての要素が wait コマンドに渡されます。