Skip to content

Inférence sécurisée avec les modèles YOLO

L'exécution des modèles YOLO dans un environnement multithread nécessite une attention particulière pour assurer la sécurité des threads. Python's threading te permet d'exécuter plusieurs threads simultanément, mais lorsqu'il s'agit d'utiliser les modèles YOLO à travers ces threads, il y a d'importantes questions de sécurité à prendre en compte. Cette page te guidera dans la création d'une inférence de modèle YOLO sécurisée pour les threads.

Comprendre Python Threading

Python Les threads sont une forme de parallélisme qui permet à ton programme d'exécuter plusieurs opérations à la fois. Cependant, le Global Interpreter Lock (GIL) de Python signifie qu'un seul thread peut exécuter le bytecode Python à la fois.

Exemples de fils simples et de fils multiples

Bien que cela semble être une limitation, les threads peuvent toujours fournir de la concurrence, en particulier pour les opérations liées aux E/S ou lors de l'utilisation d'opérations qui libèrent la GIL, comme celles effectuées par les bibliothèques C sous-jacentes de YOLO.

Le danger des instances de modèle partagées

L'instanciation d'un modèle YOLO en dehors de tes threads et le partage de cette instance entre plusieurs threads peuvent conduire à des conditions de course, où l'état interne du modèle est modifié de manière incohérente en raison d'accès simultanés. Cela est particulièrement problématique lorsque le modèle ou ses composants détiennent un état qui n'est pas conçu pour être à l'abri des threads.

Exemple non sécurisé par des threads : Instance de modèle unique

Lorsque tu utilises des threads dans Python, il est important de reconnaître les modèles qui peuvent entraîner des problèmes de concurrence. Voici ce qu'il faut éviter : partager une seule instance de modèle YOLO entre plusieurs threads.

# 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()

Dans l'exemple ci-dessus, le shared_model est utilisé par plusieurs threads, ce qui peut conduire à des résultats imprévisibles parce que predict pourrait être exécuté simultanément par plusieurs threads.

Exemple non sécurisé : Instances de modèles multiples

De même, voici un modèle non sécurisé avec plusieurs instances du modèle 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()

Même s'il y a deux instances de modèle distinctes, le risque de problèmes de concurrence existe toujours. Si l'implémentation interne de YOLO n'est pas sûr pour les threads, l'utilisation d'instances séparées peut ne pas empêcher les conditions de course, en particulier si ces instances partagent des ressources ou des états sous-jacents qui ne sont pas locaux pour les threads.

Inférence sûre pour les threads

Pour effectuer une inférence sans risque pour les threads, tu dois instancier un modèle YOLO distinct dans chaque thread. Cela garantit que chaque thread dispose de sa propre instance de modèle isolée, ce qui élimine le risque de conditions de course.

Exemple sûr pour les threads

Voici comment instancier un modèle YOLO à l'intérieur de chaque thread pour une inférence parallèle sûre :

# 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()

Dans cet exemple, chaque thread crée son propre YOLO instance. Cela empêche tout thread d'interférer avec l'état du modèle d'un autre, garantissant ainsi que chaque thread effectue l'inférence en toute sécurité et sans interactions inattendues avec les autres threads.

Conclusion

Lors de l'utilisation des modèles YOLO avec Python's threadingPour garantir la sécurité des threads, instancie toujours tes modèles dans le thread qui les utilisera. Cette pratique permet d'éviter les conditions de course et de s'assurer que tes tâches d'inférence s'exécutent de manière fiable.

Pour des scénarios plus avancés et pour optimiser davantage les performances de ton inférence multithread, envisage d'utiliser le parallélisme basé sur les processus avec multiprocessing ou de tirer parti d'une file d'attente de tâches avec des processus de travail dédiés.



Créé le 2023-11-12, Mis à jour le 2024-05-03
Auteurs : glenn-jocher (2)

Commentaires