2008-11-05 26 views
82

¿Cuál es exactamente la función del bloqueo de intérprete global de Python? ¿Otros idiomas que se compilan en bytecode emplean un mecanismo similar?¿Por qué el bloqueo de intérprete global?

+6

También debería preguntar "¿Importa incluso?" –

+2

Acepto, considero que no es un problema ahora que en 2.6 se agregó el módulo de multiprocesamiento para permitirle programar usando múltiples procesos de forma similar a un hilo. http://docs.python.org/library/multiprocessing.html – monkut

+0

http: //programmers.stackexchange.com/questions/186889/why-was-python-written-with-the-gil –

Respuesta

31

La siguiente es desde el official Python/C API Reference Manual:

El Python intérprete no es totalmente hilo seguro. Para admitir programas de múltiples hilos de Python, hay un bloqueo global que debe ser retenido por el hilo actual antes de que pueda acceder de forma segura a los objetos Python. Sin la cerradura, incluso los operaciones más simples podrían causar problemas en un programa multi-roscado: por ejemplo, cuando dos hilos simultáneamente incremento el recuento de referencia de la mismo objeto, el recuento de referencia podría terminar siendo incrementan solamente una vez en lugar de dos veces.

Por lo tanto, existe la regla de que sólo el hilo que ha adquirido la cierre global del intérprete puede operar en objetos Python o llame Python/C API funciones. Con el fin de apoyar programas multihilo Python, el intérprete publica periódicamente y vuelve a adquirir el bloqueo - por defecto, cada 100 instrucciones de código de bytes (esto se pueden cambiar con sys.setcheckinterval()). El bloqueo se también liberado y volvió a adquirir alrededor potencialmente bloquean las operaciones de E/S como leer o escribir un archivo, por lo que otros hilos pueden correr mientras el hilo que solicita la E/S es la espera de la operación de E/S a completo.

Creo que resume bien el problema.

+0

Lo leí también, pero no puedo entender por qué Python es diferente a este respecto de, por ejemplo, java (¿verdad?) –

+0

Federico : Supongo que la VM principal de Java es totalmente segura para hilos –

+0

@EliBendersky Los subprocesos de Python se implementan como pthreads y son manejados por el sistema operativo (http://www.dabeaz.com/python/UnderstandingGIL.pdf) mientras que los subprocesos de Java son subprocesos de nivel de aplicación la programación es manejada por JVM –

18

El bloqueo de intérprete global es un gran bloqueo tipo mutex que protege los contadores de referencia de las mangueras. Si está escribiendo código python puro, todo esto ocurre detrás de las escenas, pero si incrusta Python en C, entonces puede que tenga que tomar/liberar el bloqueo explícitamente.

Este mecanismo no está relacionado con la compilación de Python a bytecode. No es necesario para Java. De hecho, ni siquiera es necesario para Jython (python compilado para jvm).

ver también this question

+2

"Este mecanismo no está relacionado con la compilación de Python a bytecode": Precisamente, es un artefacto de la implementación de CPython. Otras implementaciones (como Jython que ha mencionado) pueden estar libres de esta restricción en virtud de su implementación de seguridad de subprocesos –

6

En cuanto a su segunda pregunta, no todos los lenguajes de programación utilizan este, pero sólo los hace menos potente. Por ejemplo, los hilos en Ruby son green y no son nativos.

En Python, los hilos son nativos y el GIL solo impide que se ejecuten en diferentes núcleos.

En Perl, los hilos son aún peores. Simplemente copian todo el intérprete y están lejos de ser tan utilizables como en Python.

64

En general, para cualquier problema de seguridad de hilo tendrá que proteger sus estructuras internas de datos con bloqueos. Esto se puede hacer con varios niveles de granularidad.

  • Puede usar el bloqueo de grano fino, donde cada estructura separada tiene su propio candado.

  • Puede usar el bloqueo de grano grueso donde un bloqueo lo protege todo (el enfoque GIL).

Existen varios pros y contras de cada método. El bloqueo de grano fino permite un mayor paralelismo: dos hilos pueden ejecutar en paralelo cuando no comparten ningún recurso. Sin embargo, hay una sobrecarga administrativa mucho más grande. Para cada línea de código, es posible que deba adquirir y liberar varios bloqueos.

El enfoque de grano grueso es el opuesto. Dos hilos no se pueden ejecutar al mismo tiempo, pero un hilo individual se ejecutará más rápido porque no está haciendo tanta contabilidad. En definitiva, se trata de una compensación entre la velocidad de un solo subproceso y el paralelismo.

Ha habido algunos intentos de eliminar el GIL en python, pero la sobrecarga adicional para las máquinas de un solo hilo era generalmente demasiado grande. Algunos casos en realidad pueden ser más lentos incluso en máquinas multiprocesador debido a la contención del bloqueo.

¿Otros idiomas que se compilan en bytecode emplean un mecanismo similar?

Varía, y probablemente no se debe considerar una propiedad de lenguaje tanto como una propiedad de implementación. Por ejemplo, hay implementaciones de Python como Jython e IronPython que utilizan el enfoque de subprocesamiento de su VM subyacente, en lugar de un enfoque GIL. Además, la próxima versión de Ruby parece estar moviéndose towards introduciendo un GIL.

+0

¿Puede explicar esto: 'Dos hilos no se pueden ejecutar al mismo tiempo'? Recientemente escribí un servidor web simple en Python con multihilo. Para cada nueva solicitud del cliente, los servidores generan un nuevo hilo para él y esos hilos continúan ejecutándose. Entonces, habrá múltiples hilos ejecutándose al mismo tiempo, ¿verdad? ¿O lo he entendido de la manera equivocada? – avi

+0

@avi Los subprocesos de python AFAIK no se pueden ejecutar simultáneamente, pero eso no significa que un subproceso deba bloquear al otro. GIL solo significa que solo un hilo puede interpretar código python a la vez, no significa que la administración de hilos y la asignación de recursos no funcionen. – Benproductions1

+1

^por lo que en cualquier punto del tiempo, solo un hilo estará publicando contenido para el cliente ... así que no tiene sentido utilizar el multihilo para mejorar el rendimiento. ¿derecho? – avi

10

Python, al igual que perl 5, no fue diseñado desde cero para ser seguro para subprocesos. Los hilos fueron injertados después del hecho, por lo que el bloqueo del intérprete global se usa para mantener la exclusión mutua cuando solo un hilo está ejecutando código en un momento dado en las entrañas del intérprete.

Los subprocesos individuales de Python son cooperativamente multitarea por el propio intérprete ciclando el bloqueo cada cierto tiempo.

Es necesario agarrar el candado cuando habla con Python desde C cuando otros hilos de Python están activos para 'aceptar' este protocolo y asegurarse de que no ocurra nada inseguro a sus espaldas.

Otros sistemas que tienen un patrimonio de subproceso único que luego se convirtieron en sistemas multiproceso a menudo tienen algún mecanismo de este tipo. Por ejemplo, el kernel de Linux tiene el "Gran bloqueo de kernel" desde sus primeros días de SMP. Poco a poco, a medida que el rendimiento de subprocesos múltiples se convierte en un problema, hay una tendencia a tratar de romper este tipo de bloqueos en partes más pequeñas o reemplazarlos con algoritmos de bloqueo y estructuras de datos donde sea posible para maximizar el rendimiento.

+0

+1 por mencionar el hecho de que se usa el bloqueo de grano grueso de lo que la mayoría piensa, especialmente el frecuentemente olvidado BKL (yo uso 'reiserfs' - la única razón real que conozco). – new123456

+3

Linux tenía BKL, desde la versión 2.6.39, BKL ha sido eliminado por completo. – avi

+5

Por supuesto. Eso sí, fue ~ 3 años después de que respondí la pregunta. =) –

2

Tal vez this artículo de la BDFL ayudará.

Cuestiones relacionadas