Я хочу обработать много файлов, и так как у меня здесь куча ядер, я хочу сделать это параллельно:
for i in *.myfiles; do do_something $i `derived_params $i` other_params; done
Я знаю решение Makefile, но мои команды нуждаются в аргументах из списка глобализации оболочки. То, что я нашел, это:
> function pwait() {
> while [ $(jobs -p | wc -l) -ge $1 ]; do
> sleep 1
> done
> }
>
Чтобы использовать его, все, что нужно сделать, это поставить и после заданий и вызова pwait, параметр дает количество параллельных процессов:
> for i in *; do
> do_something $i &
> pwait 10
> done
Но это работает не очень хорошо, например, я попробовал это, например, с помощью цикла for, конвертирующего много файлов, но из-за которого я получил ошибку и оставил задания отмененными.
Я не могу поверить, что это еще не сделано, так как обсуждение списка рассылки zsh уже давно. Так ты знаешь лучше?
bash
shell
zsh
parallel-processing
математический
источник
источник
echo "DONE"
после цикла, который выполнялся до того, как активные задания не были завершены. => Это заставило меня думать, что работа не выполнена.Ответы:
Makefile - хорошее решение вашей проблемы. Вы можете запрограммировать это параллельное выполнение в оболочке, но, как вы заметили, это сложно. Параллельная реализация make не только позаботится о запуске заданий и обнаружении их завершения, но также будет управлять балансировкой нагрузки, что сложно.
Требование к глобализации не является препятствием: существуют реализации make, которые его поддерживают. GNU make, который имеет расширение подстановочных знаков, например,
$(wildcard *.c)
и доступ к оболочке, такой как$(shell mycommand)
(посмотрите функции в руководстве по GNU make для получения дополнительной информации). Это по умолчаниюmake
в Linux и доступно в большинстве других систем. Вот скелет Makefile, который вы можете адаптировать к вашим потребностям:Запустите что-то вроде
make -j4
параллельного выполнения четырех заданий илиmake -j -l3
сохранения средней нагрузки около 3.источник
Я не уверен, на что похожи ваши аргументы. Но с помощью GNU Parallel http: // www.gnu.org/software/parallel/ вы можете сделать это, чтобы запустить одно задание на ядро процессора:
Если то, что вы хотите получить, это просто изменить .extension, то {.} Может пригодиться:
Посмотрите вступительное видео для GNU Parallel на http://www.youtube.com/watch?v=OpaiGYxkSuQ
источник
Не подойдет ли вам команда оболочки
wait
?Ваш цикл выполняет задание, затем ждет его, затем выполняет следующее задание. Если вышеперечисленное не работает для вас, то ваш может работать лучше, если вы перейдете
pwait
послеdone
.источник
for
циклы, чтобы ограничить это:for file in *; do for i in {1..10}; do do_something "$i" & done; wait; done
(не проверено) Это должно делать десять раз и ждать, пока все десять каждой группы не будут выполнены, прежде чем начинать следующие десять. Ваш цикл делает по одному, делая&
спор. Смотрите вопрос, с которым связан JRobert, для других вариантов. Поищите в Stack Overflow другие вопросы, похожие на ваши (и на этот).for i in *
. Ему придется передавать аргументы в цикл с помощью канала или чего-то еще. Тогда вместо внутреннего цикла вы можете запустить инкрементный счетчик и запускать"micro-"wait"-s"
каждый "$ ((i% 32))" -eq '0'wait
с внутренним счетчиком работало для меня хорошо. Благодарность!Почему еще никто не упомянул xargs?
Предполагая, что у вас есть ровно три аргумента,
В противном случае используйте разделитель (для этого удобно использовать null):
РЕДАКТИРОВАТЬ: для вышеупомянутого, каждый параметр должен быть разделен нулевым символом, а затем число параметров должно быть указано с помощью xargs -n.
источник
Я попробовал некоторые из ответов. Они делают сценарий немного сложнее, чем нужно. В идеале использование
parallel
илиxargs
было бы предпочтительным, однако, если операции внутри цикла for сложны, может быть проблематично создать файлы большой и длинной строк для параллельной передачи. вместо этого мы могли бы использовать источник следующим образомТаким образом, для вашей проблемы решение будет выглядеть
определить сделать что-то как
do_something.sh
}
выполнить с
xarg
илиgnu parallel
Я предполагаю функциональную независимость итераций для for.
источник