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 threading import Thread

from ultralytics import YOLO

# 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 threading import Thread

from ultralytics import YOLO

# 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 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("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.

FAQ

Comment puis-je éviter les conditions de course lorsque j'utilise les modèles YOLO dans un environnement multithread Python ?

Pour éviter les conditions de course lors de l'utilisation des modèles Ultralytics YOLO dans un environnement Python multithread, instancie un modèle YOLO distinct dans chaque thread. Cela garantit que chaque thread dispose de sa propre instance de modèle isolée, évitant ainsi toute modification concurrente de l'état du modèle.

Exemple :

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("yolov8n.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()

Pour plus d'informations sur la sécurité des fils, visite le site Thread-Safe Inference with YOLO Models.

Quelles sont les meilleures pratiques pour exécuter l'inférence du modèle YOLO en multithread dans Python?

Pour exécuter en toute sécurité l'inférence du modèle YOLO multithread dans Python, suis ces bonnes pratiques :

  1. Instancie les modèles YOLO dans chaque thread plutôt que de partager une instance de modèle unique entre les threads.
  2. Utilise le site Python multiprocessing pour le traitement parallèle afin d'éviter les problèmes liés au verrouillage global de l'interprète (GIL).
  3. Libère la GIL en utilisant les opérations effectuées par les bibliothèques C sous-jacentes de YOLO.

Exemple d'instanciation de modèle sans fil :

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."""
    model = YOLO("yolov8n.pt")
    results = 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()

Pour un contexte supplémentaire, reporte-toi à la section sur l'inférence sûre pour les threads.

Pourquoi chaque thread devrait-il avoir sa propre instance du modèle YOLO ?

Chaque thread doit avoir sa propre instance de modèle YOLO pour éviter les conditions de course. Lorsqu'une seule instance de modèle est partagée entre plusieurs threads, les accès simultanés peuvent entraîner un comportement imprévisible et des modifications de l'état interne du modèle. En utilisant des instances séparées, tu garantis l'isolation des threads, ce qui rend tes tâches multithreads fiables et sûres.

Pour obtenir des conseils détaillés, consulte les sections Exemple non sécurisé par un thread : Instance unique du modèle et Exemple sûr pour les threads.

Comment le verrouillage global de l'interprète (GIL) de Python affecte-t-il l'inférence du modèle YOLO ?

PythonLe Global Interpreter Lock (GIL) de Python ne permet qu'à un seul thread d'exécuter le bytecode à la fois, ce qui peut limiter les performances des tâches multithreading liées à CPU. Cependant, pour les opérations liées aux E/S ou les processus qui utilisent des bibliothèques libérant le GIL, comme les bibliothèques C de YOLO, tu peux toujours obtenir la simultanéité. Pour améliorer les performances, tu peux envisager d'utiliser le parallélisme basé sur les processus avec Python's multiprocessing module.

Pour en savoir plus sur l'enfilage dans Python, voir la section Comprendre l'enfilage dans Python .

Est-il plus sûr d'utiliser le parallélisme basé sur les processus plutôt que le threading pour l'inférence du modèle YOLO ?

Oui, en utilisant Python's multiprocessing est plus sûr et souvent plus efficace pour exécuter en parallèle l'inférence du modèle YOLO . Le parallélisme basé sur les processus crée des espaces mémoire distincts, ce qui permet d'éviter le verrouillage global de l'interpréteur (GIL) et de réduire le risque de problèmes de concurrence. Chaque processus fonctionne indépendamment avec sa propre instance du modèle YOLO .

Pour plus de détails sur le parallélisme basé sur les processus avec les modèles YOLO , reporte-toi à la page sur l'inférence sûre pour les threads.



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

Commentaires