Python - пул не использует все ядра - PullRequest
0 голосов
/ 24 июня 2018

Я использую Pool из пакета multiprocessing (from multiprocessing.dummy import Pool).Я написал функцию, которая читает текстовый файл и предварительно обрабатывает его для будущей функции.У меня есть около 20 000 таких текстовых файлов, поэтому я хотел распараллелить процесс - и для этого я использовал пул.У меня 32 ядра на удаленном сервере, на котором выполняется код, поэтому я попытался открыть 70 процессов (я тоже пробовал меньше, проблема остается) - так выглядит мой системный монитор:

enter image description here

Как видно, 16 из 32 ядер вообще не работают!

Буду признателен за любую помощь.

1 Ответ

0 голосов
/ 24 июня 2018

Как я уже сказал в своем комментарии, все структуры multiprocessing.dummy предназначены для имитации многопроцессорного интерфейса с использованием обычных потоков, которые могут быть весьма полезны для тестирования, отладки, профилирования и т. Д. Или в качестве официальных документов. говорят:

multiprocessing.dummy дублирует API multiprocessing, но является не более чем оболочкой для модуля threading.

Хотя Python (CPython) threading использует реальные системные потоки, и, следовательно, теоретически возможно, чтобы ваш многопоточный код выполнялся на разных процессорах, из-за страшного GIL ни один из этих потоков не будет когда-либо бегать одновременно. Есть исключения из этого правила, хотя все задачи, которые абстрагируют системные вызовы и ожидают событие (например, ввод / вывод), могут выполняться параллельно, но в тот момент, когда обработка переместится в домен Python, она будет заблокирована GIL и не будет разрешено продолжать выполнение до тех пор, пока счетчик кода не переключит свой контекст.

Короче говоря, если вы хотите использовать несколько ядер через пул multiprocessing, не используйте адаптации и абстракции в multiprocessing.dummy (который имеет значение true для другие пакеты dummy тоже) и используйте сам корневой модуль multiprocessing - в вашем случае, multiprocessing.pool.Pool.

При этом, учитывая, что модуль threading не имеет интерфейса пула, я часто использую multiprocessing.dummy.Pool (или multiprocessing.pool.ThreadPool) вместо этого для тяжелых операций ввода / вывода ( т.е. не ограничен GIL), когда совместно используемая память важнее обработки shared и накладных расходов, которые она несет. Вполне возможно, что даже при переключении на multiprocessing.pool.Pool вы не заметите большой разницы, если не будете выполнять сложную постобработку при получении файлов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...