Terminal pogryzł człowieka: parallel
Kto mógłby przypuszczać, że narzędzie do uruchamiania równoległych zadań w terminalu kryje się pod jakże zwodniczą nazwą parallel. Oczywiście opisanie tego narzędzia za pomocą dwóch słów „równoległe uruchamianie” w żaden sposób nie oddaje potencjału jaki drzemie w tym programie.
Na początku uściślijmy. W ogromnym uproszczeniu parallel tak naprawdę najbardziej przyda się nam w efektywnym optymalizowaniu pętli w skryptach. O ile zadaniem każdego przebiegu pętli jest uruchomienie tego samego polecenia tylko z innymi parametrami. Idąc najkrótszą drogą można stwierdzić, że wspomniane polecenie potrafi „zapuścić” w tle kilka instancji tego samego polecenia z różnymi parametrami:
parallel ls ::: *.c *.txt *.h
Trzykrotny dwukropek nie jest pomyłką. Co nam daje powyższe? Po aktywowaniu zostaną jednocześnie wykonane trzy polecenia ls każde z innym parametrem – tak jak po dwukropku. Oczywiście powyższy przykład jest bez sensu, bowiem ls *.c *.txt *.h zadziała i bez parallel. Ale nie o sens tu idzie, a o zaprezentowanie koncepcji. Niemal każdy miłośnik backupów dostrzeże bowiem nowe możliwości wykorzystania pełnej mocy rdzeni CPU tkwiących w serwerach:
parallel gzip ::: backup1-dump.sql backup2-dump.sql backup3-dump.sql
(co dla użytkowników pgzip też jest bez sensu)
Ale wspomniałem też na początku o pętlach w skryptach. O co chodzi? Generalnie chodzi o to, że za pomocą parallel bardzo szybko i zgrabnie zamienimy twory typu:
for i in 1 2 3; do jakas-komenda $i; done
… na:
parallel jakas_komenda ::: parametr-1 parametr-2 parametr-3 parametr-3
Bystrzy użytkownicy zauważą zapewne, że w sumie w pętli for możemy zakończyć naszą komendę znaczkiem & i… Zakończymy życie naszego systemu mając przy bardziej rozbudowanych zajęciach 200 procesów w tle. Parallel robi to inaczej. Uwzględnia liczbę rdzeni naszego CPU i wyzwala w jednostce czasu tyle samo wywołań naszego polecenia. Chyba, że zaordynujemy mu za pomocą -j aby uruchomił jednocześnie 5, 6 a nawet 20 instancji naszej komendy. Przeszkodą jest jedynie nasza fantazja, gdyż parallel dysponuje potężnym zestawem parametrów regulujących jego działanie.
Wspominałem o potrójnym dwukropku? Nie dokończyłem tej opowieści.
parallel service {1} {2} ::: apache2 proftpd nscd ::: stop start
Powyższe jest adekwatne wykonaniu:
service apache2 stop
service apache2 start
service proftpd stop
service proftpd start
service nscd stop
service nscd start
Prawda, że zgrabnie? Ale to nie wszystko. Jeżeli pominiemy komendę to program potraktuje wszystko po ::: jako polecenia do uruchomienia:
parallel ::: 'gzip test' 'echo "hehe"' 'uname -a'
Dociekliwym polecam sprawdzenie, do czego służy poczwórny dwukropek, potrójny dwukropek zakończony plusem i tak dalej.
A teraz chwila prawdy. Czy na dwurdzeniowym procesorze da się zauważyć przewagę parallel na zwykłą pętlą w Bashu albo zadaniami kolejkowanymi przez xargs? Wykorzystamy do tego celu nasz ulubiony program convert z pakietu ImageMagick. W katalogu w którym się znajdujemy znajduje się też 15 plików jpg. Za pomocą wspomnianego polecenia i z wykorzystaniem standardowego find oraz xargs przeskalujemy te pliki o 300% (wiem, po raz kolejny zadanie bez sensu, ale nie w sensie tkwi istota tego testu).
time find . -type f -name "*.jpg" |xargs -d "\n" -I file -n1 convert -resize 300% file file-new.jpg
real 0m32.140s user 0m46.384s sys 0m3.096s
Ok, 32 sekundy. A jak to wygląda z wykorzystaniem parallel? Dla pewności włączymy uruchamianie trzech instancji convert naraz (pomimo dwóch rdzeni procesora).
time find . -type f -name "*.jpg" | parallel -j 3 convert -resize 300% {} {.}-resized.jpg
real 0m21.976s user 0m39.728s sys 0m1.888s
To samo zadanie zostało wykonane w 21 sekund. Teraz oczyma wyobraźni przenieśmy powyższe na jakiekolwiek zapętlone działania w naszych skryptach.
Powyższe to zaledwie wstęp do tego, co może nam zaoferować tytułowy program. Co więcej, to również wstęp do świętej wojny, gdyż niejeden z Was ściska w ręku kamień, by w odpowiednim momencie zaakcentować nim swoją frustrację słowami “GNU Parallel ignorancie!”. I będziecie wszyscy mieli rację, gdyż rozwiązanie to powstało pod auspicjami Free Software Foundation. Niemniej, program występuje we wszystkich repozytoriach wszystkich dystrybucji i jedne co może zaniepokoić nasze zmysły to wyświetlana przezeń (program) winieta:
When using programs that use GNU Parallel to process data for publication please cite: O. Tange (2011): GNU Parallel - The Command-Line Power Tool, ;login: The USENIX Magazine, February 2011:42-47. This helps funding further development; and it won't cost you a cent. Or you can get GNU Parallel without this requirement by paying 10000 EUR. To silence this citation notice run 'parallel --bibtex' once or use '--no-notice'.
… co możemy wyłączyć w zacytowany sposób. A może zapłacić? Ciekawe zaiste.