#python #message-queue #multiprocessing
#python #очередь сообщений #многопроцессорная обработка
Вопрос:
У меня есть приложение python (2.6.5 64-разрядная версия, Windows 2008 Server R2), которое запускает рабочие процессы. Родительский процесс помещает задания в очередь заданий, из которой рабочие их забирают. Аналогично у него есть очередь результатов. Каждый рабочий выполняет свою работу, запрашивая сервер. Загрузка процессора рабочими низкая.
Когда число рабочих растет, загрузка ЦП на серверах фактически сокращается. Сами серверы не являются узким местом, поскольку я могу загружать их дальше из других приложений.
Кто-нибудь еще видел подобное поведение? Существует ли проблема с многопроцессорными очередями python, когда большое количество процессов читает или записывает в одни и те же очереди?
Комментарии:
1. Пожалуйста, не могли бы вы уточнить, вы говорите, что «я увеличил количество рабочих, но объем выполняемой работы упал»?
2. Можете ли вы поделиться некоторым кодом? Причин может быть много, в зависимости от реализации.
3. @MattH: меньше работы, что означает (А) снижение загрузки ЦП на сервере и (Б) снижение скорости записи результатов. (Запись результатов не является узким местом, это было проверено, как и избыточная вычислительная мощность сервера.).
4. @Underhill: Ваш вопрос смущает меня, говоря о сервере и серверах взаимозаменяемо, упомянув, что работа рабочих заключается в запросе серверов. Все ли рабочие и родительские находятся в одной системе? Это та система, загрузка процессора которой снижается с увеличением количества рабочих?
5. @MattH: родительский и рабочие находятся в одной системе. Загрузка ЦП на этом компьютере всегда низкая, независимо от количества рабочих. Серверы — это отдельные машины; это машины, которые видят снижение загрузки ЦП при большом количестве рабочих.
Ответ №1:
Две разные идеи для ограничения производительности:
- Узким местом являются рабочие, сражающиеся друг с другом и с родителем за доступ к очереди заданий.
- Узким местом являются ограничения скорости соединения (защита от syn-flood) на серверах.
Сбор дополнительной информации:
- Профилируйте объем выполняемой работы: задачи, выполняемые в секунду, используйте это в качестве основного показателя производительности.
- Используйте захват пакетов для просмотра сетевой активности на предмет задержек на сетевом уровне.
- Попросите ваших рабочих документировать, как долго они ожидают доступа к очереди заданий.
Возможные улучшения:
- Попросите ваших работников использовать постоянные соединения, если они доступны / применимы (например, HTTP).
- Разделите задачи на несколько очередей заданий, передаваемых в пулы рабочих.
Комментарии:
1. Рабочие уже используют постоянные соединения. Я рассматривал подход с несколькими очередями, но не решаюсь переставлять столько кода, когда фактическая проблема все еще настолько туманна. (Я также рассматривал возможность использования, скажем, 4 рабочих потоков на рабочий процесс, чтобы уменьшить количество реальных процессов, если проблема заключается в многопроцессорной обработке python.)
Ответ №2:
Не совсем уверен, что происходит, если вы не предоставите все подробности.
Однако помните, что реальный параллелизм ограничен фактическим количеством аппаратных потоков. Если количество запущенных процессов намного больше, чем фактическое количество аппаратных потоков, в какой-то момент накладные расходы на переключение контекста будут больше, чем выгода от большего количества одновременных процессов.
Комментарии:
1. Доступно достаточно физического времени обработки, загрузка процессора довольно низкая. Это не должно быть проблемой переключения контекста. Проблема возникает всего с 30 рабочими в 8-ядерной системе. Кроме того, каждый рабочий тратит довольно много времени на простой: запросы к серверу занимают около 1/3 секунды.
Ответ №3:
Создание нового thead — очень дорогостоящая операция.
Одним из простейших способов управления большим количеством параллельных сетевых подключений является использование потоков без стека с поддержкой асинхронных сокетов. У Python была отличная поддержка и куча библиотек для этого.
Мой любимый — gevent, у которого есть отличная и полностью прозрачная утилита для исправления ошибок.