GNU Paralelo vincular argumentos con argumentos alternos

GNU Paralelo vincular argumentos con argumentos alternos

Creé un simulador de Python que se ejecuta en base a argumentos proporcionados por el usuario. Para usar el programa, ejecuto múltiples simulaciones aleatorias (controladas con un valor inicial). Utilizo GNU paralelo para ejecutar el simulador con argumentos de manera similar a la que se muestra a continuación:

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

Ahora, hay un tercer argumento --numque quiero usar, pero quiero vincular ese argumento con el valor inicial. De modo que, para cada valor inicial, solo se utiliza un valor numérico. Sin embargo, no se debe utilizar el mismo argumento numérico con todos los valores de potencia.

En pocas palabras, esta tabla debería ayudarle a comprender mejor:

| 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      |
....

(El formato de la tabla puede no ser adecuado para dispositivos móviles)

Si tuviera que escribir la implementación anterior usando un bucle for, haría algo como:

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

Donde power es una matriz 1D, semilla es una matriz 1D y num es una matriz 2D donde una fila representa los valores numéricos correspondientes para una potencia p.

Mi solución:

Utilice varias declaraciones paralelas para cada valor de potencia y utilice la--linkparámetrode paralelo para vincular los argumentos semilla y 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
...

El problema con esta solución sería que tendría que limitar la cantidad de trabajos para cada declaración en función de la cantidad de valores de potencia. Mi computadora puede manejar 50 procesos adicionales antes de sufrir un paro cardíaco, por lo tanto, para 3 valores de potencia, tendría que limitar los trabajos para cada declaración a 12.

lo que estoy buscando

Una sola línea de modo que no tenga que ejecutar varias declaraciones paralelas y fijar el número de trabajos en 50.

Respuesta1

No está claro cómo se determina num. Puede utilizar una matriz basada en potencia y semilla:

$ 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

O una matriz basada en el número de secuencia:

$ 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

O tal vez:

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

Respuesta2

Parapartede la respuesta quieres esto, ¿correcto?

$ 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

Si es así, una forma de hacer lo que creo que quieres sería

$ 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

Otra forma sería (con una clasificación para mostrarlo en el orden que desee; no sería necesario en la ejecución real):

$ 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

Otra forma más sería hacer que paralelo invoque paralelo:

$ 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

Esto funciona porque el paralelo "interno" usa comas en lugar de dos puntos como separadores de argumentos, por lo que el paralelo "externo" no "ve" el argumento vinculado.

Mientras trabajaba en una manera de hacerlo más comprensible (se supone que hay un '{}' allí), me di cuenta de que el último ejemplo no funcionaría exactamente para usted, porque el segundo y tercer argumento son una cadena. Así que agregué la aclaración y (¡otra más!) el paralelo para demostrar cómo ejecutarías tu simulador de 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

Para cualquier lista enumerada de valores

$ 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

Esta está llegando a ser una respuesta muy larga. Creo que tal vez quieras algo más parecido a esto, donde del 1 al 12 (número de potencias multiplicado por el número de semillas) son los valores únicos para cada combinación de potencia y semilla, y podría ser una lista enumerada de valores en lugar de {1..12 }? Tenga en cuenta que estoy vinculando poder y semilla en lugar de número y semilla.

$ 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

información relacionada