Una migliore ricerca unix con elaborazione parallela?


43

L' find(1)utilità unix è molto utile e mi consente di eseguire un'azione su molti file che soddisfano determinate specifiche, ad es

find /dump -type f -name '*.xml' -exec java -jar ProcessFile.jar {} \;

Quanto sopra potrebbe eseguire uno script o uno strumento su ogni file XML in una determinata directory.

Diciamo che il mio script / programma impiega molto tempo CPU e ho 8 processori. Sarebbe bello elaborare fino a 8 file alla volta.

GNU make consente l'elaborazione di lavori paralleli con il -jflag ma findnon sembra avere tale funzionalità. Esiste un metodo di pianificazione dei lavori generico alternativo per affrontare questo problema?

Risposte:


65

xargscon l' -Popzione (numero di processi). Supponiamo che volessi comprimere tutti i file di registro in una directory su una macchina da 4 cpu:

find . -name '*.log' -mtime +3 -print0 | xargs -0 -P 4 bzip2

Puoi anche indicare -n <number>il numero massimo di unità di lavoro per processo. Quindi dire che avevo 2500 file e ho detto:

find . -name '*.log' -mtime +3 -print0 | xargs -0 -n 500 -P 4 bzip2

Ciò darebbe inizio a 4 bzip2processi, ognuno dei quali con 500 file, e quindi al termine del primo sarebbe iniziato un altro per gli ultimi 500 file.

Non so perché la risposta precedente usi xargs e make , ci sono due motori paralleli lì!


7
Con find / xargs, fai attenzione: trova i valori predefiniti per le nuove righe come delimitatori di output, ma xargs imposta automaticamente tutti gli spazi bianchi come delimitatori di input. Usa -0 su entrambi per sicurezza, o passa al parallelo GNU che per impostazione predefinita passa a newline come delimitatori di input (corrispondente all'output di find).
effimero

1
Wow fantastico! Ho appena controllato, ed è vero, xargs ha -Pun'opzione!
PP.

Fai attenzione a usare il xargs -P- ha un bug mai corretto di confondere l'output (a differenza parallel) ogni volta che 2 thread producono output nello stesso preciso momento ...
Vlad

34

Anche il parallelo GNU può aiutare.

find /dump -type f -name '*.xml' | parallel -j8 java -jar ProcessFile.jar {}

Si noti che senza l' -j8argomento, il parallelvalore predefinito è il numero di core sulla macchina :-)


6

Non è necessario "aggiustare" find: utilizzare makese stesso per gestire il parallelismo.

Chiedi al tuo processo di creare un file di registro o un altro file di output e quindi utilizzare un Makefile in questo modo:

.SUFFIXES:  .xml .out

.xml.out:
        java -jar ProcessFile.jar $< 1> $@

e invocato così:

find /dump -type f -name '*.xml' | sed -e 's/\.xml$/.out/' | xargs make -j8

Meglio ancora, se si assicura che il file di output venga creato solo al completamento con esito positivo del processo Java, è possibile sfruttare makela gestione delle dipendenze per garantire che la prossima volta vengano eseguiti solo i file non elaborati.


1
Spero non ci siano spazi o altri personaggi "interessanti" in quei nomi di file; Make non li gestisce in modo molto elegante.
effimero

Ottima idea! Non ho mai pensato di usare makefile in questo modo.
oscfri,

3

Trova ha un'opzione parallela che puoi usare direttamente usando il simbolo "+"; non sono richiesti xargs. Combinandolo con grep, può strappare rapidamente il tuo albero in cerca di partite. per esempio, se sto cercando tutti i file nella mia directory dei sorgenti che contengono la stringa 'pippo', posso invocare
find sources -type f -exec grep -H foo {} +


12
Leggendo il manuale di ricerca, puoi vedere che la -exec command +sintassi non la esegue in parallelo, ma "raggruppa" molti file insieme ed esegui il comando con più file come argomenti contemporaneamente. Succede che grep può guardare attraverso i suoi obiettivi in ​​parallelo.
Gyscos
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.