es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Cómo afecta “GIL” a Python asyncio `run_in_executor` con tareas vinculadas a E/S?

En relación a este código ejemplo de Python asyncio run_in_executor:

import asyncio
import concurrent.futures

def blocking_io():
    # Las operaciones de archivo (como el registro) pueden bloquear
    # el bucle de eventos: ejecútalas en un grupo de subprocesos.
    with open('/dev/urandom', 'rb') as f:
        return f.read(100)

def cpu_bound():
    # Las operaciones intensivas en CPU bloquearán el bucle de eventos:
    # en general, es preferible ejecutarlas en un grupo de procesos.
    return sum(i * i for i in range(10 ** 7))

async def main():
    loop = asyncio.get_running_loop()

## Opciones:

# 1. Ejecutar en el grupo de subprocesos predeterminado del bucle:
result = await loop.run_in_executor(
    None, blocking_io)
print('Grupo de subprocesos predeterminado:', result)

# 3. Ejecutar en un grupo de procesos personalizado:
with concurrent.futures.ProcessPoolExecutor() as pool:
    result = await loop.run_in_executor(
        pool, cpu_bound)
    print('Grupo de procesos personalizado:', result)

asyncio.run(main())

El ejemplo (en comentarios) recomienda ejecutar la función de E/S enlazada utilizando el ThreadPoolExecutor y la función de CPU enlazada utilizando el ProcessPoolExecutor. Quiero verificar mi comprensión de las razones detrás de esto con tres preguntas:

  1. Estas recomendaciones no son realmente recomendaciones, ya que de lo contrario el bucle de eventos se bloqueará. En consecuencia, perderemos el beneficio principal de la programación de eventos, ¿correcto?

  2. Ejecutar la tarea de enlace de E/S en un hilo separado requiere la siguiente suposición: ¿La llamada de E/S liberará el GIL? De lo contrario, el sistema operativo no podrá cambiar de contexto entre el bucle de eventos y este nuevo hilo separado.

  3. Si la respuesta al punto 2 es sí, ¿cómo saber con certeza si una llamada de E/S libera el GIL o no?

Tags:  , , ,

Answer

  1. Avatar for davy.ai
    1. Sí, eso es correcto. El objetivo principal de utilizar asyncio es evitar bloquear el bucle de eventos, por lo que es importante ejecutar funciones bloqueantes en hilos o procesos separados para evitar que el bucle de eventos se bloquee.
    2. Sí, eso también es correcto. Para que el bucle de eventos se ejecute sin problemas, necesita poder cambiar de contexto entre tareas. Si una tarea retiene el GIL (Bloqueo Global del Intérprete), evitará que el bucle de eventos ejecute otras tareas concurrentemente.
    3. En general, las llamadas de E/S que involucran llamadas al sistema (como leer desde un archivo, recibir datos de un socket de red, etc.) liberarán el GIL. Sin embargo, siempre es mejor probar y verificar el comportamiento en su caso de uso específico para asegurarse de que la llamada no retenga innecesariamente el GIL. Puede utilizar herramientas de perfilado o inspeccionar el código fuente de CPython para determinar si una llamada de E/S específica libera o no el GIL.

Comments are closed.