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 for
fü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 for
Schleife parallel und die äußere for
Schleife nacheinander startet.
Beispielsweise möchte ich, dass für 5 verschiedene Prozesse mit gleich simSeed = 1
ausgefü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 .launchPower
17.76 20.01 21.510 23.76
simSeed = 2
launchPower
17.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 --memfree
Option 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 wait
zur 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
pids
ist ein Array von Prozess-IDs der Hintergrundjobs der inneren Schleife. Dabei ${pids[@]}
werden alle Elemente des Arrays an den Wait-Befehl übergeben.