Paralleles Ausführen von Programmen mit xargs

86

Ich habe derzeit das aktuelle Skript.

#!/bin/bash
# script.sh

for i in {0..99}; do
   script-to-run.sh input/ output/ $i
done

Ich möchte es parallel mit xargs ausführen. Ich habe versucht

script.sh | xargs -P8

Dies wird jedoch nur einmal ausgeführt. Auch mit -n8 kein Glück. Wenn Sie & am Ende der Zeile hinzufügen, die im Skript für die Schleife ausgeführt werden soll, wird versucht, das Skript 99 Mal gleichzeitig auszuführen. Wie führe ich die Schleife jeweils nur 8 aus, bis zu 100 insgesamt.

Olivier
quelle
Das wollte ich ursprünglich tun, musste aber auf xargs zurückgreifen, weil ich unter Windows bin. Ich konnte GNU Parallel unter Windows nicht zum Laufen bringen
Olivier
Ruft sich das Skript selbst auf oder haben Sie die Namen nur verwechselt, als Sie hier gefragt haben?
Etan Reisner
Entschuldigung, es sollte ein anderes Skript aufrufen. Ich werde es reparieren
Olivier
Die Antwort auf stackoverflow.com/questions/3321738/… ist hier relevant.
Etan Reisner

Antworten:

129

Von der xargsManpage:

Diese Handbuchseite dokumentiert die GNU-Version von xargs. xargs liest Elemente aus der Standardeingabe, die durch Leerzeichen (die durch doppelte oder einfache Anführungszeichen oder einen Backslash geschützt werden können) oder Zeilenumbrüche begrenzt sind, und führt den Befehl (Standard ist / bin / echo) ein- oder mehrmals mit den folgenden Anfangsargumenten aus durch Elemente, die aus der Standardeingabe gelesen wurden. Leerzeilen am Standardeingang werden ignoriert.

Dies bedeutet, dass in Ihrem Beispiel xargsdie gesamte Ausgabe Ihres Skripts gewartet und gesammelt und dann ausgeführt wird echo <that output>. Nicht gerade so nützlich oder was Sie wollten.

Das -nArgument ist, wie viele Elemente aus der Eingabe mit jedem Befehl verwendet werden sollen, der ausgeführt wird (nichts an sich über Parallelität hier).

Um das zu tun, was Sie wollen xargs, müssten Sie etwas Ähnliches tun (ungetestet):

printf %s\\n {0..99} | xargs -n 1 -P 8 script-to-run.sh input/ output/

Was so zusammenbricht.

  • printf %s\\n {0..99}- Drucken Sie eine Zahl pro Zeile von 0bis 99.
  • Lauf xargs
    • Nehmen Sie höchstens ein Argument pro Befehlszeile
    • und führen Sie bis zu acht Prozesse gleichzeitig aus
Etan Reisner
quelle
8
Eigentlich müssen Sie die Argumente nicht in separate Zeilen setzen; xargs Wortspaltungen. So echo {0..99} |würde genauso gut funktionieren. <<<{0..99}scheint nicht zu funktionieren; Obwohl <<<wordes als Klammer-expandierendes Wort dokumentiert ist, funktioniert es mit keiner Version von Bash, die ich zur Hand habe.
Rici
1
@rici Sieht dann wie ein Dokumentationsfehler aus, zumal in der Dokumentation zu Here Documents die Klammererweiterung nicht erwähnt wird (und dies auch dort in einem Schnelltest nicht der Fall ist), obwohl auch die Tilde-Erweiterung nicht erwähnt wird (was nicht der Fall ist) für <<aber tut für <<<so *shrug*). Die Erweiterungen, die hier in den Dokumenten und hier in den Zeichenfolgen vorkommen und nicht, sind für mich etwas seltsam.
Etan Reisner
1
Wie können Sie Ergebnisse von verschiedenen Läufen mit z. B. Zeilenumbrüchen trennen?
Nirvana-Msu
3
Demo: time head -12 <(yes "1") | xargs -n1 -P4 sleepFührt 12 sleep 1Befehle aus, 4 parallel. Der Befehl dauert 3 Sekunden.
Walter A
66

Mit GNU Parallel würden Sie Folgendes tun:

parallel script-to-run.sh input/ output/ {} ::: {0..99}

Fügen -P8Sie hinzu, wenn Sie nicht einen Job pro CPU-Kern ausführen möchten.

Im Gegensatz xargsdazu wird The Right Thing ausgeführt, auch wenn die Eingabe Leerzeichen 'oder "enthält (dies ist hier jedoch nicht der Fall). Außerdem wird sichergestellt, dass die Ausgabe von verschiedenen Jobs nicht miteinander gemischt wird. Wenn Sie also die Ausgabe verwenden, sind Sie es garantiert, dass Sie von zwei verschiedenen Jobs keine halbe Linie bekommen.

GNU Parallel ist ein allgemeiner Parallelisierer und erleichtert das parallele Ausführen von Jobs auf demselben Computer oder auf mehreren Computern, auf die Sie SSH-Zugriff haben.

Wenn Sie 32 verschiedene Jobs haben, die Sie auf 4 CPUs ausführen möchten, besteht eine einfache Möglichkeit zur Parallelisierung darin, 8 Jobs auf jeder CPU auszuführen:

Einfache Planung

GNU Parallel erzeugt stattdessen einen neuen Prozess, wenn man fertig ist - die CPUs bleiben aktiv und sparen so Zeit:

GNU Parallele Planung

Installation

Wenn GNU Parallel nicht für Ihre Distribution gepackt ist, können Sie eine persönliche Installation durchführen, für die kein Root-Zugriff erforderlich ist. Dies kann in 10 Sekunden erfolgen:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 67bd7bc7dc20aff99eb8f1266574dadb
12345678 67bd7bc7 dc20aff9 9eb8f126 6574dadb
$ md5sum install.sh | grep b7a15cdbb07fb6e11b0338577bc1780f
b7a15cdb b07fb6e1 1b033857 7bc1780f
$ sha512sum install.sh | grep 186000b62b66969d7506ca4f885e0c80e02a22444
6f25960b d4b90cf6 ba5b76de c1acdf39 f3d24249 72930394 a4164351 93a7668d
21ff9839 6f920be5 186000b6 2b66969d 7506ca4f 885e0c80 e02a2244 40e8a43f
$ bash install.sh

Weitere Installationsoptionen finden Sie unter http://git.savannah.gnu.org/cgit/parallel.git/tree/README

Mehr erfahren

Weitere Beispiele: http://www.gnu.org/software/parallel/man.html

Sehen Sie sich die Intro-Videos an: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Gehen Sie durch das Tutorial: http://www.gnu.org/software/parallel/parallel_tutorial.html

Melden Sie sich für die E-Mail-Liste an, um Unterstützung zu erhalten: https://lists.gnu.org/mailman/listinfo/parallel

Ole Tange
quelle
19
Dies beantwortet weder die Frage noch weist es darauf hin, warum xargs nicht dasselbe erreichen können.
实 唯
8
Downvote, weil xarg für mich genau das tut, was das zweite Bild zeigt.
Noonex
3
@noonex Ist Ihnen bewusst, dass nicht jeder die von Ihnen verwendete Version von xargs verwendet und dass -P nicht in allen Versionen von xargs enthalten ist?
Ole Tange
20
Vielleicht wissen nicht alle, dass diese Antwort vom Autor von GNU parallel zur Verfügung gestellt wird.
Izkeros
1
Downvoted aufgrund klarer Werbung auf einer Software, die nicht wie bei den ersten Versuchen beschrieben ordnungsgemäß ausgeführt wird, aufgrund einer interaktiven Eingabeaufforderung, die die meisten Skripte durcheinander bringt.
Daniel Sorichetti