Почему в виртуальной машине Java нет GIL? Почему Python так нужен?

177

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

AgentLiquid
источник

Ответы:

223

Python (язык) не нуждается в GIL (именно поэтому он может быть идеально реализован на JVM [Jython] и .NET [IronPython], и эти реализации могут быть многопоточными свободно). CPython (популярная реализация) всегда использовал GIL для простоты кодирования (особенно кодирование механизмов сборки мусора) и интеграции не поточно-безопасных C-кодированных библиотек (раньше их было множество; -).

Проект Unladen Swallow , помимо других амбициозных целей, планирует создать виртуальную машину без GIL для Python - процитировать этот сайт: «Кроме того, мы намерены удалить GIL и исправить состояние многопоточности в Python. Мы считаем, что это возможно благодаря внедрению более сложной системы GC, чем-то вроде IBM Recycler (Bacon et al, 2001). "

Алекс Мартелли
источник
6
Алекс, как насчет старых попыток удалить GIL, разве не было тонны накладных расходов (фактор 2 - это то, что я помню)?
Бартош Радачиньски
10
Да, Бартош, Грег Стейн действительно измерил это в 1999 году. Сборка мусора с помощью подсчета ссылок была убийцей, что привело к огромным накладным расходам мелкозернистой блокировки. Вот почему более продвинутый GC имеет решающее значение там.
Алекс Мартелли
80
Команда Unladen Swallow отказалась от удаления GIL: code.google.com/p/unladen-swallow/wiki/…
Сеун Осева,
1
Альтернативами Unladen и CPython являются PyPy, Jython и IronPython. Последние два не имеют GIL, но использование многопроцессорного модуля обходит GIL и в любом случае безопаснее.
Сис Тиммерман
50

JVM (по крайней мере, горячая точка) действительно имеет концепцию, аналогичную «GIL», она гораздо более тонка в своей детализации блокировки, большая часть которой исходит от GC в горячей точке, которые являются более продвинутыми.

В CPython это одна большая блокировка (вероятно, это не так, но достаточно хорошо для аргументов), в JVM она более распространена с различными концепциями в зависимости от того, где она используется.

Взгляните, например, на vm / runtime / safepoint.hpp в коде горячей точки, который фактически является барьером. Оказавшись в безопасном месте, вся виртуальная машина остановилась в связи с Java-кодом, так же, как Python VM останавливается в GIL.

В мире Java такие события приостановки виртуальной машины известны как «остановка мира», в этих точках только нативный код, который связан с определенными критериями, является свободным, остальная часть виртуальной машины была остановлена.

Кроме того, отсутствие грубой блокировки в java делает JNI намного более трудным для написания, поскольку JVM дает меньше гарантий относительно своей среды для вызовов FFI - одна из вещей, которую cpython делает довольно простой (хотя и не такой простой, как использование ctypes).

Грег Бауер
источник
7

Ниже в этом сообщении блога http://www.grouplens.org/node/244 есть комментарий, объясняющий причину, по которой так легко обойтись без GIL для IronPython или Jython, заключается в том, что CPython использует подсчет ссылок, тогда как другие 2 виртуальные машины имеют сборщики мусора.

Точная механика того, почему это так, я не понимаю, но это звучит как правдоподобная причина.

user235859
источник
5
Когда вы беспорядочно делитесь объектами между потоками, работать, когда никто не имеет ссылки на конкретный объект, умеренно неловко. Подсчет ссылок с глобальной блокировкой - это один (дорогой) способ. Другой способ ее решения состоял бы в том, чтобы позволить только одному потоку одновременно хранить ссылки на объект, что сделало бы большую часть активности локально-ориентированной на потоки за счет того, что связь между потоками стала более неудобной. Лично я думаю, что это говорит о том, что HPC использует передачу сообщений между процессорами, а не разделяемой памятью, и что это происходит по соображениям масштабируемости ...
Донал Феллоуз
0

В этой ссылке они имеют следующее объяснение:

... "Части Интерпретатора не являются поточно-ориентированными, хотя в основном потому, что превращение их в многопотоковое благодаря использованию массивных блокировок крайне замедляет однопоточность ( источник ). Это, по-видимому, связано с сборщиком мусора CPython, использующим подсчет ссылок (JVM) и CLR этого не делают, и, следовательно, не нужно каждый раз блокировать / освобождать счетчик ссылок. Но даже если кто-то подумает о приемлемом решении и реализует его, сторонние библиотеки все равно будут иметь такие же проблемы ».

Оливер Уилкен
источник
-1

В Python отсутствует jit / aot, и временные рамки, в которых он был написан на многопоточных процессорах, не существовали. В качестве альтернативы вы можете перекомпилировать все в Julia lang, в котором отсутствует GIL, и получить некоторое ускорение в своем коде Python. Также Jython отстой, он медленнее, чем Cpython и Java. Если вы хотите придерживаться Python, подумайте об использовании параллельных плагинов, вы не получите мгновенного прироста скорости, но вы можете выполнять параллельное программирование с правильным плагином.

Джим
источник
что насчет PyPy?
denis631