Выполнить несколько заданий параллельно и эффективно

ОС: Cent-OS

у меня есть немного 30,000 задания (или сценарии) для запуска. Каждая работа занимает 3-5 минут. я имею 48 CPUs(nproc = 48), я могу использовать 40 CPUs to run 40 Jobs параллельно. Пожалуйста, предложите, чтобы некоторые сценарии или инструменты могли обрабатывать 30 000 заданий, выполняя каждые 40 заданий параллельно.

Что я сделал:

  • Я создал 40 различных папок и выполнил задания параллельно, создав сценарий оболочки для каждого каталога.

  • Я хочу узнать лучшие способы справиться с этим видом работ в следующий раз.

3 ответа

Решение

Как говорит Марк Сетчелл: GNU Parallel.

find scripts/ -type f | parallel

Если вы настаиваете на том, чтобы освободить 8 процессоров:

find scripts/ -type f | parallel -j-8

Но, как правило, проще использовать nice так как это даст вам все 48 ядер, когда они больше никому не нужны:

find scripts/ -type f | nice -n 15 parallel

Узнать больше:

  • Посмотрите вступительное видео для быстрого ознакомления: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
  • Пройдите учебник (man parallel_tutorial). Ты командная строка с любовью тебя за это.

Я использовал REDIS чтобы делать такие вещи - его очень просто установить, а интерфейс командной строки прост в использовании.

Я в основном использовал LPUSH поместить все задания в "очередь" в REDIS и BLPOP сделать блокировку удаления задания из очереди. Так что вы бы LPUSH 30 000 заданий (или имен сценариев или параметров) в начале, затем запустите 40 процессов в фоновом режиме (по 1 на процессор), и каждый процесс будет выполнять цикл BLPOP чтобы получить работу, запустить ее и сделать следующее.

Вы можете добавить уровни сложности, чтобы регистрировать выполненные задания в другой "очереди".

Вот небольшая демонстрация того, что делать:

Поместите 3 задания в очередь, которая называется заданием:

./redis-server &    # start REDIS server in background

./redis-cli         # start REDIS command line interface
redis 127.0.0.1:6379> lpush jobs "job1"
(integer) 1
redis 127.0.0.1:6379> lpush jobs "job2"
(integer) 2
redis 127.0.0.1:6379> lpush jobs "job3"
(integer) 3

Посмотрите, сколько вакансий в очереди:

redis 127.0.0.1:6379> llen jobs
(integer) 3

Ждать с бесконечным тайм-аутом для работы

redis 127.0.0.1:6379> brpop jobs 0
1) "jobs"
2) "job1"
redis 127.0.0.1:6379> brpop jobs 0
1) "jobs"
2) "job2"
redis 127.0.0.1:6379> brpop jobs 0
1) "jobs"
2) "job3"

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

redis 127.0.0.1:6379> brpop jobs 0

Конечно, это легко сценарий:

Поставить 30 000 заданий в очередь:

for i=0;i<30000;i++
do
    echo "lpush jobs job$i" | redis-cli
done

Вот как проверить прогресс:

echo "llen jobs" | redis-cli
(integer) 30000

И вы можете начать 40 рабочих мест, как это:

for i=0;i<40;i++
    ./Keep1ProcessorBusy  $i &
done

А потом Keep1ProcessorBusy будет что-то вроде этого:

while(1)
do
    job=$(echo brpop jobs 0 | redis_cli)
    # Set processor affinity here too if you want to force it, use $1 parameter we were called with
    do $job
done

Как совершенно другой вариант, вы можете посмотреть на GNU Parallel, который здесь. А также помните, что вы можете запустить вывод find через xargs с -P возможность распараллеливать вещи.

Просто запустите эти сценарии, Linux будет правильно распределять эти задачи между доступными процессорами. Это на планировщике задач Linux. Но, если вы хотите, вы также можете выполнить задачу на определенном процессоре, используя taskset (увидеть man taskset). Вы можете сделать это из скрипта, чтобы выполнить ваши задачи 30K. Помните об этом вручную, будьте уверены в том, что вы делаете.

Другие вопросы по тегам