GNU 平行連結參數與交替參數

GNU 平行連結參數與交替參數

我製作了一個基於使用者提供的參數運行的 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

相關內容