Производительность кода Python снижается с поточной - PullRequest
26 голосов
/ 25 июля 2011

Я написал рабочую программу на 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

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

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

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

Ответы [ 2 ]

39 голосов
/ 25 июля 2011

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

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

Я рекомендую использовать модуль multiprocessing вместо нескольких потоков.

9 голосов
/ 25 июля 2011

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

...