Saltar al contenido

Inferencia a prueba de hilos con modelos YOLO

Ejecutar los modelos YOLO en un entorno multihilo requiere una cuidadosa consideración para garantizar la seguridad de los hilos. Python's threading te permite ejecutar varios subprocesos simultáneamente, pero cuando se trata de utilizar modelos YOLO en estos subprocesos, hay que tener en cuenta importantes cuestiones de seguridad. Esta página te guiará en la creación de la inferencia de modelos YOLO a prueba de hilos.

Comprender el roscado Python

Python Los hilos son una forma de paralelismo que permite a tu programa ejecutar varias operaciones a la vez. Sin embargo, Python's Global Interpreter Lock (GIL) significa que sólo un hilo puede ejecutar Python bytecode a la vez.

Ejemplos de un solo hilo frente a varios hilos

Aunque esto parezca una limitación, los subprocesos pueden proporcionar concurrencia, especialmente para operaciones de E/S o cuando se utilizan operaciones que liberan el GIL, como las que realizan las bibliotecas C subyacentes de YOLO.

El peligro de las instancias modelo compartidas

Instanciar un modelo YOLO fuera de tus subprocesos y compartir esta instancia entre varios subprocesos puede provocar condiciones de carrera, en las que el estado interno del modelo se modifica de forma incoherente debido a accesos concurrentes. Esto es especialmente problemático cuando el modelo o sus componentes contienen un estado que no está diseñado para ser seguro para los subprocesos.

Ejemplo no seguro: Una sola instancia del modelo

Cuando utilices hilos en Python, es importante reconocer los patrones que pueden provocar problemas de concurrencia. Esto es lo que debes evitar: compartir una única instancia del modelo YOLO entre varios subprocesos.

# Unsafe: Sharing a single model instance across threads
from ultralytics import YOLO
from threading import Thread

# Instantiate the model outside the thread
shared_model = YOLO("yolov8n.pt")


def predict(image_path):
    """Predicts objects in an image using a preloaded YOLO model, take path string to image as argument."""
    results = shared_model.predict(image_path)
    # Process results


# Starting threads that share the same model instance
Thread(target=predict, args=("image1.jpg",)).start()
Thread(target=predict, args=("image2.jpg",)).start()

En el ejemplo anterior, el shared_model es utilizado por varios subprocesos, lo que puede dar lugar a resultados impredecibles porque predict podría ser ejecutado simultáneamente por varios hilos.

Ejemplo no seguro: Múltiples instancias del modelo

Del mismo modo, aquí tienes un patrón inseguro con varias instancias del modelo YOLO :

# Unsafe: Sharing multiple model instances across threads can still lead to issues
from ultralytics import YOLO
from threading import Thread

# Instantiate multiple models outside the thread
shared_model_1 = YOLO("yolov8n_1.pt")
shared_model_2 = YOLO("yolov8n_2.pt")


def predict(model, image_path):
    """Runs prediction on an image using a specified YOLO model, returning the results."""
    results = model.predict(image_path)
    # Process results


# Starting threads with individual model instances
Thread(target=predict, args=(shared_model_1, "image1.jpg")).start()
Thread(target=predict, args=(shared_model_2, "image2.jpg")).start()

Aunque haya dos instancias del modelo separadas, sigue existiendo el riesgo de problemas de concurrencia. Si la implementación interna de YOLO no es seguro para los subprocesos, el uso de instancias separadas podría no evitar las condiciones de carrera, especialmente si estas instancias comparten recursos o estados subyacentes que no son locales para los subprocesos.

Inferencia segura de hilos

Para realizar una inferencia a prueba de hilos, debes instanciar un modelo YOLO independiente dentro de cada hilo. Esto garantiza que cada subproceso tenga su propia instancia aislada del modelo, eliminando el riesgo de condiciones de carrera.

Ejemplo de hilo seguro

He aquí cómo instanciar un modelo YOLO dentro de cada hilo para una inferencia paralela segura:

# Safe: Instantiating a single model inside each thread
from ultralytics import YOLO
from threading import Thread


def thread_safe_predict(image_path):
    """Predict on an image using a new YOLO model instance in a thread-safe manner; takes image path as input."""
    local_model = YOLO("yolov8n.pt")
    results = local_model.predict(image_path)
    # Process results


# Starting threads that each have their own model instance
Thread(target=thread_safe_predict, args=("image1.jpg",)).start()
Thread(target=thread_safe_predict, args=("image2.jpg",)).start()

En este ejemplo, cada hilo crea su propio YOLO instancia. Esto impide que cualquier hilo interfiera con el estado del modelo de otro, garantizando así que cada hilo realice la inferencia de forma segura y sin interacciones inesperadas con los demás hilos.

Conclusión

Si utilizas los modelos YOLO con Python's threadinginstanciar siempre tus modelos dentro del subproceso que los utilizará para garantizar la seguridad del subproceso. Esta práctica evita las condiciones de carrera y garantiza que tus tareas de inferencia se ejecuten de forma fiable.

Para escenarios más avanzados y para optimizar aún más el rendimiento de tu inferencia multihilo, considera la posibilidad de utilizar el paralelismo basado en procesos con multiprocessing o aprovechando una cola de tareas con procesos de trabajadores dedicados.



Creado 2023-11-12, Actualizado 2024-05-03
Autores: glenn-jocher (2)

Comentarios