GNU Parallel-Verknüpfungsargumente mit alternierenden Argumenten

GNU Parallel-Verknüpfungsargumente mit alternierenden Argumenten

Ich habe einen Python-Simulator erstellt, der auf der Grundlage von vom Benutzer bereitgestellten Argumenten ausgeführt wird. Um das Programm zu verwenden, führe ich mehrere zufällige Simulationen aus (gesteuert mit einem Startwert). Ich verwende GNU parallel, um den Simulator mit Argumenten auf ähnliche Weise wie unten gezeigt auszuführen:

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

Nun gibt es ein drittes Argument --num, das ich verwenden möchte, das ich aber mit dem Startwert verknüpfen möchte. So dass für jeden Startwert nur ein Num-Wert verwendet wird. Allerdings sollte nicht für jeden Leistungswert dasselbe Num-Argument verwendet werden.

Kurz gesagt, diese Tabelle soll Ihnen zum besseren Verständnis verhelfen:

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

(Das Tabellenformat ist möglicherweise nicht für Mobilgeräte geeignet)

Wenn ich die obige Implementierung mit einer For-Schleife schreiben würde, würde ich etwa Folgendes tun:

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

Wobei „Power“ ein 1D-Array ist, „Seed“ ein 1D-Array und „Num“ ein 2D-Array, wobei eine Zeile die entsprechenden Num-Werte für eine Power p darstellt.

Meine Lösung:

Verwenden Sie mehrere parallele Anweisungen für jeden Leistungswert und verwenden Sie die--linkParametervon parallel, um die Seed- und Num-Argumente zu binden.

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

Das Problem bei dieser Lösung wäre, dass ich die Anzahl der Jobs für jede Anweisung basierend auf der Anzahl der Leistungswerte begrenzen müsste. Mein Computer kann 50 zusätzliche Prozesse verarbeiten, bevor er einen Herzstillstand erleidet. Daher müsste ich bei 3 Leistungswerten die Jobs für jede Anweisung auf 12 begrenzen.

Was ich suche

Ein einzelner Liner, sodass ich nicht mehrere parallele Anweisungen ausführen und die Anzahl der Jobs auf 50 begrenzen muss.

Antwort1

Es ist unklar, wie Sie bestimmen num. Sie können ein Array basierend auf Leistung und Startwert verwenden:

$ 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

Oder ein Array basierend auf der Sequenznummer:

$ 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

Oder vielleicht:

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

Antwort2

FürTeilSie möchten diese Antwort, richtig?

$ 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

Wenn ja, wäre eine Möglichkeit, das zu tun, was Sie meiner Meinung nach wollen,

$ 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

Eine andere Möglichkeit wäre (mit einer Sortierung, um es in der gewünschten Reihenfolge anzuzeigen; beim tatsächlichen Ausführen wäre dies nicht erforderlich):

$ 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

Eine weitere Möglichkeit wäre, parallel parallel aufzurufen:

$ 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

Dies funktioniert, weil die „innere“ Parallele Kommas anstelle von Doppelpunkten als Argumenttrenner verwendet, sodass die „äußere“ Parallele das verknüpfte Argument nicht „sieht“.

Während ich daran arbeitete, das verständlicher zu machen (da wird ein '{}' angenommen), wurde mir klar, dass das letzte Beispiel für Sie nicht ganz funktionieren würde, da das zweite und dritte Argument eine Zeichenfolge sind. Also fügte ich die Klarstellung hinzu und (noch eine!) Parallele, um zu demonstrieren, wie Sie Ihren Python-Simulator ausführen würden.

$ 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

Für jede aufgezählte Werteliste

$ 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

Dies wird eine sehr lange Antwort. Ich denke, Sie möchten vielleicht eher etwas in dieser Art, wo 1 bis 12 (Anzahl der Potenzen mal Anzahl der Seeds) die eindeutigen Werte für jede Kombination aus Potenz und Seed sind und eine aufgezählte Werteliste statt {1..12} sein könnte? Beachten Sie, dass ich Potenz und Seed verknüpfe und nicht Num und 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

verwandte Informationen