Inferencia segura para subprocesos con modelos YOLO#
Para ejecutar la inferencia de Ultralytics YOLO de forma segura entre subprocesos de Python, crea una instancia de modelo YOLO independiente dentro de cada subproceso en lugar de compartir una entre ellos. Compartir un único modelo provoca condiciones de carrera que corrompen su estado interno y generan resultados impredecibles, porque el módulo threading de Python ejecuta los subprocesos simultáneamente sobre el mismo objeto. Esta guía explica por qué falla el uso compartido, muestra el patrón seguro por subproceso y trata el decorador ThreadingLocked para los casos en los que tengas que compartir una instancia.
Ve directamente a por qué falla compartir un modelo, al patrón seguro para subprocesos o al decorador [ThreadingLocked].
Watch: How to Perform Thread Safe Inference with Ultralytics YOLO Models in Python | Multi-Threading 🚀
Cómo funcionan los subprocesos de Python#
Los subprocesos de Python son una forma de paralelismo que permite que tu programa ejecute varias operaciones a la vez. Sin embargo, el Bloqueo global del intérprete (GIL) de Python implica que solo un subproceso puede ejecutar bytecode de Python cada vez.
Aunque esto parezca una limitación, los subprocesos pueden proporcionar concurrencia, especialmente en operaciones limitadas por E/S o al utilizar operaciones que liberan el GIL, como las que realizan las bibliotecas C subyacentes de YOLO.
El peligro de compartir instancias de modelos#
Crear una instancia de un modelo YOLO fuera de los subprocesos y compartirla entre varios puede provocar condiciones de carrera, en las que el estado interno del modelo se modifica de forma incoherente debido a accesos simultáneos. Esto resulta especialmente problemático cuando el modelo o sus componentes mantienen un estado que no está diseñado para ser seguro para subprocesos.
Ejemplo no seguro para subprocesos: una única instancia del modelo#
Al utilizar subprocesos 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 YOLO26 entre varios subprocesos.
# Unsafe: Sharing a single model instance across threads
from threading import Thread
from ultralytics import YOLO
# Instantiate the model outside the thread
shared_model = YOLO("yolo26n.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, varios subprocesos utilizan shared_model, lo que puede producir resultados impredecibles porque varios subprocesos podrían ejecutar predict simultáneamente.
Ejemplo seguro: una instancia dedicada por subproceso#
Varias instancias de modelos independientes funcionan correctamente siempre que cada subproceso sea propietario de su instancia y nunca la comparta con otro subproceso. No importa que las instancias siguientes se creen antes de iniciar los subprocesos; el único patrón no seguro es compartir una instancia entre subprocesos:
# Safe: each thread uses its own dedicated model instance
from threading import Thread
from ultralytics import YOLO
# Instantiate one model per thread
model_1 = YOLO("yolo26n.pt")
model_2 = YOLO("yolo26n.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
# Each thread uses a separate, dedicated model instance
Thread(target=predict, args=(model_1, "image1.jpg")).start()
Thread(target=predict, args=(model_2, "image2.jpg")).start()Como cada subproceso trabaja con su propia instancia dedicada, no existe un estado de modelo compartido que los subprocesos puedan corromper. Crear el modelo dentro de cada subproceso, como se muestra a continuación, es simplemente la forma más sencilla de garantizar que una instancia no se comparta accidentalmente.
Inferencia segura para subprocesos#
Para realizar inferencias seguras para subprocesos, debes crear una instancia independiente del modelo YOLO dentro de cada subproceso. Esto garantiza que cada subproceso tenga su propia instancia de modelo aislada y elimina el riesgo de condiciones de carrera.
Ejemplo seguro para subprocesos#
Así puedes crear un modelo YOLO dentro de cada subproceso para realizar inferencias paralelas de forma segura:
# Safe: Instantiating a single model inside each thread
from threading import Thread
from ultralytics import YOLO
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("yolo26n.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 subproceso crea su propia instancia YOLO. Esto evita que un subproceso interfiera en el estado del modelo de otro y garantiza que cada subproceso realice inferencias de forma segura y sin interacciones inesperadas con los demás.
Uso del decorador ThreadingLocked#
Ultralytics proporciona un decorador ThreadingLocked que puedes utilizar para garantizar la ejecución segura para subprocesos de las funciones. Este decorador utiliza un bloqueo para garantizar que solo un subproceso pueda ejecutar la función decorada en cada momento.
from ultralytics import YOLO
from ultralytics.utils import ThreadingLocked
# Create a model instance
model = YOLO("yolo26n.pt")
# Decorate the prediction function to make it thread-safe
@ThreadingLocked()
def thread_safe_predict(image_path):
"""Thread-safe prediction using a shared model instance."""
results = model.predict(image_path)
return results
# Now you can safely call this function from multiple threadsEl decorador ThreadingLocked resulta especialmente útil cuando necesitas compartir una instancia de modelo entre subprocesos, pero quieres garantizar que solo uno pueda acceder a ella cada vez.
Compartir una instancia de modelo bloqueada ahorra memoria frente a cargar un modelo en cada subproceso, pero reduce la concurrencia porque los subprocesos se serializan en el bloqueo y esperan su turno. Prefiere el patrón por subproceso cuando tengas memoria disponible y quieras obtener el máximo paralelismo, y utiliza ThreadingLocked cuando la memoria del modelo sea el cuello de botella.
Conclusión#
Al utilizar modelos YOLO con threading de Python, asigna a cada subproceso su propia instancia de modelo dedicada y no compartas nunca una instancia entre subprocesos. Crear el modelo dentro del subproceso que lo utiliza es la forma más sencilla de garantizarlo, evitar condiciones de carrera y mantener la fiabilidad de tus tareas de inferencia.
Para escenarios más avanzados y para optimizar aún más el rendimiento de tus inferencias multihilo, considera utilizar paralelismo basado en procesos con multiprocessing o aprovechar una cola de tareas con procesos de trabajo dedicados.
Preguntas frecuentes#
Para evitar condiciones de carrera al utilizar modelos Ultralytics YOLO en un entorno Python multihilo, crea un modelo YOLO independiente dentro de cada subproceso. Esto garantiza que cada subproceso tenga su propia instancia de modelo aislada y evita modificaciones simultáneas del estado del modelo.
Ejemplo:
from threading import Thread from ultralytics import YOLO def thread_safe_predict(image_path): """Predict on an image in a thread-safe manner.""" local_model = YOLO("yolo26n.pt") results = local_model.predict(image_path) # Process results Thread(target=thread_safe_predict, args=("image1.jpg",)).start() Thread(target=thread_safe_predict, args=("image2.jpg",)).start()Para obtener más información sobre cómo garantizar la seguridad para subprocesos, visita Inferencia segura para subprocesos con modelos YOLO.
Para ejecutar inferencias multihilo de modelos YOLO de forma segura en Python, sigue estas prácticas recomendadas:
- Crea los modelos YOLO dentro de cada subproceso en lugar de compartir una única instancia entre varios subprocesos.
- Utiliza el módulo
multiprocessingde Python para el procesamiento paralelo y evitar problemas relacionados con el Bloqueo global del intérprete (GIL). - Recuerda que las bibliotecas C subyacentes de YOLO (PyTorch, OpenCV) liberan automáticamente el GIL durante los cálculos intensivos, por lo que los subprocesos aún pueden ejecutar inferencias simultáneamente.
- Considera utilizar el decorador
ThreadingLockedpara instancias de modelos compartidas cuando la memoria sea un factor limitante.
Ejemplo de creación de instancias de modelos segura para subprocesos:
from threading import Thread from ultralytics import YOLO def thread_safe_predict(image_path): """Runs inference in a thread-safe manner with a new YOLO model instance.""" local_model = YOLO("yolo26n.pt") results = local_model.predict(image_path) # Process results # Initiate multiple threads Thread(target=thread_safe_predict, args=("image1.jpg",)).start() Thread(target=thread_safe_predict, args=("image2.jpg",)).start()Para obtener más contexto, consulta la sección Inferencia segura para subprocesos.
Cada subproceso debe tener su propia instancia del modelo YOLO para evitar condiciones de carrera. Cuando se comparte una única instancia entre varios subprocesos, los accesos simultáneos pueden provocar un comportamiento impredecible y modificaciones del estado interno del modelo. Al utilizar instancias independientes, garantizas el aislamiento entre subprocesos y haces que tus tareas multihilo sean fiables y seguras.
Para obtener instrucciones detalladas, consulta las secciones Ejemplo no seguro para subprocesos: una única instancia del modelo y Ejemplo seguro para subprocesos.
El Bloqueo global del intérprete (GIL) de Python solo permite que un subproceso ejecute bytecode de Python cada vez, lo que puede limitar el rendimiento de las tareas multihilo limitadas por la CPU. Sin embargo, en operaciones limitadas por E/S o procesos que utilizan bibliotecas que liberan el GIL, como las bibliotecas C subyacentes de YOLO, aún puedes conseguir concurrencia. Para mejorar el rendimiento, considera utilizar paralelismo basado en procesos con el módulo
multiprocessingde Python.Para obtener más información sobre los subprocesos en Python, consulta la sección Cómo funcionan los subprocesos de Python.
Sí, utilizar el módulo
multiprocessingde Python es más seguro y, a menudo, más eficiente para ejecutar inferencias de modelos YOLO en paralelo. El paralelismo basado en procesos crea espacios de memoria independientes, evita el Bloqueo global del intérprete (GIL) y reduce el riesgo de problemas de concurrencia. Cada proceso funciona de forma independiente con su propia instancia del modelo YOLO.Para obtener más información sobre el paralelismo basado en procesos con modelos YOLO, consulta la página sobre Inferencia segura para subprocesos.