Алексей Махоткин

домашняя страница

Использование GNU Make для многотредовой обработки файлов

Стандартная задача — есть поток входящих файлов, на их основе надо создавать результирующие файлы. Входящих файлов десятки и сотни, постоянно появляются новые. Процессоров на машине много. Хочется сделать просто, надежно, с использованием всех процессоров и с минимальными усилиями. Неоднократно оказывалось, что хорошим инструментом для решения этой задачи может стать старый добрый GNU Make.

Например, у нас есть поток видео-файлов в формате .ts. Из каждого такого файла надо создать а) файл для iPad б) файл для Flash в) промежуточный WAV-файл г) файл с аудио-отпечатком и д) залить аудио-отпечаток на удаленный сервер.

Можно создать Makefile, который будет выглядеть примерно так:

.PHONY: all
all: file1.afp-uploaded file1.mp4 file1.flv

file1.mp4: file1.ts
    convert-to-mp4.sh $< $@

file1.flv: file1.ts
    convert-to-mp4.sh $< $@

file1.wav: file1.ts
    convert-to-wav.sh $< $@

file1.afp: file1.wav
    generate-audio-fingerprint.sh $< $@

file1.afp-uploaded: file1.afp
    scp $< 192.168.1.1:
    touch $@

Теперь скажем make -j 3 all. На основании информации о зависимости файлов и инструкции по их созданию Make начнет запускать указанные скрипты. Ключ -j 3 означает, что в каждый момент времени будет запущено вплоть до трех одновременных задач (если есть возможность для распараллеливания). Естественно, цифру нужно подобрать в соответствии с возможностями вашего железа.

Так, в нашем примере будут параллельно генерироваться file1.mp4, file1.flv и file1.wav. Сразу после генерации file1.wav (на фоне прочих выполняющихся задач) начнет генерироваться file1.afp. Если требуется выполнить задачу, не связанную с созданием файла — например, залить файл на удаленный сервер, то используется стандартный трюк с пустым файлом (в данном случае file1.afp-uploaded). Переменная $< означает “входной файл”, переменная $@ — выходной файл.

Это был пример. Так как файлов много, то давайте напишем скрипт, который берет список новых пришедших файлов, генерирует Makefile, а затем запускает make, который волшебным образом обработает всю простыню. Затем обработанные файлы можно удалить, снова сгенерировать Makefile и повторять до бесконечности.

Язык GNU Make подробно описан в документации и местами довольно непрост из-за того, что в нем перемешаны команды shell и конструкции самого Makefile. Иногда в сложных случаях можно запутаться в знаках доллара и т. п. Однако, если просто генерировать Makefile внешними средствами, без использования макро-команд Make, то обычно никаких проблем не возникает.

Comments