Meet YOLO26: next-gen vision AI.

Link to this sectionInferenza thread-safe con i modelli YOLO#

To run Ultralytics YOLO inference safely across Python threads, instantiate a separate YOLO model inside each thread instead of sharing one instance across them. Sharing a single model causes race conditions that corrupt its internal state and produce unpredictable results, because Python's threading module runs the threads concurrently against the same object. This guide explains why sharing fails, shows the safe per-thread pattern, and covers the ThreadingLocked decorator for cases where you must share an instance.

Vai a perché la condivisione di un modello fallisce, al pattern thread-safe, o al decoratore ThreadingLocked.



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

Link to this sectionComprendere il threading in Python#

I thread di Python sono una forma di parallelismo che consente al tuo programma di eseguire più operazioni contemporaneamente. Tuttavia, il Global Interpreter Lock (GIL) di Python significa che solo un thread può eseguire il bytecode Python alla volta.

Single-thread vs multi-thread inference

Sebbene sembri una limitazione, i thread possono comunque fornire concorrenza, specialmente per operazioni I/O-bound o quando si utilizzano operazioni che rilasciano il GIL, come quelle eseguite dalle librerie C sottostanti di YOLO.

Link to this sectionIl pericolo delle istanze di modello condivise#

Istanziare un modello YOLO al di fuori dei tuoi thread e condividere questa istanza tra più thread può portare a race condition, in cui lo stato interno del modello viene modificato in modo incoerente a causa di accessi simultanei. Questo è particolarmente problematico quando il modello o i suoi componenti mantengono uno stato non progettato per essere thread-safe.

Link to this sectionEsempio non thread-safe: istanza di modello singola#

Quando usi i thread in Python, è importante riconoscere i pattern che possono portare a problemi di concorrenza. Ecco cosa dovresti evitare: condividere una singola istanza del modello YOLO26 tra più thread.

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

Nell'esempio precedente, il shared_model viene utilizzato da più thread, il che può portare a risultati imprevedibili poiché predict potrebbe essere eseguito simultaneamente da più thread.

Link to this sectionEsempio sicuro: un'istanza dedicata per thread#

Più istanze del modello separate vanno bene finché ogni thread possiede la propria istanza e non la condivide mai con un altro thread. Non importa che le istanze qui sotto siano create prima dell'avvio dei thread: l'unico pattern non sicuro è condividere un'istanza tra i thread:

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

Poiché ogni thread lavora con la propria istanza dedicata, non c'è alcuno stato del modello condiviso che i thread possano corrompere. Istanziare il modello all'interno di ogni thread, come mostrato di seguito, è semplicemente il modo più semplice per garantire che un'istanza non venga mai condivisa accidentalmente.

Link to this sectionInferenza thread-safe#

Per eseguire un'inferenza thread-safe, dovresti istanziare un modello YOLO separato all'interno di ogni thread. Questo garantisce che ogni thread abbia la propria istanza del modello isolata, eliminando il rischio di race condition.

Link to this sectionEsempio thread-safe#

Ecco come istanziare un modello YOLO all'interno di ogni thread per un'inferenza parallela sicura:

# 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 questo esempio, ogni thread crea la propria istanza YOLO. Ciò impedisce a qualsiasi thread di interferire con lo stato del modello di un altro, garantendo così che ogni thread esegua l'inferenza in modo sicuro e senza interazioni impreviste con gli altri thread.

Link to this sectionUtilizzo del decoratore ThreadingLocked#

Ultralytics fornisce un decoratore ThreadingLocked che può essere utilizzato per garantire l'esecuzione thread-safe delle funzioni. Questo decoratore utilizza un lock per assicurare che solo un thread alla volta possa eseguire la funzione decorata.

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

Il decoratore ThreadingLocked è particolarmente utile quando devi condividere un'istanza del modello tra i thread ma vuoi assicurarti che solo un thread alla volta possa accedervi.

Compromesso tra memoria e concorrenza

Condividere un'unica istanza di modello bloccata risparmia memoria rispetto al caricamento di un modello in ogni thread, ma riduce la concorrenza perché i thread si serializzano sul lock e attendono il proprio turno. Preferisci il pattern per thread quando hai memoria da risparmiare e vuoi il massimo parallelismo, e usa ThreadingLocked quando la memoria del modello è il collo di bottiglia.

Link to this sectionConclusione#

Quando utilizzi i modelli YOLO con il threading di Python, assegna a ogni thread la propria istanza del modello dedicata e non condividere mai un'istanza tra i thread. Istanziare il modello all'interno del thread che lo utilizza è il modo più semplice per garantire ciò, evitando race condition e mantenendo affidabili le tue attività di inferenza.

Per scenari più avanzati e per ottimizzare ulteriormente le prestazioni della tua inferenza multi-thread, considera l'utilizzo del parallelismo basato su processi con multiprocessing o lo sfruttamento di una coda di attività con processi di lavoro dedicati.

Link to this sectionFAQ#

Link to this sectionCome posso evitare le race condition quando uso i modelli YOLO in un ambiente Python multi-thread?#

Per prevenire le race condition quando utilizzi i modelli YOLO di Ultralytics in un ambiente Python multi-thread, istanzia un modello YOLO separato all'interno di ogni thread. Questo garantisce che ogni thread abbia la propria istanza del modello isolata, evitando la modifica simultanea dello stato del modello.

Esempio:

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

Per ulteriori informazioni su come garantire la sicurezza dei thread, visita Inferenza thread-safe con i modelli YOLO.

Link to this sectionQuali sono le migliori pratiche per eseguire un'inferenza del modello YOLO multi-thread in Python?#

Per eseguire l'inferenza del modello YOLO multi-thread in modo sicuro in Python, segui queste migliori pratiche:

  1. Istanzia i modelli YOLO all'interno di ogni thread invece di condividere una singola istanza di modello tra i thread.
  2. Usa il modulo multiprocessing di Python per l'elaborazione parallela per evitare problemi legati al Global Interpreter Lock (GIL).
  3. Ricorda che le librerie C sottostanti di YOLO (PyTorch, OpenCV) rilasciano automaticamente il GIL durante i calcoli intensivi, quindi i thread possono comunque eseguire l'inferenza contemporaneamente.
  4. Prendi in considerazione l'utilizzo del decoratore ThreadingLocked per istanze di modello condivise quando la memoria è un problema.

Esempio per l'istanziazione di modelli thread-safe:

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

Per un contesto aggiuntivo, fai riferimento alla sezione su Inferenza thread-safe.

Link to this sectionPerché ogni thread dovrebbe avere la propria istanza di modello YOLO?#

Ogni thread dovrebbe avere la propria istanza di modello YOLO per prevenire le race condition. Quando una singola istanza di modello viene condivisa tra più thread, gli accessi simultanei possono portare a comportamenti imprevedibili e modifiche dello stato interno del modello. Utilizzando istanze separate, garantisci l'isolamento dei thread, rendendo le tue attività multi-thread affidabili e sicure.

Per una guida dettagliata, controlla le sezioni Esempio non thread-safe: istanza di modello singola e Esempio thread-safe.

Link to this sectionIn che modo il Global Interpreter Lock (GIL) di Python influisce sull'inferenza del modello YOLO?#

Il Global Interpreter Lock (GIL) di Python consente a un solo thread alla volta di eseguire il bytecode Python, il che può limitare le prestazioni delle attività multi-thread CPU-bound. Tuttavia, per operazioni I/O-bound o processi che utilizzano librerie che rilasciano il GIL, come le librerie C sottostanti di YOLO, puoi comunque ottenere la concorrenza. Per prestazioni migliorate, considera l'utilizzo del parallelismo basato su processi con il modulo multiprocessing di Python.

Per saperne di più sul threading in Python, vedi la sezione Comprendere il threading in Python.

Link to this sectionÈ più sicuro utilizzare il parallelismo basato su processi invece del threading per l'inferenza del modello YOLO?#

Sì, utilizzare il modulo multiprocessing di Python è più sicuro e spesso più efficiente per eseguire l'inferenza del modello YOLO in parallelo. Il parallelismo basato su processi crea spazi di memoria separati, evitando il Global Interpreter Lock (GIL) e riducendo il rischio di problemi di concorrenza. Ogni processo opererà indipendentemente con la propria istanza di modello YOLO.

Per ulteriori dettagli sul parallelismo basato su processi con i modelli YOLO, fai riferimento alla pagina su Inferenza thread-safe.

Commenti