¿Por qué Python se escribió con GIL?

El bloqueo de intérprete global (GIL) parece ser citado a menudo como una de las principales razones por las que el enhebrado y cosas por el estilo son un poco complicadas en Python, lo que plantea la pregunta «¿Por qué se hizo eso en primer lugar?»

Al no ser un programador, no tengo ni idea de por qué podría ser eso: ¿cuál fue la lógica detrás de la instalación del GIL?

Comentarios

  • El artículo de Wikipedia establece que » el GIL puede ser una barrera significativa para el paralelismo, un precio que se paga por tener el dinamismo del lenguaje » , y continúa diciendo que » Las razones para emplear un bloqueo de este tipo incluyen: mayor velocidad de los programas de un solo subproceso (no es necesario adquirir o liberar bloqueos en todas las estructuras de datos por separado) y una fácil integración de las bibliotecas C que generalmente son no es seguro para subprocesos. »
  • @RobertHarvey, el dinamismo no tiene nada que ver con eso. El problema es la mutación.
  • stackoverflow.com/questions/265687/…
  • ¿No puede ‘ evitar sentir que, al igual que la ‘ de Java, la falta de números sin firmar, tenía la intención de evitar ‘ No sé lo que ‘ están haciendo disparándose en el pie. Desafortunadamente, cualquiera que sepa sepa lo que ‘ está haciendo obtiene un lenguaje deficiente, lo cual es una verdadera lástima porque Python se mueve de muchas otras formas
  • @Basic, tiene que haber alguna forma estándar de tratar con matrices de bytes en Java (no lo he ‘ t usado en mucho tiempo) para hacer cripto matemática. Python (por ejemplo) no ‘ t tiene números con signo, pero yo no ‘ ni siquiera intentaría hacer operaciones bit a bit con él porque hay mejores formas.

Respuesta

Hay varias implementaciones de Python, por ejemplo, CPython, IronPython, RPython, etc.

Algunos de ellos tienen un GIL, otros no. Por ejemplo, CPython tiene el GIL:

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

Las aplicaciones escritas en lenguajes de programación con GIL pueden diseñarse para usar procesos separados para lograr un paralelismo completo, ya que cada proceso tiene su propio intérprete y a su vez tiene su propio GIL.

Beneficios del GIL

  • Mayor velocidad de programas de un solo subproceso.
  • Fácil integración de bibliotecas C que generalmente no son seguras para subprocesos.

Por qué Python (CPython y otros) usa GIL

En CPython, el bloqueo de intérprete global, o GIL, es un mutex que evita que varios subprocesos nativos ejecuten códigos de bytes de Python a la vez. Este bloqueo es necesario principalmente porque la administración de memoria de CPython no es segura para subprocesos.

El GIL es controvertido porque evita que los programas CPython multiproceso aprovechen al máximo los sistemas multiprocesador en ciertas situaciones. Tenga en cuenta que el bloqueo potencial o Las operaciones de larga duración, como E / S, procesamiento de imágenes y procesamiento de números NumPy, ocurren fuera del GIL. Por lo tanto, solo en los programas multiproceso que pasan mucho tiempo dentro del GIL, interpretando el código de bytes CPython, el GIL se convierte en un cuello de botella.

Python tiene un GIL en lugar de un bloqueo de grano fino por varias razones:

  • Es más rápido en el caso de un solo subproceso.

  • Es más rápido en el caso de subprocesos múltiples para programas enlazados a E / S.

  • Es más rápido en el caso de subprocesos múltiples para programas enlazados a cpu que lo hacen su trabajo intensivo en computación en bibliotecas C.

  • Hace Extensiones de C más fáciles de escribir: no habrá cambio de subprocesos de Python excepto donde permita que suceda (es decir, entre las macros Py_BEGIN_ALLOW_THREADS y Py_END_ALLOW_THREADS).

  • Facilita el empaquetado de bibliotecas C. No tiene que preocuparse por la seguridad de los subprocesos. Si la biblioteca no es segura para los subprocesos, simplemente mantenga el GIL bloqueado mientras lo llama.

El GIL puede ser lanzado por extensiones C. La biblioteca estándar de Python libera el GIL alrededor de cada llamada de E / S de bloqueo. Por lo tanto, el GIL no tiene consecuencias para el rendimiento de los servidores vinculados a E / S. Por lo tanto, puede crear servidores de red en Python utilizando procesos (bifurcación), subprocesos o E / S asíncronas, y el GIL no se interpondrá en su camino.

Las bibliotecas numéricas en C o Fortran se pueden llamar de manera similar con el GIL lanzado. Mientras su extensión C espera que se complete una FFT, el intérprete ejecutará otros subprocesos de Python.Por lo tanto, un GIL es más fácil y rápido que el bloqueo de grano fino también en este caso. Esto constituye la mayor parte del trabajo numérico. La extensión NumPy libera GIL siempre que sea posible.

Los subprocesos suelen ser una mala forma de escribir la mayoría de los programas de servidor. Si la carga es baja, la bifurcación es más fácil. Si la carga es alta, la E / S asincrónica y la programación dirigida por eventos (por ejemplo, usando el marco Twisted de Python) es mejor. La única excusa para usar subprocesos es la falta de os.fork en Windows.

El GIL es un problema si, y solo si, está haciendo un trabajo intensivo de CPU en Python puro. Aquí puede obtener un diseño más limpio utilizando procesos y paso de mensajes (por ejemplo, mpi4py). También hay un módulo de «procesamiento» en Python cheese shop, que proporciona a los procesos la misma interfaz que los subprocesos (es decir, reemplace el subproceso por el procesamiento).

Los subprocesos se pueden utilizar para mantener la capacidad de respuesta de una GUI independientemente del GIL. Si el GIL afecta su rendimiento (ver la discusión anterior), puede dejar que su hilo genere un proceso y esperar a que termine.

Comentarios

  • Suena como uvas amargas para mí. Python no puede ‘ t hacer subprocesos correctamente, por lo que inventa razones por las que los subprocesos son innecesarios o incluso malos. » Si la carga es bajo, fo rking es más fácil «, ¿en serio? Y el GIL es » más rápido » para todos esos casos solo si insiste en usar GC de recuento de referencias.
  • s/RPython/PyPy/g. @MichaelBorgwardt Dar razones a favor de GIL es el punto de la pregunta, ¿no es ‘ verdad? Aunque estoy de acuerdo en que algunos de los contenidos de esta respuesta (a saber, la discusión de alternativas) no viene al caso. Y para bien o para mal, ahora es casi imposible deshacerse del recuento; está profundamente arraigado en toda la API y la base de código; es ‘ casi imposible deshacerse de él sin volver a escribir la mitad del código y romper todo el código externo.
  • Don ‘ No olvide la biblioteca multiprocessing – estándar desde 2.6. Es ‘ s grupos de trabajadores son una abstracción muy hábil para algunos tipos simples de paralelismo.
  • @alcalde Solo si no ‘ no sé lo que ‘ estás haciendo y / o no ‘ no quieres que tus subprocesos funcionen de forma cooperativa / comunicar. De lo contrario, ‘ es un verdadero dolor de cabeza, especialmente si se considera la sobrecarga de iniciar un nuevo proceso en algunos sistemas operativos. Tenemos servidores con 32 núcleos, por lo que para utilizarlos completamente en CPython, ‘ d necesito 32 procesos. Esa ‘ no es una » buena solución » es ‘ sa hack para evitar las deficiencias de CPython ‘.
  • El hecho de que existan subprocesos en plataformas distintas de Windows debería ser una prueba suficiente de que la bifurcación no es ‘ t adecuado en cada situación.

Responder

Primero apagado: Python no tiene un GIL. Python es un lenguaje de programación. Un lenguaje de programación es un conjunto de reglas y restricciones matemáticas abstractas. No hay nada en la Especificación del lenguaje Python que diga que debe haber un GIL.

Hay muchas implementaciones diferentes de Python. Algunas tienen una GIL, otras no.

Una explicación simple para tener una GIL es que escribir código concurrente es difícil. Al colocar un candado gigante alrededor de su código, lo obliga a ejecutarse siempre en serie. ¡Problema resuelto!

En CPython, en particular, un objetivo importante es facilitar la extensión del intérprete con complementos escritos en C. Nuevamente, escribir código concurrente es difícil, así que garantizando que no habrá concurrencia, facilita la escritura de extensiones para el intérprete. Además, muchas de esas extensiones son simples envoltorios de bibliotecas existentes que pueden no haberse escrito teniendo en cuenta la simultaneidad.

Comentarios

  • Eso ‘ es el mismo argumento que Java ‘ s falta de tipos numéricos sin firmar – los desarrolladores piensan que todos los demás son más tontos que ellos …
  • @Basic – créalo o no, incluso cuando ‘ no eres realmente tonto, resulta que tener un lenguaje que hace suposiciones simplificadoras que significan que no ‘ No pensar en ciertas cosas para que funcionen sigue siendo algo útil.CPython es excelente para ciertas cosas, incluidas las aplicaciones multiproceso simples (donde el programa está vinculado a IO, que muchos lo están, y por lo tanto, el GIL no ‘ t importa), porque las decisiones de diseño que tomaron la mejor solución de GIL también facilita la programación de esas aplicaciones, en particular el hecho de que admite operaciones atómicas en colecciones .
  • @Jules Sí, ‘ es muy útil hasta que necesite esas capacidades. cpython ‘ s » preferida » solución de » simplemente escríbalo en otro lenguaje como c ++ » entonces significa que pierde todos los beneficios de Python. Si ‘ está escribiendo la mitad de su código en c ++, ¿por qué empezar desde Python? Claro, para proyectos pequeños de API / pegamento es ‘ rápido y fácil, y para ETL es ‘ insuperable, pero ‘ s no es adecuado para nada que requiera levantar objetos pesados. Igual que usar Java para hablar con el hardware … Es ‘ casi cómicos los obstáculos que tienes que atravesar.
  • @Basic Uno de Python ‘ sy, por lo tanto, en una extensión amplia, la filosofía central de CPython ‘ es hacer que la tecnología » sea amigable y fácil de usar «. La programación paralela sin bloqueo global no es eso. Teniendo en cuenta que hay muchas implementaciones sin GIL, tiene sentido proporcionar al menos una implementación que lo tenga.
  • Dice » que tiene sentido al menos proporcionar una implementación que lo tiene. » me gusta ‘ es la conclusión obvia, pero no en otro idioma ‘ Soy consciente de que obstaculiza a sus desarrolladores de esta manera, por lo que no puede ‘ ser tan obvio.

Respuesta

¿Cuál es el propósito de un GIL?

La documentación de CAPI tiene esto que decir sobre el tema:

El intérprete de Python no es completamente seguro para subprocesos . Para admitir programas de Python de subprocesos múltiples, existe un bloqueo global, llamado bloqueo de intérprete global o GIL, que debe ser mantenido por el subproceso actual antes de que pueda acceder de forma segura a los objetos de Python. Sin el bloqueo, incluso las operaciones más simples podrían causar problemas en un programa de subprocesos múltiples: por ejemplo, cuando dos subprocesos incrementan simultáneamente el recuento de referencias del mismo objeto, el recuento de referencias podría terminar incrementándose solo una vez en lugar de dos.

En otras palabras, el GIL previene la corrupción del estado. Los programas de Python nunca deberían producir una falla de segmentación, porque solo se permiten operaciones seguras de memoria. El GIL extiende esta garantía a los programas de subprocesos múltiples.

¿Cuáles son las alternativas?

Si el propósito de la GIL es proteger al estado de la corrupción, entonces una alternativa obvia es bloquear en un grano mucho más fino; quizás a nivel de objeto. El problema con esto es que, aunque se ha demostrado que aumenta el rendimiento de los programas de subprocesos múltiples, tiene más sobrecarga y los programas de un solo subproceso sufren como resultado.

Comentarios

  • Sería genial permitir que un usuario ejecute un programa con una opción de intérprete que reemplace el gil por un bloqueo de grano fino, y de alguna manera saber, de una manera de solo lectura, si el proceso actual se generó con o sin gil.
  • A pesar de GIL, logré producir una falla de segmentación en un programa multiproceso debido al uso descuidado del módulo pyodbc. Por lo tanto, » nunca debería producir un error de segmentación » es una falacia.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *