Overslaan naar inhoud

Draadveilige inferentie met YOLO modellen

Het uitvoeren van YOLO modellen in een omgeving met meerdere threads vereist zorgvuldige overweging om threadveiligheid te garanderen. Python's threading Met de module kun je meerdere threads tegelijk laten draaien, maar als het gaat om het gebruik van YOLO modellen over deze threads heen, zijn er belangrijke veiligheidskwesties waar je rekening mee moet houden. Deze pagina leidt je door het maken van thread-veilige YOLO modelinferentie.

Inzicht in Python Threading

Python threads zijn een vorm van parallellisme waarmee je programma meerdere bewerkingen tegelijk kan uitvoeren. Echter, Python's Global Interpreter Lock (GIL) betekent dat slechts één thread tegelijk Python bytecode kan uitvoeren.

Single vs Multi-Thread Voorbeelden

Hoewel dit klinkt als een beperking, kunnen threads nog steeds zorgen voor gelijktijdigheid, vooral voor I/O-gebonden bewerkingen of bij het gebruik van bewerkingen die de GIL vrijgeven, zoals die worden uitgevoerd door YOLO's onderliggende C-bibliotheken.

Het gevaar van gedeelde modelinstanties

Het instantiëren van een YOLO model buiten je threads en het delen van deze instantie over meerdere threads kan leiden tot "race conditions", waarbij de interne toestand van het model inconsistent wordt gewijzigd door gelijktijdige toegang. Dit is vooral problematisch als het model of de componenten ervan een toestand bevatten die niet is ontworpen om thread-veilig te zijn.

Voorbeeld zonder threads: Enkele modelinstantie

Bij het gebruik van threads in Python is het belangrijk om patronen te herkennen die kunnen leiden tot concurrency problemen. Dit is wat je moet vermijden: het delen van een enkele instantie van een YOLO model over meerdere 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()

In het bovenstaande voorbeeld is de shared_model wordt gebruikt door meerdere threads, wat kan leiden tot onvoorspelbare resultaten omdat predict gelijktijdig door meerdere threads kunnen worden uitgevoerd.

Voorbeeld zonder threads: Meerdere modelinstanties

Op dezelfde manier is hier een onveilig patroon met meerdere YOLO modelinstanties:

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

Ook al zijn er twee aparte modelinstanties, het risico van gelijktijdigheidsproblemen bestaat nog steeds. Als de interne implementatie van YOLO niet thread-safe is, kan het gebruik van aparte instanties race condities niet voorkomen, vooral als deze instanties onderliggende bronnen of toestanden delen die niet thread-local zijn.

Thread-veilige inferentie

Om thread-veilige inferentie uit te voeren, moet je een apart YOLO model instantiëren binnen elke thread. Dit zorgt ervoor dat elke thread zijn eigen geïsoleerde modelinstantie heeft, waardoor het risico op "race conditions" wordt geëlimineerd.

Thread-Safe voorbeeld

Hier wordt uitgelegd hoe je een YOLO model kunt instantiëren binnen elke thread voor veilige parallelle inferentie:

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

In dit voorbeeld maakt elke thread zijn eigen YOLO instantie. Dit voorkomt dat een thread zich bemoeit met de modeltoestand van een andere thread en zorgt er zo voor dat elke thread veilig inferentie uitvoert zonder onverwachte interacties met de andere threads.

Conclusie

Bij gebruik van YOLO modellen met Python's threadinginstantieer je modellen altijd binnen de thread die ze gaat gebruiken om threadveiligheid te garanderen. Dit voorkomt race condities en zorgt ervoor dat je inferentietaken betrouwbaar worden uitgevoerd.

Voor geavanceerdere scenario's en om de prestaties van inferenties met meerdere threads verder te optimaliseren, kun je overwegen om procesgebaseerd parallellisme te gebruiken met multiprocessing of gebruik maken van een taakwachtrij met speciale werkprocessen.



Gemaakt op 2023-11-12, Bijgewerkt op 2024-05-03
Auteurs: glenn-jocher (2)

Reacties