Параллельные циклы оболочки

Я хочу обработать много файлов и так как у меня есть здесь набор Core i, хотят сделать это параллельно:

for i in *.myfiles; do do_something $i `derived_params $i` other_params; done

Я знаю о решении для Make-файла, но для моих команд нужны аргументы из оболочки globbing список. То, что я нашел:

> function pwait() {
>     while [ $(jobs -p | wc -l) -ge $1 ]; do
>         sleep 1
>     done
> }
>

Для использования его все, что нужно сделать, помещаются и после того, как задания и вызов pwait, параметр дает количество параллельных процессов:

> for i in *; do
>     do_something $i &
>     pwait 10
> done

Но это не работает очень хорошо, например, Я попробовал его, например, для цикла, преобразовывающего много файлов, но дающего мне ошибка, и оставил задания отмененными.

Я не могу живо, что это еще не сделано, так как обсуждение zsh списка рассылки так старо к настоящему времени. Вы знаете лучше?

11
задан 20.03.2017, 12:17

3 ответа

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

Требование для globbing не является препятствием: существуют, делают реализации, которые поддерживают его. GNU делает, который имеет подстановочное расширение такой как $(wildcard *.c) и доступ оболочки такой как $(shell mycommand) (ищите, функции в GNU делают руководство для получения дополнительной информации). Это - значение по умолчанию make на Linux, и доступный в большинстве других систем. Вот скелет Make-файла, который Вы можете адаптировать к своим потребностям:

sources = $(wildcard *.src)

all: $(sources:.src=.tgt)

%.tgt: $.src
    do_something $< $$(derived_params $<) >$@

Выполните что-то как make -j4 выполнить четыре задания параллельно, или make -j -l3 сохранять среднее число загрузки приблизительно 3.

15
ответ дан 07.12.2019, 12:11

Не был бы с помощью оболочки wait управлять работой для Вас?

for i in *
do
    do_something $i &
done
wait

Ваш цикл выполняется, задание затем ожидает его, затем делает следующее задание. Если вышеупомянутое не работает на Вас, то Ваш мог бы работать лучше, если Вы перемещаетесь pwait после done.

6
ответ дан 07.12.2019, 12:11

Я не уверен, на что похожи Ваши полученные аргументы. Но с Параллелью GNU http:// www.gnu.org/software/parallel/ можно сделать это для выполнения одного задания на ядро CPU:

find . | parallel -j+0 'a={}; name=${a##*/}; upper=$(echo "$name" | tr "[:lower:]" "[:upper:]");
   echo "$name - $upper"'

Если то, что Вы хотите получить, просто изменяет .extension {.} можение удобно:

parallel -j+0 lame {} -o {.}.mp3 ::: *.wav

Посмотрите вводное видео к Параллели GNU по http://www.youtube.com/watch?v=OpaiGYxkSuQ

8
ответ дан 07.12.2019, 12:11

Теги

Похожие вопросы