Por que não há GIL na Java Virtual Machine? Por que o Python precisa tanto de um?

177

Espero que alguém possa fornecer algumas dicas sobre o que é fundamentalmente diferente sobre a Java Virtual Machine que permite implementar threads de maneira adequada, sem a necessidade de um Global Interpreter Lock (GIL), enquanto o Python exige esse mal.

AgentLiquid
fonte

Respostas:

223

O Python (a linguagem) não precisa de um GIL (e é por isso que ele pode ser implementado perfeitamente na JVM [Jython] e .NET [IronPython], e essas implementações multithread livremente). O CPython (a implementação popular) sempre usou um GIL para facilitar a codificação (especialmente a codificação dos mecanismos de coleta de lixo) e a integração de bibliotecas C-codificadas não seguras para thread (costumava haver muitas delas por aí; -)

O projeto Unladen Swallow , entre outros objetivos ambiciosos, planeja uma máquina virtual sem GIL para Python - para citar esse site: "Além disso, pretendemos remover o GIL e corrigir o estado de multithreading em Python. Acreditamos que isso seja possível através da implementação de um sistema de GC mais sofisticado, algo como o IBM's Recycler (Bacon et al, 2001). "

Alex Martelli
fonte
6
Alex, e as velhas tentativas de remover o GIL, não havia muita sobrecarga nisso (um fator 2 é o que eu me lembro)?
Bartosz Radaczyński
10
Sim Bartosz, Greg Stein mediu isso em 1999. A coleta de lixo por contagem de referência foi o assassino, forçando uma enorme sobrecarga de bloqueio de grãos finos. É por isso que um GC mais avançado é crucial lá.
287 Alex Martelli
80
A equipe do Unladen Swallow desistiu de remover o GIL: code.google.com/p/unladen-swallow/wiki/…
Seun Osewa
1
Alternativas para Unladen e CPython são PyPy, Jython e IronPython. Os dois últimos não têm um GIL, mas o uso do módulo de multiprocessamento evita o GIL e fica mais seguro.
Cees Timmerman
50

A JVM (pelo menos hotspot) tem um conceito semelhante ao "GIL", é muito mais fina em sua granularidade de bloqueios, a maior parte disso vem dos GCs em hotspot, que são mais avançados.

No CPython, é um grande bloqueio (provavelmente não tão verdadeiro, mas bom o suficiente para o argumento), na JVM é mais difundido com conceitos diferentes, dependendo de onde é usado.

Veja, por exemplo, vm / runtime / safepoint.hpp no ​​código do ponto de acesso, o que é efetivamente uma barreira. Uma vez em um ponto seguro, a VM inteira parou em relação ao código java, assim como a VM python para no GIL.

No mundo Java, esses eventos de pausa da VM são conhecidos como "pare o mundo"; nesses pontos, apenas o código nativo que está vinculado a determinados critérios é de execução livre; o restante da VM foi interrompido.

Além disso, a falta de um bloqueio grosseiro no java torna a JNI muito mais difícil de escrever, pois a JVM oferece menos garantias sobre seu ambiente para chamadas de FFI, uma das coisas que o cpython facilita bastante (embora não seja tão fácil quanto usar ctypes).

Greg Bowyer
fonte
7

Há um comentário abaixo nesta postagem do blog http://www.grouplens.org/node/244 que sugere o motivo pelo qual foi tão fácil dispensar um GIL para IronPython ou Jython; é que o CPython usa contagem de referência, enquanto as outras 2 VMs têm coletores de lixo.

A mecânica exata do porquê disso é que eu não entendo, mas parece uma razão plausível.

user235859
fonte
5
Quando você compartilha promiscuamente objetos entre threads, malhar quando ninguém mais faz referência a um objeto específico é moderadamente estranho. A contagem de referência com um bloqueio global é uma maneira (cara). Uma maneira diferente de resolvê-lo seria deixar apenas um encadeamento de cada vez manter referências ao objeto, o que tornaria a maioria das atividades local do encadeamento, a um custo de tornar as comunicações entre encadeamentos mais estranhas. Pessoalmente, acho que ele está dizendo que HPC usa-passagem de mensagens entre processadores e memória não compartilhada, e que ele faz isso por razões de escalabilidade ...
Donal Fellows
0

Neste link, eles têm a seguinte explicação:

... "Partes do intérprete não são seguras para threads, embora principalmente porque torná-las todas seguras para threads pelo uso massivo de bloqueios reduzisse extremamente o encadeamento único ( fonte ). Isso parece estar relacionado ao coletor de lixo CPython usando a contagem de referência (a JVM e o CLR não e, portanto, não precisa bloquear / liberar uma contagem de referência todas as vezes.) Mas mesmo que alguém pensasse em uma solução aceitável e a implementasse, as bibliotecas de terceiros ainda teriam os mesmos problemas ".

Oliver Wilken
fonte
-1

O Python não possui jit / aot e o período em que foi gravado em processadores multithread não existia. Como alternativa, você pode recompilar tudo no Julia lang que não possui GIL e obter algum aumento de velocidade no seu código Python. O Jython também é uma droga, é mais lento que o Cpython e Java. Se você quiser se ater ao Python, considere usar plug-ins paralelos, não obterá um aumento instantâneo de velocidade, mas poderá fazer programação paralela com o plug-in correto.

Jim
fonte
e o PyPy?
Denis631 22/01/19