Быстрая статья, объясняющая GIL

Как поток взаимодействует с процессором?

Учтите, что у меня есть очередь с 4 потоками и 4 процессорами. Тип планировщика, который вы используете, определяет, как организованы потоки.

Первый поток уходит в начале и выделяется процессору; остальные три потока теперь активны. Остальные потоки также выделяются одному или нескольким из оставшихся 3 процессоров, поскольку они свободны. (Это часто встречается в C++, Java, GO и т. д.)

Python использует для этого другой стиль.

Представьте еще раз, что у меня есть четыре процессора и очередь (имеющая 4 потока), называемая очередью готовности.

Теперь операционная система выберет поток из готовой очереди и передаст его процессору. Python заблокирует оставшийся поток этой программы в этот момент, пока поток выполняется.

Теперь это приведет к заполнению очереди ожидания оставшимися потоками (т. е. их выполнение не будет запланировано ни на одном из процессоров).

В конечном итоге поток будет прерван и вернется обратно в очередь готовности вместе со всеми другими потоками из очереди ожидания. Новый поток теперь будет назначен процессору, блокируя другие. так что цикл продолжается! Это называется GIL или Global Interpreter Lock.

Почему GIL на картинке?

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

Какая проблема была решена GIL?

Как уже говорилось, GIL в Python гарантирует, что одновременно активен только один поток. Таким образом, мы можем обещать, что опасности возникновения условий гонки не будет, даже если многопоточная функция будет обращаться к общим данным.

Чтобы лучше понять, давайте рассмотрим пример…

Представьте, что у папы и его сына есть банковский счет на 50 долларов. Поэтому если подумать о том, что папа постоянно откладывает деньги, а сын всегда их тратит.
У нас будет три условия!

  1. Отец копит деньги здесь; сын тратит его позже
current_account_balance = 50

# Dad saves
current_account_balance = current_account_balance + 10
# we have current balance i.e. 50 + 10 = 60


# Son spends
current_account_balance = current_account_balance - 10
# we have current balance i.e. 60 -10 = 50

2. Сын тратит деньги, а отец копит их.

current_account_balance = 50

# Son spends
current_account_balance = current_account_balance - 10
# we have current balance i.e. 50 -10 = 40

# Dad saves
current_account_balance = current_account_balance + 10
# we have current balance i.e. 40 + 10 = 50

3. И отец, и сын одновременно копят и тратят деньги.

Затем они оба прочитают начальное значение current_account_balance, равное 50, а окончательное значение current_account_balance будет определено потоком, который изменит current_account_balance. сильный> в конце.

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

Поскольку Python позволяет одновременно запускать только один поток, GIL избегает этого обстоятельства (состояния гонки).

Примечание:

Когда программа полностью привязана к ЦП, добавление потоков для ее ускорения не имеет смысла.

Что связано с процессором?

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

Например, программы, привязанные к процессору, которые большую часть времени работают на процессоре. Игры и визуальные эффекты — очевидные темы. Игры включают в себя много арифметики! Дополнительные примеры включают программное обеспечение с обработкой изображений, машинным обучением и т. д.

Процессы, связанные с вводом-выводом, противоположны процессам, связанным с процессором.

Что такое связанный с вводом-выводом процесс?

Это ситуация, в которой вашему процессу требуется много времени для ожидания ввода или вывода. (IP/OP может использоваться для различных целей, включая чтение с сервера, запись на него и ожидание ввода данных пользователем.)

Например. эта веб-страница в настоящее время отображается, пока мы ждем загрузки фотографий; в результате из-за необходимости ждать сервера веб-серверы потребляют много операций ввода-вывода!

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

Однако, если ваш процесс связан с вводом-выводом, как веб-сервер, можно использовать потоки, поскольку они экономят время.

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

Что делать с GIL Python? а такжекак я могу увеличить скорость привязки ЦП?

Можно сказать, что следующий подход будет эффективен для обеих задач.

  • Многопроцессорность. Это один из самых популярных и успешных методов обхода GIL. Поскольку каждый процесс в Python имеет свой собственный уникальный интерпретатор и область памяти, GIL не представляет проблемы, когда мы используем несколько процессов, а не множество потоков. Кроме того, поскольку использование множества процессов намного дороже, чем использование множества потоков, его следует использовать с умом. потому что это требует времени и индивидуальной памяти.
  • Выбор альтернативного интерпретатора. Доступны многочисленные версии интерпретатора Python. Самые известные из них созданы соответственно на Python (PyPy), Java (Jython), C# (IronPython) и C (CPython).