YOLO Vision 2026:

Thread-sichere Inferenz mit YOLO-Modellen#

Um Ultralytics YOLO Inferenz sicher über Python-Threads hinweg auszuführen, instanziiere ein separates YOLO-Modell innerhalb jedes Threads, anstatt eine einzige Instanz gemeinsam zu nutzen. Das Teilen eines einzigen Modells verursacht Race Conditions, die seinen internen Zustand beschädigen und zu unvorhersehbaren Ergebnissen führen, da das threading-Modul von Python die Threads gleichzeitig auf dasselbe Objekt loslässt. Diese Anleitung erklärt, warum das Teilen fehlschlägt, zeigt das sichere Pattern pro Thread und behandelt den ThreadingLocked-Decorator für Fälle, in denen du eine Instanz teilen musst.

Springe zu warum das Teilen eines Modells fehlschlägt, zum thread-sicheren Pattern oder zum ThreadingLocked-Decorator.



Watch: How to Perform Thread Safe Inference with Ultralytics YOLO Models in Python | Multi-Threading 🚀

Python-Threading verstehen#

Python-Threads sind eine Form der Parallelität, die es deinem Programm ermöglicht, mehrere Operationen gleichzeitig auszuführen. Da Pythons Global Interpreter Lock (GIL) jedoch existiert, kann immer nur ein Thread gleichzeitig Python-Bytecode ausführen.

Single-thread vs multi-thread inference

Obwohl dies wie eine Einschränkung klingt, können Threads dennoch Nebenläufigkeit bieten, insbesondere bei I/O-lastigen Vorgängen oder bei der Verwendung von Operationen, die das GIL freigeben, wie sie von den zugrunde liegenden C-Bibliotheken von YOLO durchgeführt werden.

Die Gefahr gemeinsam genutzter Modellinstanzen#

Das Instanziieren eines YOLO-Modells außerhalb deiner Threads und das Teilen dieser Instanz über mehrere Threads hinweg kann zu Race Conditions führen, bei denen der interne Zustand des Modells aufgrund gleichzeitiger Zugriffe inkonsistent verändert wird. Dies ist besonders problematisch, wenn das Modell oder seine Komponenten einen Zustand aufweisen, der nicht für die Thread-Sicherheit ausgelegt ist.

Nicht-thread-sicheres Beispiel: Einzelne Modellinstanz#

Wenn du Threads in Python verwendest, ist es wichtig, Muster zu erkennen, die zu Konkurrenzproblemen führen können. Hier ist, was du vermeiden solltest: das Teilen einer einzigen YOLO26-Modellinstanz über mehrere Threads hinweg.

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

Im obigen Beispiel wird das shared_model von mehreren Threads verwendet, was zu unvorhersehbaren Ergebnissen führen kann, da predict gleichzeitig von mehreren Threads ausgeführt werden könnte.

Sicheres Beispiel: Eine dedizierte Instanz pro Thread#

Mehrere separate Modellinstanzen sind in Ordnung, solange jeder Thread seine Instanz besitzt und sie niemals mit einem anderen Thread teilt. Es spielt keine Rolle, dass die Instanzen unten erstellt werden, bevor die Threads starten – das einzige unsichere Muster ist das Teilen einer Instanz über Threads hinweg:

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

Da jeder Thread mit seiner eigenen dedizierten Instanz arbeitet, gibt es keinen gemeinsamen Modellzustand, den die Threads beschädigen könnten. Das Instanziieren des Modells innerhalb jedes Threads, wie im Folgenden gezeigt, ist einfach der leichteste Weg, um zu garantieren, dass eine Instanz niemals versehentlich geteilt wird.

Thread-sichere Inferenz#

Um eine thread-sichere Inferenz durchzuführen, solltest du innerhalb jedes Threads ein separates YOLO-Modell instanziieren. Dies stellt sicher, dass jeder Thread seine eigene isolierte Modellinstanz besitzt, was das Risiko von Race Conditions eliminiert.

Thread-sicheres Beispiel#

So instanziierst du ein YOLO-Modell innerhalb jedes Threads für eine sichere parallele Inferenz:

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

In diesem Beispiel erstellt jeder Thread seine eigene YOLO-Instanz. Dies verhindert, dass ein Thread den Modellzustand eines anderen beeinträchtigt, und stellt somit sicher, dass jeder Thread die Inferenz sicher und ohne unerwartete Wechselwirkungen mit den anderen Threads durchführt.

Verwendung des ThreadingLocked Dekorators#

Ultralytics stellt einen ThreadingLocked-Decorator bereit, der verwendet werden kann, um eine thread-sichere Ausführung von Funktionen sicherzustellen. Dieser Decorator verwendet eine Sperre (Lock), um sicherzustellen, dass immer nur ein Thread gleichzeitig die dekorierte Funktion ausführen kann.

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 threads

Der ThreadingLocked-Decorator ist besonders nützlich, wenn du eine Modellinstanz über Threads hinweg teilen musst, aber sicherstellen willst, dass jeweils nur ein Thread darauf zugreifen kann.

Speicher- vs. Nebenläufigkeits-Abwägung

Das Teilen einer gesperrten Modellinstanz spart Speicher im Vergleich zum Laden eines Modells in jedem Thread, aber es reduziert die Parallelität, da sich Threads an der Sperre serialisieren und auf ihre Reihe warten. Bevorzuge das Pattern pro Thread, wenn du Speicher übrig hast und maximalen Parallelismus willst, und greife zu ThreadingLocked, wenn der Modellspeicher der Flaschenhals ist.

Fazit#

Wenn du YOLO-Modelle mit dem threading von Python verwendest, gib jedem Thread seine eigene dedizierte Modellinstanz und teile niemals eine Instanz über Threads hinweg. Das Instanziieren des Modells innerhalb des Threads, der es verwendet, ist der einfachste Weg, dies zu garantieren, um Race Conditions zu vermeiden und deine Inferenzaufgaben zuverlässig zu halten.

Für fortgeschrittenere Szenarien und zur weiteren Optimierung deiner multithreaded Inferenzleistung solltest du die Verwendung von prozessbasierter Parallelität mit multiprocessing oder die Nutzung einer Task-Warteschlange mit dedizierten Worker-Prozessen in Betracht ziehen.

FAQ#

  • Um Race Conditions bei der Verwendung von Ultralytics YOLO-Modellen in einer Multi-Thread-Python-Umgebung zu verhindern, instanziiere ein separates YOLO-Modell innerhalb jedes Threads. Dies stellt sicher, dass jeder Thread seine eigene isolierte Modellinstanz hat und verhindert die gleichzeitige Änderung des Modellzustands.

    Beispiel:

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

    Weitere Informationen zur Gewährleistung der Threadsicherheit findest du unter Thread-Safe Inference with YOLO Models.

  • Um YOLO-Modell-Inferenz in Python sicher mit mehreren Threads auszuführen, befolge diese Best Practices:

    1. Instanziiere YOLO-Modelle innerhalb jedes Threads, anstatt eine einzelne Modellinstanz über Threads hinweg zu teilen.
    2. Verwende das multiprocessing-Modul von Python für die parallele Verarbeitung, um Probleme im Zusammenhang mit dem Global Interpreter Lock (GIL) zu vermeiden.
    3. Denke daran, dass die zugrunde liegenden C-Bibliotheken von YOLO (PyTorch, OpenCV) während schwerer Berechnungen automatisch das GIL freigeben, sodass Threads weiterhin gleichzeitig Inferenz ausführen können.
    4. Erwäge die Verwendung des ThreadingLocked-Decorators für gemeinsam genutzte Modellinstanzen, wenn Speicher ein Problem darstellt.

    Beispiel für eine thread-sichere Modellinstanziierung:

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

    Für zusätzlichen Kontext beziehe dich auf den Abschnitt zu Thread-Safe Inference.

  • Jeder Thread sollte seine eigene YOLO-Modellinstanz haben, um Race Conditions zu verhindern. Wenn eine einzelne Modellinstanz von mehreren Threads gemeinsam genutzt wird, können gleichzeitige Zugriffe zu unvorhersehbarem Verhalten und Änderungen am internen Zustand des Modells führen. Durch die Verwendung separater Instanzen stellst du die Thread-Isolation sicher und machst deine Multi-Thread-Aufgaben zuverlässig und sicher.

    Für detaillierte Anleitungen schaue dir die Abschnitte Non-Thread-Safe Example: Single Model Instance und Thread-Safe Example an.

  • Der Global Interpreter Lock (GIL) von Python erlaubt es nur einem Thread, Python-Bytecode gleichzeitig auszuführen, was die Leistung von CPU-gebundenen Multithreading-Aufgaben einschränken kann. Für I/O-gebundene Operationen oder Prozesse, die Bibliotheken verwenden, welche das GIL freigeben (wie die zugrundeliegenden C-Bibliotheken von YOLO), kannst du jedoch trotzdem Parallelität erreichen. Für eine verbesserte Leistung solltest du die Verwendung von prozessbasierter Parallelität mit dem multiprocessing-Modul von Python in Betracht ziehen.

    Mehr über das Threading in Python findest du im Abschnitt Understanding Python Threading.

  • Ja, die Verwendung des multiprocessing-Moduls von Python ist sicherer und oft effizienter für die parallele Ausführung von YOLO-Modellinferenzen. Prozessbasierte Parallelität schafft separate Speicherbereiche, vermeidet den Global Interpreter Lock (GIL) und verringert das Risiko von Konkurrenzproblemen. Jeder Prozess arbeitet unabhängig mit seiner eigenen YOLO-Modellinstanz.

    Weitere Details zur prozessbasierten Parallelität mit YOLO-Modellen findest du auf der Seite über Thread-Safe Inference.

Kommentare