Я использую Celery, чтобы ставить в очередь задания из приложения CGI, которое я сделал .В соответствии с тем, как я это настроил, Celery запускает каждое задание по одному или два за раз, устанавливая CELERYD_CONCURRENCY = 1
или = 2
(чтобы они не вытесняли процессор или не зависали от потребления памяти).Очередь работает отлично, благодаря совету, который я получил по StackOverflow.
Каждое из этих заданий занимает достаточно много времени (~ 30 минут), но имеет смущающую параллелизуемость.По этой причине я использовал Pool.map
, чтобы разделить его и выполнить работу параллельно.Он отлично работал из командной строки, и я получил время выполнения около 5 минут с использованием нового многоядерного чипа.
К сожалению, есть некоторые ограничения, которые не позволяют демоническому процессу иметь подпроцессы, и когда я запускаюпричудливый распараллеленный код в очереди CGI, я получаю эту ошибку:
AssertionError: демоническим процессам не разрешено иметь детей
Я заметил другие люди у были похожие вопросы , но я не могу найти ответ, который не требовал бы полного отказа от Pool.map
и создания более сложного кода потока.
Каков подходящий выбор дизайнаВот?Я могу легко выполнять свои последовательные задания, используя мою очередь Celery.Я также могу выполнять свои намного более быстрые распараллеленные задания без очереди.Как мне подойти к этому, и возможно ли получить то, что я хочу ( и очередь и распараллеливание для каждой работы)?
У меня есть пара идей (некоторыедовольно забавно):
- Задание, отправленное в очередь Celery, просто вызывает программу командной строки.Эта программа может использовать пул по своему усмотрению, а затем сохраняет полученные результаты и данные в файл (как и сейчас).
Недостаток: Я не смогу проверить состояние задания или посмотреть, успешно ли оно завершилось.Кроме того, системные вызовы из CGI могут вызвать проблемы с безопасностью. - Очевидно, что если очередь заполнена заданиями, я могу использовать ресурсы ЦП (установив CELERYD_CONCURRENCY = 6 или около того);это позволит многим людям быть «впереди очереди» одновременно.
Недостатки: Каждая работа будет проводить много времени в начале очереди;если очередь не заполнена, ускорения не будет.Кроме того, многие частично выполненные задания будут храниться в памяти одновременно, используя гораздо больше оперативной памяти. - Используйте @task в Celery для распараллеливания внутри подзадач.Затем вместо установки CELERYD_CONCURRENCY = 1 я бы установил его на 6 (или сколь угодно много подзадач я бы хотел оставить в памяти одновременно).
Недостаток: Прежде всего, я не уверен, удастся ли это успешно избежать проблемы "задача в задаче".Кроме того, понятие позиции в очереди может быть потеряно, и многие частично завершенные задания могут сразу оказаться в памяти. - Возможно, есть способ вызвать Pool.map и указать, что потоки не являются демонами?Или, может быть, есть что-то более легкое, что я могу использовать вместо Pool.map?Это похоже на подход, принятый для другого открытого вопроса StackOverflow .Кроме того, я должен отметить, что распараллеливание, которое я использую через Pool.map, похоже на линейную алгебру, и межпроцессное взаимодействие отсутствует (каждый просто работает независимо и возвращает свой результат, не разговаривая с другими).
- Выбросьте сельдерей и используйте многопроцессорную обработку. Очередь.Тогда, возможно, был бы какой-то способ использовать одну и ту же «глубину потока» для каждого используемого мной потока ( т.е. , может быть, все потоки могли бы использовать один и тот же пул, избегая вложения)?
Заранее большое спасибо.