Bash aufeinanderfolgende und parallele Schleifen/Befehle

Bash aufeinanderfolgende und parallele Schleifen/Befehle

Ich möchte einige Simulationen mit einem von mir erstellten Python-Tool ausführen. Der Haken dabei ist, dass ich es mehrere Male mit unterschiedlichen Parametern/Argumenten usw. aufrufen müsste.

Im Moment verwende ich forfür die Aufgabe mehrere Schleifen, wie:

for simSeed in 1 2 3 4 5
do
    for launchPower in 17.76 20.01 21.510 23.76
    do
        python sim -a $simSeed -p $launchPower
    done
done

Damit die Simulationen gleichzeitig laufen, füge ich &am Ende der Zeile, in der ich den Simulator aufrufe, ein an.

python sim -a $simSeed -p $launchPower &

Mit dieser Methode kann ich mehrere solcher Seeds ausführen. Da mein Computer jedoch nur über begrenzten Speicher verfügt, möchte ich das obige Skript so umschreiben, dass es die innere forSchleife parallel und die äußere forSchleife nacheinander startet.

Beispielsweise möchte ich, dass für 5 verschiedene Prozesse mit gleich simSeed = 1ausgeführt werden . Sobald dieser Teil abgeschlossen ist, möchte ich, dass das Skript für und erneut 5 verschiedene parallele Prozesse mit gleich ausgeführt wird .launchPower17.76 20.01 21.510 23.76simSeed = 2launchPower17.76 20.01 21.510 23.76

Wie kann ich diese Aufgabe lösen?

Kurz zusammengefasst:

Ich möchte, dass die äußere Schleife sequenziell und die innere Schleife parallel ausgeführt wird, sodass die äußere Schleife mit der nächsten Iteration fortfährt, wenn der letzte parallele Prozess der inneren Schleife abgeschlossen ist.

Antwort1

GNU Parallel bietet mehrere Optionen zur Begrenzung der Ressourcennutzung beim parallelen Starten von Jobs.

Die grundlegende Verwendung für zwei verschachtelte Schleifen wäre

parallel python sim -a {1} -p {2} ::: 1 2 3 4 5 ::: 17.76 20.01 21.510 23.76

Wenn Sie beispielsweise höchstens 5 Jobs gleichzeitig starten möchten, können Sie sagen

parallel -j5 python <etc.>

Alternativ können Sie die --memfreeOption verwenden, neue Jobs erst zu starten, wenn genügend Speicher frei ist, z.B. mindestens 256 MByte

parallel --memfree 256M python <etc.>

Beachten Sie, dass die letzte Option den zuletzt gestarteten Job beendet, wenn der Speicher unter 50 % des angegebenen „Reserve“-Werts fällt (er wird jedoch automatisch erneut zum Aufholen in die Warteschlange gestellt).

Antwort2

Wie in den Kommentaren erwähnt, ist GNU genau dafür da parallel:

for simSeed in 1 2 3 4 5
do
    ## Launch 5 instances in parallel 
    parallel -j5 python sim -a $simSeed -p {} ::: 17.76 20.01 21.510 23.76
done

Antwort3

Sie können die jeweiligen Prozess-IDs speichern und waitzur Beendigung Folgendes ausführen:

for simSeed in {1..5}; do
  pids=()
  for launchPower in 17.76 20.01 21.510 23.76; do
    python sim -a $simSeed -p $launchPower &
    pids+=($!)
  done
  wait ${pids[@]}
done

pidsist ein Array von Prozess-IDs der Hintergrundjobs der inneren Schleife. Dabei ${pids[@]}werden alle Elemente des Arrays an den Wait-Befehl übergeben.

verwandte Informationen