Esecuzione di programmi in parallelo utilizzando xargs


86

Al momento ho lo script corrente.

#!/bin/bash
# script.sh

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

Vorrei eseguirlo in parallelo usando xargs. Ho provato

script.sh | xargs -P8

Ma facendo quanto sopra eseguito solo una volta alla volta. Nessuna fortuna anche con -n8. L'aggiunta di & alla fine della riga da eseguire nello script for loop proverebbe a eseguire lo script 99 volte contemporaneamente. Come eseguo il ciclo solo 8 alla volta, fino a un totale di 100.


Questo è quello che inizialmente volevo fare, ma ho dovuto ricorrere a xargs perché sono su Windows. Non sono riuscito a far funzionare GNU Parallel su Windows
Olivier

Quella sceneggiatura si sta chiamando o hai solo confuso i nomi quando hai chiesto qui?
Etan Reisner

Spiacenti, dovrebbe chiamare un altro script. Lo aggiusterò
Olivier

La risposta a stackoverflow.com/questions/3321738/… è rilevante qui.
Etan Reisner

Risposte:


129

Dalla xargspagina man:

Questa pagina di manuale documenta la versione GNU di xargs. xargs legge gli elementi dallo standard input, delimitati da spazi (che possono essere protetti da virgolette doppie o singole o da una barra rovesciata) o da una nuova riga, ed esegue il comando (l'impostazione predefinita è / bin / echo) una o più volte con qualsiasi argomento iniziale seguito per elementi letti dallo standard input. Le righe vuote sullo standard input vengono ignorate.

Ciò significa che per il tuo esempio xargssta aspettando e raccogliendo tutto l'output dallo script e quindi in esecuzione echo <that output>. Non esattamente così utile né quello che volevi.

L' -nargomento è quanti elementi dall'input da utilizzare con ogni comando che viene eseguito (niente, di per sé, sul parallelismo qui).

Per fare quello che vuoi con xargste dovresti fare qualcosa di più simile a questo (non testato):

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

Che si rompe in questo modo.

  • printf %s\\n {0..99}- Stampa un numero per riga da 0a 99.
  • Correre xargs
    • prendendo al massimo un argomento per riga di comando eseguita
    • ed eseguire fino a otto processi alla volta

8
In realtà non è necessario mettere gli argomenti su righe separate; xargs suddivisione in parole. Quindi echo {0..99} |funzionerebbe altrettanto bene. <<<{0..99}non sembra funzionare; sebbene <<<wordsia documentata come parola che si espande con le parentesi graffe, non lo fa con nessuna versione di bash che ho a portata di mano.
rici

1
@rici Sembra un bug della documentazione, soprattutto perché la documentazione di Here Documents non menziona l'espansione delle parentesi graffe (e non accade nemmeno lì in un rapido test) sebbene non menzionino nemmeno l'espansione della tilde (cosa che non accade per <<ma lo fa per <<<così *shrug*). Le espansioni che fanno e non avvengono in here docs e here stringings sono un po 'strane per la mia mente.
Etan Reisner

1
Come puoi separare i risultati da diverse corse, ad esempio con i newline?
nirvana-msu

4
Demo: time head -12 <(yes "1") | xargs -n1 -P4 sleepeseguirà 12 sleep 1comandi, 4 in parallelo. Il comando richiederà 3 secondi.
Walter A

66

Con GNU Parallel faresti:

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

Aggiungere -P8se non si desidera eseguire un lavoro per core della CPU.

Al contrario xargs, farà La cosa giusta, anche se l'input contiene spazio, 'o "(non è il caso qui, però). Inoltre si assicura che l'output di lavori diversi non venga mischiato insieme, quindi se usi l'output sei garantito che non otterrai mezza riga da due lavori diversi.

GNU Parallel è un parallelizzatore generale e rende facile eseguire lavori in parallelo sulla stessa macchina o su più macchine a cui si ha accesso ssh.

Se hai 32 lavori diversi che desideri eseguire su 4 CPU, un modo semplice per parallelizzare è eseguire 8 lavori su ogni CPU:

Pianificazione semplice

GNU Parallel invece genera un nuovo processo quando uno finisce, mantenendo le CPU attive e risparmiando così tempo:

Pianificazione parallela GNU

Installazione

Se GNU Parallel non è pacchettizzato per la tua distribuzione, puoi eseguire un'installazione personale, che non richiede l'accesso come root. Può essere fatto in 10 secondi in questo modo:

$ (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

Per altre opzioni di installazione vedere http://git.savannah.gnu.org/cgit/parallel.git/tree/README

Per saperne di più

Vedi altri esempi: http://www.gnu.org/software/parallel/man.html

Guarda i video introduttivi: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

Segui il tutorial: http://www.gnu.org/software/parallel/parallel_tutorial.html

Iscriviti alla mailing list per ottenere supporto: https://lists.gnu.org/mailman/listinfo/parallel


19
Questo non risponde alla domanda, né indica perché xargs non può ottenere la stessa cosa.
张 实 唯

8
downvote perché xarg per me fa esattamente come mostra la seconda immagine.
noonex

3
@noonex Sei consapevole del fatto che non tutti usano la versione di xargs che usi tu e che -P non è presente in tutte le versioni di xargs?
Ole Tange

20
Forse non tutti sanno che questa risposta è fornita dall'autore di GNU parallel.
izkeros

1
Downvoted a causa di una chiara pubblicità su un software che non funziona correttamente come descritto nei primi tentativi, a causa di un prompt interattivo che rovina la maggior parte degli script.
Daniel Sorichetti
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.