In Linux we trust!

GNU parallel

Рассмотрим утилиту для распараллеливания задач parallel. Нижеследующая выжимка взята из этого руководства. Обращайтесь к нему для полной информации.

Установка:

# wget 'http://ftp.gnu.org/gnu/parallel/parallel-latest.tar.bz2'
# tar -xvf parallel-latest.tar.bz2
# cd parallel-*
# ./configure && make && make install
# alias parallel="parallel --no-notice"
# parallel --version | head -1
GNU parallel 20181122

Alias по возможности лучше прописать в .bashrc, он скрывает шапку с просьбой о денюжке =)

Входные данные:

Один из ключевых аспектов это работа с входными данными и их распределение между заданиями.

# parallel echo ::: A B C
A
B
C
# parallel echo ::: A B C ::: X Z
A X
A Z
B X
B Z
C X
C Z
# parallel --link echo ::: A B C ::: X Z
A X
B Z
C X

Опция --link сопоставляет аргументы из разных потоков ввода. По умолчанию утилита берет по одному аргументу из каждого потока. Это поведение можно изменить опцией -N:

# parallel -N 2 echo ::: A B C ::: X Z
A X A Z
B X B Z
C X C Z
# parallel -N 2 --link echo ::: A B C ::: X Z
A X B Z
C X

В роли входных данных могут быть файлы:

# seq 2 >seq.2
# seq 3 >seq.3
# parallel echo :::: seq.3 seq.2
1 1
1 2
2 1
2 2
3 1
3 2

Стандартный поток ввода (stdin), если он есть, обозначается -.

Placeholders:

В примерах выше мы не использовали placeholder'ы, и утилита parallel автоматически добавляла в конец выполняемой команды {}.

PlaceholderОписание
{}Список аргументов
{1}Первый аргумент
{-1}Последний аргумент
{%}Номер потока
{#}Номер задания
{.}Файл без расширения
{/}Имя файла без пути
{//}Каталог файла
{/.}Имя файла без расширения

Примеры (опция -j, к слову, задает кол-во потоков):

# parallel -j2 -N2 echo job='{#}' thread='{%}' ... {1} {-1} ::: `seq 10`
job=1 thread=1 ... 1 2
job=2 thread=2 ... 3 4
job=3 thread=1 ... 5 6
job=4 thread=2 ... 7 8
job=5 thread=1 ... 9 10
# parallel echo {} {.} {/} {//} {/.} ::: /etc/apt/sources.list
/etc/apt/sources.list /etc/apt/sources sources.list /etc/apt sources

Управление выводом:

По умолчанию parallel ждет завершения задания, потом уже направляет вывод задания в stdout. В случае если не задана опция --keep-order/-k, то порядок вывода может быть нарушен.

# parallel sleep {}';' echo {} ::: 3 2 1
1
2
3
# parallel -k sleep {}';' echo {} ::: 3 2 1
3
2
1

Если вывод нужен ДО завершения задания, то --linebuffer поможет вам в этом:

# parallel echo {}';' sleep {}';' echo {} ::: 3 2 1
1
1
2
2
3
3
# parallel --line-buffer echo {}';' sleep {}';' echo {} ::: 3 2 1
3
2
1
1
2
3