it-swarm.com.ru

Запуск сценария Shell параллельно

У меня есть сценарий Shell, который 

  1. перетасовывает большой текстовый файл (6 миллионов строк и 6 столбцов) 
  2. сортирует файл по первому столбцу
  3. выводит 1000 файлов 

Таким образом, псевдокод выглядит так 

file1.sh 

#!/bin/bash
for i in $(seq 1 1000)
do

  Generating random numbers here , sorting  and outputting to file$i.txt  

done

Есть ли способ запустить этот сценарий оболочки в parallel, чтобы в полной мере использовать многоядерные процессоры?

На данный момент ./file1.sh выполняется в последовательности от 1 до 1000, и это очень медленно.

Спасибо за вашу помощь.

41
Tony

Проверьте bash subshells , они могут использоваться для параллельного запуска частей скрипта.

Я не проверял это, но это может быть началом:

#!/bin/bash
for i in $(seq 1 1000)
do
   ( Generating random numbers here , sorting  and outputting to file$i.txt ) &
   if (( $i % 10 == 0 )); then wait; fi # Limit to 10 concurrent subshells.
done
wait
42
Anders Lindahl

Другой очень удобный способ сделать это с помощью gnu parallel , который стоит установить, если у вас его еще нет; это неоценимо, если задачи не обязательно занимают одинаковое количество времени. 

seq 1000 | parallel -j 8 --workdir $PWD ./myrun {}

запустит ./myrun 1, ./myrun 2 и т. д., убедившись, что одновременно выполняется 8 заданий. Он также может принимать списки узлов, если вы хотите работать на нескольких узлах одновременно, например, в задании PBS; наши инструкции для наших пользователей о том, как это сделать в нашей системе, находятся здесь

Обновлено для добавления: Вы хотите убедиться, что вы используете gnu-parallel, а не более ограниченную утилиту с тем же именем, которая входит в пакет moreutils (расходящаяся история этих двух описана здесь .)

84
Jonathan Dursi

Чтобы заставить вещи работать параллельно, вы используете '&' в конце команды Shell для запуска в фоновом режиме, а затем wait по умолчанию (т.е. без аргументов) будет ждать завершения всех фоновых процессов. Так что, возможно, начните 10 параллельно, затем подождите, затем сделайте еще десять. Вы можете сделать это легко с помощью двух вложенных циклов.

13
Tony Delroy

Существует полный список программ , которые могут запускать задания параллельно из командной консоли, что даже включает сравнения между ними, в документации по GNU параллельный. Есть много, много решений там. Еще одна хорошая новость заключается в том, что они, вероятно, весьма эффективны в планировании заданий, поэтому все ядра/процессоры всегда заняты.

9
Eric O Lebigot

Существует простая, переносимая программа, которая сделает это за вас: PPSS . PPSS автоматически планирует для вас задания, проверяя, сколько ядер доступно, и запускает другое задание каждый раз, когда другое только что закончилось.

4
Eric O Lebigot
IDLE_CPU=1
NCPU=$(nproc)

int_childs() {
    trap - INT
    while IFS=$'\n' read -r pid; do
        kill -s SIGINT -$pid
    done < <(jobs -p -r)
    kill -s SIGINT -$$
}

# cmds is array that hold commands
# the complex thing is display which will handle all cmd output
# and serialized it correctly

trap int_childs INT
{
    exec 2>&1
    set -m

    if [ $NCPU -gt $IDLE_CPU ]; then
        for cmd in "${cmds[@]}"; do
            $cmd &
            while [ $(jobs -pr |wc -l) -ge $((NCPU - IDLE_CPU)) ]; do
                wait -n
            done
        done
        wait

    else
        for cmd in "${cmds[@]}"; do
            $cmd
        done
    fi
} | display
0
Zakaria