Поддерживает ли Python многопоточность? Может ли это ускорить время выполнения?


Я немного смущен тем, работает ли многопоточность в Python или нет.

Я знаю, что было много вопросов об этом, и я прочитал многие из них, но я все еще смущен. Я знаю из своего собственного опыта и видел, как другие публикуют свои собственные ответы и примеры здесь, на StackOverflow, что многопоточность действительно возможна в Python. Так почему же все продолжают говорить, что Python заблокирован GIL и что только один поток может работать одновременно? Это явно выполнять работу. Или есть какая-то разница, которую я не получаю здесь?

многие плакаты / респонденты также продолжают упоминать, что резьба ограничена, потому что она не использует несколько ядер. Но я бы сказал, что они все еще полезны, потому что они работают одновременно и, таким образом, быстрее выполняют объединенную рабочую нагрузку. Я имею в виду, почему вообще должен быть модуль потока Python в противном случае?

обновление:

Спасибо за все ответы до сих пор. Как я поймите, что многопоточность будет выполняться параллельно только для некоторых задач ввода-вывода, но может выполняться только по одному для нескольких основных задач, связанных с ЦП.

Я не совсем уверен, что это означает для меня в практическом плане, поэтому я просто приведу пример задачи, которую я хотел бы многопоточность. Например, предположим, что я хочу перебрать очень длинный список строк, и я хочу сделать некоторые основные строковые операции над каждым элементом списка. Если я разделю список, отправьте каждый подсписок, чтобы быть обработанный моим циклом/строковым кодом в новом потоке и отправляющий результаты обратно в очередь, будут ли эти рабочие нагрузки выполняться примерно в одно и то же время? Самое главное, это теоретически ускорит время, необходимое для запуска скрипта?

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

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

2 57

2 ответа:

Гил не предотвращает продевать нитку. Все, что делает GIL, - это убедиться, что только один поток выполняет код Python за раз; Управление по-прежнему переключается между потоками.

то, что Gil предотвращает тогда, использует более одного ядра процессора или отдельных процессоров для параллельного запуска потоков.

Это относится только к коду Python. Расширения C могут и действительно выпускают GIL, чтобы позволить нескольким потокам кода C и одному потоку Python работать на нескольких ядрах. Это распространяется на ввод-вывод управляется ядром, например select() вызовы для чтения и записи сокетов, что делает Python достаточно эффективно обрабатывать сетевые события в многопоточной многоядерной установке.

то, что делают многие развертывания серверов, выполняется более чем одним процессом Python, чтобы ОС могла обрабатывать планирование между процессами для максимального использования ядер вашего процессора. Вы также можете использовать multiprocessing библиотека для обработки параллельной обработки нескольких процессов из одной кодовой базы и родительский процесс, если это подходит для ваших случаев использования.

обратите внимание, что GIL применим только к реализации CPython; Jython и IronPython используют другую реализацию потоков (собственные потоки Java VM и .NET common runtime соответственно).

чтобы напрямую обратиться к вашему обновлению: любая задача, которая пытается получить повышение скорости от параллельного выполнения, используя чистый код Python, не будет видеть ускорение, поскольку потоковый код Python заблокирован для одного потока, выполняющегося одновременно. Если однако вы смешиваете расширения C и операции ввода-вывода (например, операции PIL или numpy) , и любой код C может выполняться параллельно с один активный поток Python.

Python threading отлично подходит для создания отзывчивого графического интерфейса или для обработки нескольких коротких веб-запросов, где ввод-вывод является узким местом больше, чем код Python. Он не подходит для распараллеливания вычислительно интенсивного кода Python, придерживайтесь multiprocessing модуль для таких задач или делегировать на выделенный внешний библиотека.

да. :)

У вас низкий уровень thread модуль и более высокий уровень резьбонарезной модуль. Но это вы просто хотите использовать многоядерные машины, то многопроцессорная обработка модуль-это путь.

цитата docs:

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