Lepsze znalezisko unixa z równoległym przetwarzaniem?

43

Narzędzie unix find(1)jest bardzo przydatne, pozwalając mi wykonać akcję na wielu plikach, które pasują do określonych specyfikacji, np

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

Powyższe może uruchomić skrypt lub narzędzie na każdym pliku XML w określonym katalogu.

Powiedzmy, że mój skrypt / program zajmuje dużo czasu procesora i mam 8 procesorów. Byłoby miło przetwarzać do 8 plików jednocześnie.

GNU make pozwala na równoległe przetwarzanie zadań z -jflagą, ale findwydaje się, że nie ma takiej funkcjonalności. Czy istnieje alternatywna ogólna metoda planowania zadań, która się do tego zbliża?

PP.
źródło

Odpowiedzi:

65

xargsz -Popcją (liczba procesów). Powiedzmy, że chciałem skompresować wszystkie pliki dziennika w katalogu na komputerze z 4 procesorami:

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

Możesz także powiedzieć -n <number>o maksymalnej liczbie jednostek roboczych na proces. Powiedzmy, że miałem 2500 plików i powiedziałem:

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

Spowodowałoby to uruchomienie 4 bzip2procesów, z których każdy miałby 500 plików, a następnie, gdy pierwszy zakończył, uruchomiono kolejny dla ostatnich 500 plików.

Nie jestem pewien, dlaczego użyto poprzedniej odpowiedzi xargs i make masz tam dwa równoległe silniki!

Gajusz
źródło
7
Korzystając z find / xargs, zachowaj ostrożność: znajdź wartości domyślne dla nowych linii jako ograniczniki wyjściowe, ale xargs domyślnie dla dowolnej białej spacji jako ograniczniki wejściowe. Użyj -0 na obu, aby być bezpiecznym, lub przełącz się na GNU równolegle, który domyślnie jest znakami nowej linii jako ogranicznikami wejściowymi (pasujące do wyjścia find).
ephemient
1
Wow niesamowite! Właśnie sprawdziłem i to prawda, xargs ma -Popcję!
PP.
Uważaj na używanie xargs -P- ma nigdy nie naprawiony błąd zniekształcania wyjścia (w przeciwieństwie do parallel), ilekroć 2 wątki generują wyjście w tym samym momencie ...
Vlad
34

GNU równoległy też może pomóc.

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

Zauważ, że bez -j8argumentu paralleldomyślnie jest liczba rdzeni na twoim komputerze :-)

efemeryczny
źródło
6

Nie trzeba „naprawiać” find- wykorzystaj makesię do obsługi równoległości.

Poproś proces o utworzenie pliku dziennika lub innego pliku wyjściowego, a następnie użyj pliku Makefile:

.SUFFIXES:  .xml .out

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

i przywołał w ten sposób:

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

Co więcej, jeśli upewnisz się, że plik wyjściowy zostanie utworzony tylko po pomyślnym zakończeniu procesu Java, możesz skorzystać z makeobsługi zależności, aby następnym razem zrobić tylko nieprzetworzone pliki.

Alnitak
źródło
1
Mam nadzieję, że w nazwach plików nie ma spacji ani innych „interesujących” znaków; Make nie radzi sobie z nimi bardzo elegancko.
ephemient
Świetny pomysł! Nigdy nie myślałem o użyciu takich plików makefile.
oscfri
3

Znajdź ma opcję równoległą, której można użyć bezpośrednio za pomocą symbolu „+”; nie wymaga Xargs. Łącząc go z grep, może szybko rozerwać twoje drzewo, szukając zapałek. na przykład, jeśli szukam wszystkich plików w moim katalogu źródeł zawierających ciąg „foo”, mogę wywołać
find sources -type f -exec grep -H foo {} +

Mark Evans
źródło
12
Po przeczytaniu instrukcji wyszukiwania można zobaczyć, że -exec command +składnia nie uruchamia go równolegle, ale „grupuje” wiele plików razem i uruchamia polecenie z wieloma plikami jako argumentami jednocześnie. Zdarza się, że grep może równolegle przeglądać swoje cele.
Gyscos