wake-up-neo.net

Paralleles Ausführen des Shell-Skripts

Ich habe ein Shell-Skript welches 

  1. mischt eine große Textdatei (6 Millionen Zeilen und 6 Spalten) 
  2. sortiert die Datei anhand der ersten Spalte
  3. gibt 1000 Dateien aus 

Der Pseudocode sieht also so aus 

file1.sh 

#!/bin/bash
for i in $(seq 1 1000)
do

  Generating random numbers here , sorting  and outputting to file$i.txt  

done

Gibt es eine Möglichkeit, dieses Shell-Skript in parallel auszuführen, um Multi-Core-CPUs voll zu nutzen?

Im Moment wird ./file1.sh in der Reihenfolge 1 bis 1000 ausgeführt und ist sehr langsam.

Danke für Ihre Hilfe.

41
Tony

Check out bash subshells , damit können Teile eines Skripts parallel ausgeführt werden.

Ich habe das nicht getestet, aber das könnte ein Anfang sein:

#!/bin/bash
for i in $(seq 1 1000)
do
   ( Generating random numbers here , sorting  and outputting to file$i.txt ) &
   if (( $i % 10 == 0 )); then wait; fi # Limit to 10 concurrent subshells.
done
wait
42
Anders Lindahl

Ein weiterer sehr praktischer Weg, dies zu tun, ist gnu parallel , der sich lohnt, wenn Sie ihn noch nicht installiert haben. Dies ist von unschätzbarem Wert, wenn die Aufgaben nicht unbedingt die gleiche Zeit in Anspruch nehmen.

seq 1000 | parallel -j 8 --workdir $PWD ./myrun {}

startet ./myrun 1, ./myrun 2 usw. und stellt sicher, dass 8 Jobs gleichzeitig ausgeführt werden. Es können auch Knotenlisten erstellt werden, wenn Sie mehrere Knoten gleichzeitig ausführen möchten, z. B. in einem PBS-Job. Unsere Anweisungen an unsere Benutzer, wie dies auf unserem System zu tun ist, lauten hier .

Aktualisiert, um Folgendes hinzuzufügen: Sie möchten sicherstellen, dass Sie gnu-parallel verwenden, nicht das eingeschränktere Dienstprogramm mit demselben Namen, das im moreutils-Paket enthalten ist (Die abweichende Geschichte der beiden wird beschrieben hier .)

85
Jonathan Dursi

Damit Dinge parallel laufen, verwenden Sie '&' am Ende eines Shell-Befehls, um ihn im Hintergrund auszuführen. Dann wartet wait standardmäßig (d. H. Ohne Argumente), bis alle Hintergrundprozesse abgeschlossen sind. Also, vielleicht 10 parallel starten, dann warten, dann noch zehn. Mit zwei verschachtelten Schleifen ist dies problemlos möglich.

13
Tony Delroy

In der Dokumentation für GNU parallel gibt es eine ganze Liste von Programmen , die Jobs parallel von einer Shell aus ausführen kann, die sogar Vergleiche zwischen ihnen enthält. Es gibt viele, viele Lösungen. Eine weitere gute Nachricht ist, dass sie bei der Planung von Jobs wahrscheinlich ziemlich effizient sind, so dass alle Kerne/Prozessoren jederzeit beschäftigt sind.

9
Eric O Lebigot

Es gibt ein einfaches, tragbares Programm, das genau das für Sie tut: PPSS . PPSS plant automatisch Jobs für Sie, indem Sie prüfen, wie viele Kerne verfügbar sind, und jedes Mal einen anderen Job starten, wenn ein anderer gerade beendet wird.

4
Eric O Lebigot
IDLE_CPU=1
NCPU=$(nproc)

int_childs() {
    trap - INT
    while IFS=$'\n' read -r pid; do
        kill -s SIGINT -$pid
    done < <(jobs -p -r)
    kill -s SIGINT -$$
}

# cmds is array that hold commands
# the complex thing is display which will handle all cmd output
# and serialized it correctly

trap int_childs INT
{
    exec 2>&1
    set -m

    if [ $NCPU -gt $IDLE_CPU ]; then
        for cmd in "${cmds[@]}"; do
            $cmd &
            while [ $(jobs -pr |wc -l) -ge $((NCPU - IDLE_CPU)) ]; do
                wait -n
            done
        done
        wait

    else
        for cmd in "${cmds[@]}"; do
            $cmd
        done
    fi
} | display
0
Zakaria