GNU Parallel の交互引数による引数のリンク

GNU Parallel の交互引数による引数のリンク

ユーザーが指定した引数に基づいて実行される Python シミュレーターを作成しました。プログラムを使用するには、複数のランダム シミュレーションを実行します (シード値で制御)。以下に示すのと同様の方法で、GNU parallel を使用して引数付きシミュレーターを実行します。

parallel 'run-sim --seed {1} --power {2}' ::: <seed args> ::: <power args>

ここで、使用したい 3 番目の引数があります--numが、その引数をシード値にリンクしたいと考えています。これにより、すべてのシード値に対して 1 つの num 値のみが使用されます。ただし、すべての power 値で同じ num 引数を使用するべきではありません。

簡単に言えば、この表を見れば理解が深まるはずです。

| Power      | Seed        | num          |
|:-----------|------------:|:------------:|
| 10         |      0      |     100      |
| 10         |      1      |     150      |
| 10         |      2      |     200      |
| 10         |      3      |     250      |
|:-----------|------------:|:------------:|
| 20         |      0      |     300      |
| 20         |      1      |     350      |
| 20         |      2      |     400      |
| 20         |      3      |     450      |
....

(表形式はモバイルデバイスには適さない可能性があります)

上記の実装を for ループを使用して記述すると、次のようになります。

for p in power:
   for s, n in (seed, num[p])
       simulate(p, s, n)

ここで、power は 1D 配列、seed は 1D 配列、num は 2D 配列であり、行は power p に対応する num 値を表します。

私の解決策:

各電力値に対して複数の並列ステートメントを使用し、--linkパラメータseed と num 引数をバインドするための並列処理です。

parallel --link 'run-sim --seed {1} --num {2} --power 10' ::: 0 1 2 3 ::: 100 150 200 250
parallel --link 'run-sim --seed {1} --num {2} --power 20' ::: 0 1 2 3 ::: 300 350 400 450
...

このソリューションの問題点は、パワー値の数に基づいて各ステートメントのジョブの数を制限する必要があることです。私のコンピューターは、心停止する前に 50 の追加プロセスを処理できます。したがって、パワー値が 3 の場合、各ステートメントのジョブを 12 に制限する必要があります。

私が探しているもの

複数の並列ステートメントを実行する必要がなく、ジョブの数を 50 に固定できる単一のライナー。

答え1

をどのように決定するかは不明ですnum。べき乗とシードに基づく配列を使用できます。

$ declare -A num=([10,0]=100 [10,1]=150 [10,2]=200 [10,3]=250 [20,0]=300 [20,1]=350 [20,2]=400 [20,3]=450 [30,0]=133 [30,1]=166 [30,2]=200 [30,3]=233)
$ env_parallel -j 50 echo power {1} seed {2} num '${num[{1},{2}]}' ::: 10 20 30 ::: 0 1 2 3

または、シーケンス番号に基づく配列:

$ num=(dummy 100 150 200 250 300 350 400 450 133 166 200 233)
$ env_parallel -j 50 echo power {1} seed {2} num '${num[{#}]}' ::: 10 20 30 ::: 0 1 2 3

または多分:

parallel -j 50 echo power {1} seed '{=1 $_=(seq()-1)%4=}' num {2} ::: 10 10 10 10 20 20 20 20 30 30 30 30 :::+ 100 150 200 250 300 350 400 450 133 166 200 233

答え2

のために一部あなたが望む答えはこれですよね?

$ parallel --link -k echo {1} {2} ::: {0..3} ::: {100..450..50}
0 100
1 150
2 200
3 250
0 300
1 350
2 400
3 450

もしそうなら、あなたが望むことを実現する一つの方法は

$ parallel -k echo {1} {2} ::: {10..20..10} ::: "$(parallel --link -k echo {1} {2} ::: {0..3} ::: {100..450..50})"
10 0 100
10 1 150
10 2 200
10 3 250
10 0 300
10 1 350
10 2 400
10 3 450
20 0 100
20 1 150
20 2 200
20 3 250
20 0 300
20 1 350
20 2 400
20 3 450

別の方法は次のとおりです (ソートを実行して希望の順序で表示しますが、実際の実行では必要ありません)。

$ parallel --link -k echo {1} {2} ::: {0..3} ::: {100..450..50} | parallel -a- echo {2} {1} ::: {10..20..10} | sort -k 1,1 -k3,3 -k2,2
10 0 100
10 1 150
10 2 200
10 3 250
10 0 300
10 1 350
10 2 400
10 3 450
20 0 100
20 1 150
20 2 200
20 3 250
20 0 300
20 1 350
20 2 400
20 3 450

さらに別の方法としては、parallel が parallel を呼び出すようにすることです。

$ parallel parallel --link --arg-sep ,,, echo {1} ,,, {0..3} ,,, {100..450..50} ::: {10..20..10}
10 0 100
10 1 150
10 2 200
10 3 250
10 0 300
10 1 350
10 2 400
10 3 450
20 0 100
20 1 150
20 2 200
20 3 250
20 0 300
20 1 350
20 2 400
20 3 450

これが機能するのは、「内側」の並列処理では引数の区切りにコロンの代わりにコンマが使用されるため、「外側」の並列処理ではリンクされた引数が「見えない」ためです。

これをもっと分かりやすくする方法を考えていたときに (そこには '{}' が想定されています)、2 番目と 3 番目の引数が 1 つの文字列であるため、最後の例は正確には機能しないことに気づきました。そこで、Python シミュレーターを実行する方法を示すために、説明と (さらにもう 1 つの!) 並列処理を追加しました。

$ parallel parallel --link --arg-sep ,,, -I [] echo {1} [] ,,, {0..3} ,,, {100..450..50} ::: {10..20..10} | parallel -C' ' echo foo {1} bar {2} blat {3}
foo 10 bar 0 blat 100
foo 10 bar 1 blat 150
foo 10 bar 2 blat 200
foo 10 bar 3 blat 250
foo 10 bar 1 blat 350
foo 10 bar 0 blat 300
foo 10 bar 2 blat 400
foo 10 bar 3 blat 450
foo 20 bar 0 blat 100
foo 20 bar 1 blat 150
foo 20 bar 2 blat 200
foo 20 bar 3 blat 250
foo 20 bar 0 blat 300
foo 20 bar 1 blat 350
foo 20 bar 2 blat 400
foo 20 bar 3 blat 450

列挙された値のリスト

$ parallel parallel --link --arg-sep ,,, -I [] echo {1} [] ,,, {0..3} ,,, v0.0 v0.1 v0.2 v0.3 v1.0 v1.1 v1.2 v1.3 ::: {10..20..10} | parallel -C' ' echo power {1} seed {2} num {3}
power 20 seed 0 num v0.0
power 20 seed 1 num v0.1
power 20 seed 2 num v0.2
power 20 seed 3 num v0.3
power 20 seed 0 num v1.0
power 20 seed 1 num v1.1
power 20 seed 2 num v1.2
power 20 seed 3 num v1.3
power 10 seed 0 num v0.0
power 10 seed 1 num v0.1
power 10 seed 2 num v0.2
power 10 seed 3 num v0.3
power 10 seed 0 num v1.0
power 10 seed 1 num v1.1
power 10 seed 2 num v1.2
power 10 seed 3 num v1.3

これは非常に長い回答になってしまいました。おそらく、1 から 12 (累乗の数 × シードの数) が各累乗とシードの組み合わせの一意の値であり、{1..12} ではなく列挙された値のリストであるような、このようなものが必要ではないでしょうか。num と seed ではなく、power と seed をリンクしていることに注意してください。

$ parallel --link echo {1} {2} ::: "$(parallel echo {1} {2} ::: {10..30..10} ::: {0..3})" ::: {1..12} | parallel -C' ' echo run-sim --power {1} --seed {2} --num {3}
run-sim --power 10 --seed 0 --num 1
run-sim --power 10 --seed 1 --num 2
run-sim --power 10 --seed 2 --num 3
run-sim --power 10 --seed 3 --num 4
run-sim --power 20 --seed 0 --num 5
run-sim --power 20 --seed 1 --num 6
run-sim --power 20 --seed 2 --num 7
run-sim --power 20 --seed 3 --num 8
run-sim --power 30 --seed 0 --num 9
run-sim --power 30 --seed 1 --num 10
run-sim --power 30 --seed 2 --num 11
run-sim --power 30 --seed 3 --num 12

関連情報