
Compartir:
Max es un defensor de los desarrolladores de Python e ingeniero de software interesado en las API de comunicaciones, el aprendizaje automático, la experiencia de los desarrolladores y el baile. Su formación es en Física, pero ahora trabaja en proyectos de código abierto y hace cosas para mejorar la vida de los desarrolladores.
Eliminación del GIL de Python: ¡Está ocurriendo!
Tiempo de lectura: 9 minutos
Introducción
El Bloqueo Global del Intérprete (GIL) en Python es un mecanismo de bloqueo que asegura que sólo un hilo puede ejecutar código Python a la vez, incluso en procesadores multinúcleo. Aunque esto tiene algunas ventajas, significa que no es fácil aprovechar múltiples núcleos de CPU para el procesamiento paralelo en Python.
Recientemente, el Consejo Director de Python ha indicado que tiene la intención de aprobar PEP 703una propuesta para crear una versión de CPython, el intérprete de Python más popular, sin el GIL. Esto tiene implicaciones de gran alcance para el desarrollo de Python en el futuro, por lo que vale la pena entender lo que está pasando.
En este post, vamos a discutir por qué tenemos el GIL en Python, por qué podríamos querer eliminarlo, y el trabajo que se está haciendo actualmente para llegar allí.
¿Por qué tenemos el GIL?
El GIL simplifica la gestión de hilos y protege contra condiciones de carrera y corrupción de memoria en Python, facilitando a los desarrolladores la escritura de código concurrente de forma segura. Se introdujo cuando se añadió soporte para hilos a Python en los primeros días del lenguaje.
Compatibilidad
Muchos paquetes de Python (y el intérprete principal de Python, CPython) hacen un uso intensivo de las extensiones de C, que no son inherentemente seguras para los hilos. Es posible que varios hilos intenten acceder a los mismos recursos, lo que puede tener efectos muy negativos. El GIL hizo más segura la creación y el uso de extensiones C, lo que a su vez facilitó que los desarrolladores de los 90 empezaran a utilizar Python para crear software, impulsando su adopción.
Recogida de basura y recuento de referencias
La otra razón importante tiene que ver con cómo Python gestiona la recolección de basura. La recolección de basura es un proceso automático de gestión de memoria en el que el intérprete rastrea y reclama la memoria ocupada por objetos que ya no son referenciados o alcanzables en el programa. En Python, hay dos métodos principales de recolección de basura, pero el más prominente es un proceso llamado conteo de referencias.
El recuento de referencias en Python es una forma eficaz de gestionar la memoria y garantizar que los recursos se liberan cuando ya no se utilizan, lo que ayuda a evitar fugas de memoria en los programas Python. El conteo de referencias funciona así:
Cada objeto lleva la cuenta del número de referencias que apuntan a él.
Cuando la cuenta de referencias de un objeto cae a cero, significa que no hay más referencias a ese objeto en el programa.
Esto indica que el objeto ya no es necesario.
El sistema de gestión de memoria de Python recupera automáticamente la memoria ocupada por el objeto, borrándolo de hecho.
Sin el GIL, varios subprocesos que se ejecutan simultáneamente podrían manipular los recuentos de referencia de los objetos al mismo tiempo, dando lugar a condiciones de carrera y corrupción de memoria. El GIL actúa como una salvaguarda, permitiendo que sólo un hilo ejecute código de bytes de Python a la vez, evitando estos problemas potenciales.
¿Por qué queremos suprimir el GIL?
Aunque la GIL puede simplificar la escritura de código sin preocuparse demasiado por la seguridad de los hilos, también puede limitar las ganancias de rendimiento que se pueden esperar del uso de múltiples hilos en tareas limitadas a la CPU. Para tareas de E/S, como peticiones HTTP u operaciones con archivos, la GIL no tiene tanto impacto, por lo que aún puedes beneficiarte del multihilo en esos casos. Así que, si estás usando hilos en Python para enviar muchas peticiones HTTP, eso podría mejorar el rendimiento, pero si estás usando hilos para hacer muchas tareas intensivas de CPU, probablemente no.
Si se eliminara el GIL, podríamos obtener los beneficios de rendimiento de los hilos al realizar tareas intensivas de CPU que actualmente no obtenemos en CPython.
¿Qué tienen de malo otros métodos para mejorar la concurrencia?
Los hilos y el procesamiento asíncrono con asyncio son ambos métodos para mejorar el rendimiento, pero sólo funcionan para operaciones ligadas a E/S. Sin embargo, hay un par de métodos que funcionan para operaciones ligadas a la CPU.
Python soporta el multiprocesamiento a través del módulo multiprocessing móduloy también es posible escribir código similar a Python utilizando Cython para mejorar el rendimiento. Ambos pueden mejorar el rendimiento de las operaciones limitadas a la CPU, pero tienen sus desventajas.
Multiprocesamiento
El módulo multiprocessing le permite utilizar varios núcleos de CPU mediante la creación de procesos separados, cada uno con su propio intérprete de Python y espacio de memoria. Esto es eficaz para las tareas limitadas a la CPU, ya que evita el GIL, que opera en hilos, y le permite utilizar los múltiples núcleos de su máquina para una verdadera ejecución paralela.
Desafortunadamente, la creación de múltiples procesos tiene una mayor sobrecarga de recursos en comparación con los hilos, lo que resulta en un mayor uso de memoria y tiempo de arranque. También es más lento y complicado comunicarse entre procesos que entre hilos. Por último, los procesos no comparten memoria por defecto, lo que hace más difícil compartir datos entre ellos y sincronizarlos.
Cython
Cython es un superconjunto de Python que te permite escribir código similar a Python con algunas anotaciones extra para mejorar el rendimiento. Es una forma de hacer que tu código Python se ejecute más rápido sin tener que abandonar completamente el lenguaje Python. Cython puede hacer que tu código se ejecute más rápidamente optimizando las partes críticas mientras mantiene la facilidad y legibilidad del lenguaje Python.
Sin embargo, Cython tiene más curva de aprendizaje que Python y requiere conocimientos de construcciones en lenguaje C, lo que lo hace menos accesible. Escribir y mantener código Cython también puede ser más complejo y propenso a errores que escribir código Python puro, sobre todo cuando se reescribe código escrito originalmente en Python.
Por lo tanto, hay un par de métodos para mejorar el rendimiento, pero ambos tienen desventajas considerables. Esto demuestra por qué ha habido mucho interés en eliminar el GIL de Python.
Intentos anteriores y por qué no tuvieron éxito
Varios proyectos han intentado eliminar el GIL de CPython en el pasado, con cierto éxito, por ejemplo, el proyecto Gilectomía por ejemplo. Sin embargo, los esfuerzos para eliminar el GIL suelen venir con algunos inconvenientes:
Es una tarea compleja con el potencial de introducir errores e inestabilidad en el intérprete CPython.
Pueden romper el código Python existente y las bibliotecas que dependen del GIL.
Pueden aumentar el uso de memoria.
Las extensiones de Python basadas en C necesitarían cambios significativos.
El principal inconveniente, sin embargo, es que los antiguos proyectos sin GIL en realidad hacían que el código de un solo hilo fuera más lento que con el GIL, lo que significa que si no estabas usando multihilo para acelerar las operaciones limitadas por la CPU, tu código funcionaría peor que con CPython normal, lo que no es aceptable.
PEP 703que el Consejo Director de Python tiene intención de aprobarcambiará todo esto, y ha obtenido un amplio apoyo. Así que, ¡hablemos de ello!
¿De qué trata PEP 703? Python sin GIL, de la forma correcta
PEP 703 propone una forma de eliminar el GIL de Python, pero consigue evitar el impacto en el rendimiento del código no multihilo que afectó a otros proyectos Python sin GIL. El Consejo Directivo de Python indicó el 28 de julio que tienen la intención de aprobar el PEP, allanando el camino para que Python sin GIL entre en la corriente principal y eventualmente se convierta en el valor por defecto en Python.
¿Cómo funciona?
La principal técnica importante que permite eliminar el GIL sin afectar al rendimiento del código monohilo es el recuento de referencias sesgado.
En el recuento de referencias sesgado, los objetos a los que accede un único hilo tienen sus recuentos de referencias gestionados de forma más eficiente que aquellos a los que acceden varios hilos, lo que proporciona una mejora de rendimiento para los programas de un único hilo en los que la mayoría de los objetos son utilizados por un único hilo. Esto significa que el rendimiento de Python sin GIL que utiliza esta técnica en operaciones de un único subproceso es comparable al de Python normal, mientras que los programas Python con varios subprocesos limitados por la CPU son mucho más rápidos.
El proyecto también hace que el Python sin GIL sea más eficiente, aplazando el proceso de recuento de referencias para los objetos del módulo de nivel superior que no es probable que cambien en un programa Python, así como designando algunos objetos como "inmortales" - objetos como None nunca se destruyen, por lo que no necesitan ser contados. También hay cambios en la forma de asignar memoria a los objetos de Python, lo que facilita la asignación de memoria de forma segura para los hilos.
Me parece estupendo. Así que la pregunta es: ¿cuándo tendremos acceso a Python sin GIL?
Cómo se implementará No-GIL Python
El Python Steering Council ha descrito las tres etapas que imaginan que seguirá el Python sin GIL para convertirse en la versión por defecto de CPython:
Corto plazo: En la versión 3.13 (o posiblemente 3.14) de Python, se planea introducir la compilación no-GIL como modo experimental. Este modo se utilizará para obtener información sobre su uso, diseño de la API, empaquetado y distribución.
A medio plazo: Una vez que tengan la certeza de que la comunidad apoya suficientemente la versión sin GIL, se convertirá en una opción compatible, pero no predeterminada. Se fijará una fecha/versión objetivo para convertirla en la opción por defecto, y el calendario dependerá de factores como la compatibilidad de la API y la disposición de la comunidad. Estiman que esta fase puede durar uno o dos años, pero podría alargarse más.
A largo plazo: El objetivo final es que la versión sin GIL se convierta en la predeterminada, eliminando el GIL sin alterar la compatibilidad con versiones anteriores. Calculan que se podría tardar hasta 5 años en alcanzar esta fase. A lo largo de este proceso, se realizarán evaluaciones periódicas para garantizar que se avanza y se evitan problemas de retrocompatibilidad: nadie quiere ver otro cambio como el calvario de 10 años que supuso la introducción de Python 3...
Conclusión
Python está a punto de experimentar un cambio significativo: la (posible) eliminación del Bloqueo Global del Intérprete (GIL), que podría mejorar enormemente la capacidad de Python para utilizar varios núcleos de procesador y mejorar el rendimiento. El GIL, que solía desempeñar el papel de una red de seguridad, ha frenado el potencial de Python para utilizar plenamente los procesadores modernos para tareas ligadas a la CPU.
A diferencia de intentos anteriores, PEP 703 ofrece una solución inteligente, incorporando recuento de referencias sesgado, recuento de referencias diferido y objetos inmortales, entre otras técnicas. Garantiza que los programas Python de un solo hilo no se ralenticen, a la vez que da un empujón a los que utilizan varios hilos para tareas que consumen mucha CPU.
Este cambio se producirá en tres pasos: primero, con un modo de compilación experimental; después, como opción compatible; y, por último, como configuración predeterminada, posiblemente en los próximos cinco años. El objetivo es que esta transición sea fluida y evite problemas de compatibilidad, aportando más potencia y eficiencia a Python.
Si tienes alguna pregunta sobre este artículo, no dudes en ponerte en contacto con nosotros en nuestro Slack de la comunidad de Vonage y pregúntanos allí o enviándonos un mensaje en X, antes conocido como Twitter.
Si estás interesado en usar API para cualquier cosa relacionada con las comunicaciones, como el envío de SMS, llamadas de voz, videoconferencias, autenticación de 2 factores, prevención de fraudes y más, puedes inscribirte para obtener una cuenta de desarrollador de Vonage gratis (¡con créditos gratis!).
Compartir:
Max es un defensor de los desarrolladores de Python e ingeniero de software interesado en las API de comunicaciones, el aprendizaje automático, la experiencia de los desarrolladores y el baile. Su formación es en Física, pero ahora trabaja en proyectos de código abierto y hace cosas para mejorar la vida de los desarrolladores.