Подтвердить что ты не робот

Производительность кода Python уменьшается с потоками

Я написал рабочую программу на Python, которая в основном разбирает партию двоичных файлов, извлекает данные в структуру данных. Каждый файл занимает около секунды для синтаксического анализа, что соответствует часам для тысяч файлов. Я успешно реализовал поточную версию метода пакетного разбора с регулируемым количеством потоков. Я протестировал метод на 100 файлах с различным количеством потоков, отсчитывая каждый запуск. Вот результаты (0 потоков относится к моему исходному, пред-поточному коду, 1 поток к новой версии запускается с одним нитом, порожденным).

0 threads: 83.842 seconds
1 threads: 78.777 seconds
2 threads: 105.032 seconds
3 threads: 109.965 seconds
4 threads: 108.956 seconds
5 threads: 109.646 seconds
6 threads: 109.520 seconds
7 threads: 110.457 seconds
8 threads: 111.658 seconds

Несмотря на то, что нерестование потока дает небольшое увеличение производительности по сравнению с тем, что основной поток выполняет всю работу, увеличение количества потоков фактически снижает производительность. Я бы ожидал увидеть увеличение производительности, по крайней мере, до четырех потоков (по одному для каждого моего ядра). Я знаю, что потоки связаны с накладными расходами, но я не думал, что это будет иметь большое значение с одноразрядным числом потоков.

Я слышал об "блокировке глобального интерпретатора", но по мере того как я перемещаюсь до четырех потоков, я вижу соответствующее количество ядер на работе - с двумя потоками на два ядра отображаются активность во время разбора и т.д.

Я также тестировал несколько разных версий кода синтаксического анализа, чтобы проверить, связана ли моя программа с IO. Кажется, это не так; просто чтение в файле занимает относительно небольшую долю времени; обработка файла - это почти все. Если я не выполняю IO и не обрабатываю уже прочитанную версию файла, я добавляю второй поток, а третий поток немного улучшает его. Я просто задаюсь вопросом, почему я не могу использовать компьютер с несколькими ядрами, чтобы ускорить работу. Пожалуйста, разместите любые вопросы или способы, которые я мог бы прояснить.

4b9b3361

Ответ 1

Это, к сожалению, относится к CPython, в основном из-за Global Interpreter Lock (GIL). Код Python, который привязан к CPU, просто не масштабируется по потокам (с другой стороны, код с привязкой к I/O может масштабироваться в некоторой степени).

Давид Бэзли имеет весьма информативное представление , где он обсуждает некоторые проблемы, связанные с GIL. Видео можно найти здесь (спасибо @Ikke!)

Моя рекомендация заключалась бы в использовании модуля multiprocessing вместо нескольких потоков.

Ответ 2

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