Выполнить несколько заданий параллельно и эффективно
ОС: 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. Помните об этом вручную, будьте уверены в том, что вы делаете.