我制作了一个基于用户提供的参数运行的 Python 模拟器。为了使用该程序,我运行了多个随机模拟(用种子值控制)。我使用 GNU 并行以类似的方式运行带参数的模拟器,如下所示:
parallel 'run-sim --seed {1} --power {2}' ::: <seed args> ::: <power args>
现在,我想使用第三个参数--num
,但希望将该参数与种子值链接起来。因此,对于每个种子值,仅使用一个数字值。但是,不应对每个幂值使用相同的 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 是一维数组,seed 是一维数组,num 是 2D 数组,其中一行表示幂 p 的相应 num 值。
我的解决方案:
对每个功率值使用多个并行语句,并使用--link
范围并行绑定种子和 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 --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
这是有效的,因为“内部”并行使用逗号而不是冒号作为参数分隔符,因此“外部”并行不会“看到”链接的参数。
当我正在研究一种使其更容易理解的方法时(其中有一个假定的“{}”),我意识到最后一个示例并不完全适合您,因为第二个和第三个参数是一个字符串。因此,我添加了澄清(又一个!)并行的内容,以演示如何运行 Python 模拟器。
$ 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 }?请注意,我链接的是 power 和 Seed,而不是 num 和 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