Bash: как просто распараллелить задачи? - PullRequest
12 голосов
/ 09 июня 2010

Я пишу крошечный скрипт, который вызывает утилиту PNGOUT для нескольких сотен файлов PNG. Я просто сделал это:

find $BASEDIR -iname "*png" -exec pngout {} \;

А потом я посмотрел на монитор процессора и заметил, что использовалось только одно ядро, что довольно печально.

В этот день и в эпоху настольных компьютеров с двумя, четырьмя, окто и гекса (?) Ядрами, как мне просто распараллелить эту задачу с Bash? (это не первый раз, когда я испытываю такую ​​потребность, потому что довольно много этих утилит являются однопоточными ... У меня уже был случай с кодировщиками mp3).

Будет ли просто запускать все pngout в фоновом режиме? Как тогда будет выглядеть моя команда find ? (Я не очень уверен, как смешать find и символ '&')

Если бы у меня было три сотни картинок, это означало бы переключение между тремя сотнями процессов, что в любом случае не кажется великолепным!?

Или я должен скопировать мои три сотни файлов или около того в "nb dirs" , где "nb dirs" будет количеством ядер, а затем работать одновременно " nb находит "? (что было бы достаточно близко)

Но как мне это сделать?

Ответы [ 3 ]

22 голосов
/ 09 июня 2010

Отвечая на мой собственный вопрос ... Оказывается, есть относительно неизвестная особенность команды xargs , которую можно использовать для достижения этой цели:

find . -iname "*png" -print0 | xargs -0 --max-procs=4 -n 1 pngout

Бинго, мгновенное 4-кратное ускорение на четырехъядерном компьютере:)

4 голосов
/ 09 июня 2010

для вызова всех заданий в фоновом режиме:

find $BASEDIR -iname "*png" | while read f; do
  pngout "$f" &
done

но, конечно, это не лучший вариант. выполнять 'n' задач одновременно:

i=0
find $BASEDIR -iname "*png" | while read f; do
  pngout "$f" &
  i=$((i+1))
  if [[ $i -gt $NTASKS ]]; then
    wait
    i=0
  fi
done

это не оптимально, так как ожидает завершения всех одновременных задач для запуска другой группы; но это должно быть лучше, чем ничего.

2 голосов
/ 09 июня 2010

Распараллеливание редко бывает тривиальным. В вашем случае, если вы можете выбрать файлы уникально в наборах одинакового размера, то вы можете запустить несколько копий своего скрипта поиска. Вы не хотите запускать 300 фотографий в фоновом режиме. Для таких работ обычно быстрее запускать их последовательно. Фоновое задание команды или использование пакета являются жизнеспособными вариантами.

Предполагая, что файлы последовательно нумеруются, вы можете использовать шаблон поиска, например " [0-4] .png" для одного поиска и " [5-9] .png" для другого. Это позволило бы двум ядрам работать примерно одинаковое количество времени.

Задача ведения сельского хозяйства будет включать установку диспетчера-бегуна. Сборка, тестирование и запуск этого заняли бы довольно много времени.

Запустите BOINC, чтобы использовать эти запасные процессоры. Скорее всего, вы захотите игнорировать помеченные процессы при мониторинге частоты процессора. Добавьте такой код в rc.local.

for CPU in /sys/devices/system/cpu/cpu[0-9]*; do
    echo 1 > ${CPU}/cpufreq/ondemand/ignore_nice_load
done
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...