2009-08-18 2 views
145

Что такое глобальная блокировка интерпретатора и почему это проблема?Что такое глобальный шлюз интерпретатора (GIL)?

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

+0

Возможный дубликат [Почему глобальный переводчик?] (Http://stackoverflow.com/questions/265687/why-the-global-interpreter -lock) –

ответ

144

PILON GIL предназначен для сериализации доступа к внутренним интерпретаторам из разных потоков. В многоядерных системах это означает, что несколько потоков не могут эффективно использовать несколько ядер. (Если GIL не привел к этой проблеме, большинство людей не заботятся о GIL - это только поднимается как проблема из-за увеличения распространенности многоядерных систем.) Если вы хотите понять это подробно, вы можете посмотреть this video или посмотреть на this set of slides. Это может быть слишком много информации, но затем вы задали детали :-)

Обратите внимание, что GIL для Python - это действительно проблема для CPython, эталонной реализации. Jython и IronPython не имеют GIL. Как разработчик Python, вы обычно не сталкиваетесь с GIL, если не пишете расширение C. C-разработчикам необходимо выпустить GIL, когда их расширения блокируют ввод-вывод, так что другие потоки в процессе Python получат возможность запуска.

Обновление: Обновлена ​​ссылка на видео, чтобы указать на Youtube, так как ранее ссылка blip.tv была сгнила.

+31

Хороший ответ - в основном это означает, что потоки в Python хороши только для блокировки ввода-вывода; ваше приложение никогда не будет превышать 1 процессорное ядро ​​использования процессора –

+5

«Как разработчик Python вы обычно не сталкиваетесь с GIL, если не пишете расширение C» - Возможно, вы не знаете, что причина вашей многопоточной код работает в ритме улиток - это GIL, но вы наверняка почувствуете его эффекты. Меня все еще удивляет, что для использования 32-ядерного сервера с Python мне нужно 32 процесса со всеми связанными с ними служебными данными. – Basic

+5

@PaulBetts: это неправда. Вероятно, что критический код производительности уже использует расширения C, которые могут и могут выпускать модули GIL, например, 'regex',' lxml', 'numpy'. Cython позволяет выпустить GIL в пользовательском коде, например, ['b2a_bin (data)'] (https://gist.github.com/zed/3526111) – jfs

41

Предположим, у вас есть несколько потоков, которые не действительно касаются данных друг друга. Они должны выполняться как можно более независимо. Если у вас есть «глобальная блокировка», которую вам нужно приобрести, чтобы (скажем) вызвать функцию, которая может оказаться узким местом. Вы можете не получить большую выгоду от наличия нескольких потоков в первую очередь.

Чтобы воплотить это в реальную мировую аналогию: представьте себе 100 разработчиков, работающих в компании с единственной кружкой для кофе. Большинство разработчиков потратили свое время, ожидая кофе вместо кодирования.

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

+0

Но если разработчики использовали поддержку билетов (запись 2 -минутные ответы, а затем ждать 1 час), все они будут достаточно продуктивными, несмотря на одну кружку кофе. –

1

В Википедии есть хорошее описание глобального интерпретатора блокировка

http://en.wikipedia.org/wiki/Global_Interpreter_Lock

что статья ссылка эта хорошая статья, которая обсуждает GIL в Python.

http://www.ddj.com/linux-open-source/206103078?pgno=2

+0

Возможно, лучше связаться с началом этой статьи DDJ - http://www.ddj.com/linux-open-source/206103078 –

+5

Спасибо, но я сделал домашнее задание, прежде чем задавать этот вопрос здесь, и, конечно, пошел сначала google и wikipedia. –

13

Всякий раз, когда два потока имеют доступ к одной и той же переменной, у вас есть проблемы. В C++, например, способ избежать проблемы состоит в том, чтобы определить какую-либо блокировку мьютекса, чтобы предотвратить, например, два потока, чтобы, например, ввести установщик объекта в одно и то же время.

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

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

Обратите внимание, что вы можете освободить GIL, если вы находитесь внутри метода, который вы написали в C, например.

Использование GIL не присуще Python, а некоторому его интерпретатору, включая наиболее распространенный CPython. (#edited см комментарий)

Вопрос GIL еще действует в Python 3000.

+0

Stackless по-прежнему имеет GIL. Stackless не улучшает потоки (как в модуле) - он предлагает другой метод программирования (сопрограммы), которые пытаются обойти эту проблему, но требуют неблокирующих функций. – jnoller

+0

Хорошая точка. Спасибо за комментарий – fulmicoton

+0

Как насчет нового GIL в 3.2? – new123456

7

Watch David Beazley рассказать вам все, что вы когда-либо хотели знать о GIL.

+3

Он отличный болтун - если кто-то убедит вас, что ГИЛ сосет, это он. – new123456

+1

ссылка мертва. :( – szeitlin

+3

Дэвид Безли - Понимание Python GIL - https://www.youtube.com/watch?v=Obt-vMVdM8s –

13

Давайте сначала понять, что питон GIL обеспечивает:

Любая операция/инструкция выполняется в интерпретаторе. GIL гарантирует, что интерпретатор удерживается одним потоком на конкретным моментом времени. И ваша программа python с несколькими потоками работает в одном интерпретаторе. В любой конкретный момент времени этот интерпретатор удерживается одним потоком. Это означает, что только резьба, удерживающая переводчик, составляет , работающий, по адресу , любой момент времени.

Теперь почему это вопрос:

Ваша машина может быть, имеющих несколько ядер/процессоров. И несколько ядер позволяют нескольким потокам выполнять одновременно i.e несколько потоков могут выполнять в любой конкретный момент времени.. Но поскольку интерпретатор поддерживается одним потоком, другие потоки ничего не делают, хотя у них есть доступ к ядру. Таким образом, вы не получаете никаких преимуществ, предоставляемых несколькими ядрами, потому что в любой момент используется только одно ядро, которое является ядром, используемым потоком, в настоящее время использующим интерпретатор. Таким образом, ваша программа будет работать так долго, как если бы это была одна потоковая программа.

Однако потенциально блокирующие или длительные операции, такие как обработка ввода-вывода, обработка изображений и хруст числа NumPy, происходят за пределами GIL. Взято с here. Таким образом, для таких операций многопоточная операция будет работать быстрее, чем однопоточная операция, несмотря на наличие GIL. Таким образом, GIL не всегда является узким местом.

Редактировать: GIL представляет собой деталь реализации CPython. PyPy и Jython не имеют GIL, поэтому в них должна быть действительно многопоточной программа, я думал, что никогда не использовал PyPy и Jython и не уверен в этом.

+3

** Примечание **: PyPy имеет ** GIL **. _Reference_: [http://doc.pypy.org/en/latest/faq.html#does-pypy-have-a-gil-why](http://doc.pypy .org/en/latest/faq.html # does-pypy-have-a-gil-why). Хотя у Ironpython и Jython нет GIL. –

+0

Действительно, PyPy имеет GIL, но IronPython этого не делает. – Emmanuel

0

Почему Python (CPython и другие) использует GIL

От http://wiki.python.org/moin/GlobalInterpreterLock

В CPython, глобальная блокировка интерпретатора или GIL , является мьютеком, который мешает нескольким собственным потокам выполнять байт-коды Python сразу. Эта блокировка необходима главным образом потому, что управление памятью CPython не является потокобезопасным.

Как удалить его с Python?

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

В Numpy или какой-либо другой расширенной библиотеке python, иногда отпуская GIL другим потокам, можно повысить эффективность всей программы.

1

Я хочу поделиться примером из книги многопоточности для визуальных эффектов. Итак, вот классическая ситуация с мертвой зоной.

static void MyCallback(const Context &context){ 
Auto<Lock> lock(GetMyMutexFromContext(context)); 
... 
EvalMyPythonString(str); //A function that takes the GIL 
...  
} 

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

╔═══╦════════════════════════════════════════╦══════════════════════════════════════╗ 
║ ║ Main Thread       ║ Other Thread       ║ 
╠═══╬════════════════════════════════════════╬══════════════════════════════════════╣ 
║ 1 ║ Python Command acquires GIL   ║ Work started       ║ 
║ 2 ║ Computation requested     ║ MyCallback runs and acquires MyMutex ║ 
║ 3 ║          ║ MyCallback now waits for GIL   ║ 
║ 4 ║ MyCallback runs and waits for MyMutex ║ waiting for GIL      ║ 
╚═══╩════════════════════════════════════════╩══════════════════════════════════════╝ 
4

Python не позволяет многопоточность в прямом смысле этого слова. Он имеет многопоточный пакет, но если вы хотите многопоточность, чтобы ускорить работу вашего кода, то, как правило, не рекомендуется использовать его. Python имеет конструкцию, называемую Global Interpreter Lock (GIL). GIL гарантирует, что только один из ваших «потоков» может выполняться в любой момент. Нить получает GIL, делает небольшую работу, затем передает GIL на следующую нить. Это происходит очень быстро, поэтому человеческому глазу может показаться, что ваши потоки выполняются параллельно, но они действительно просто по очереди используют один и тот же процессорный ядро. Вся эта передача GIL добавляет накладные расходы на исполнение. Это означает, что если вы хотите, чтобы ваш код работал быстрее, то использование пакета потоковой передачи часто не является хорошей идеей.

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

Многопоточность может передаваться в операционную систему (путем многопроцессорной обработки), внешнее приложение, которое вызывает ваш код Python (например, Spark или Hadoop), или код, который вызывает ваш код на Python (например: вы может заставить ваш код Python вызвать функцию C, которая делает дорогой многопоточный материал).