YOLO Vision 2026:

Inferência Thread-Safe com modelos YOLO#

Para executar a inferência do Ultralytics YOLO de forma segura em threads do Python, instancie um modelo YOLO separado dentro de cada thread em vez de partilhar uma única instância entre elas. Partilhar um único modelo causa condições de corrida que corrompem o seu estado interno e produzem resultados imprevisíveis, porque o módulo threading do Python executa as threads concorrentemente contra o mesmo objeto. Este guia explica porque é que a partilha falha, mostra o padrão seguro por thread e aborda o decorador ThreadingLocked para casos em que tenhas de partilhar uma instância.

Vai para porque é que partilhar um modelo falha, o padrão seguro para threads ou o decorador ThreadingLocked.



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

Entendendo o Threading em Python#

As threads em Python são uma forma de paralelismo que permitem que seu programa execute várias operações de uma só vez. No entanto, o Global Interpreter Lock (GIL) do Python significa que apenas uma thread pode executar o bytecode Python por vez.

Single-thread vs multi-thread inference

Embora isso pareça uma limitação, as threads ainda podem proporcionar concorrência, especialmente para operações vinculadas a E/S ou ao usar operações que liberam o GIL, como aquelas realizadas pelas bibliotecas C subjacentes do YOLO.

O perigo de instâncias de modelo compartilhadas#

Instanciar um modelo YOLO fora de suas threads e compartilhar essa instância entre várias threads pode levar a condições de corrida, onde o estado interno do modelo é modificado de forma inconsistente devido a acessos concorrentes. Isso é particularmente problemático quando o modelo ou seus componentes mantêm um estado que não foi projetado para ser thread-safe.

Exemplo não Thread-Safe: Instância de modelo único#

Ao usares threads em Python, é importante reconhecer padrões que podem levar a problemas de concorrência. Eis o que deves evitar: partilhar uma única instância de modelo YOLO26 por várias 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("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()

No exemplo acima, o shared_model é utilizado por várias threads, o que pode levar a resultados imprevisíveis porque o predict pode ser executado em simultâneo por várias threads.

Exemplo Seguro: Uma Instância Dedicada por Thread#

Várias instâncias de modelo separadas são aceitáveis, desde que cada thread possua sua instância e nunca a compartilhe com outra thread. Não importa que as instâncias abaixo sejam criadas antes que as threads iniciem — o único padrão inseguro é compartilhar uma única instância entre threads:

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

Como cada thread trabalha com sua própria instância dedicada, não há estado de modelo compartilhado para as threads corromperem. Instanciar o modelo dentro de cada thread, conforme mostrado a seguir, é simplesmente a maneira mais fácil de garantir que uma instância nunca seja compartilhada acidentalmente.

Inferência Thread-Safe#

Para realizar uma inferência thread-safe, você deve instanciar um modelo YOLO separado dentro de cada thread. Isso garante que cada thread tenha sua própria instância de modelo isolada, eliminando o risco de condições de corrida.

Exemplo Thread-Safe#

Veja como instanciar um modelo YOLO dentro de cada thread para uma inferência paralela segura:

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

Neste exemplo, cada thread cria a sua própria instância de YOLO. Isto impede que qualquer thread interfira com o estado do modelo de outra, garantindo assim que cada thread realiza a inferência de forma segura e sem interações inesperadas com as outras threads.

Usando o Decorador ThreadingLocked#

O Ultralytics fornece um decorador ThreadingLocked que pode ser usado para garantir a execução segura de funções entre threads. Este decorador utiliza um bloqueio (lock) para garantir que apenas uma thread de cada vez pode executar a função decorada.

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

O decorador ThreadingLocked é particularmente útil quando precisas de partilhar uma instância de modelo entre threads, mas queres garantir que apenas uma thread pode aceder-lhe de cada vez.

Compromisso entre memória e concorrência

Partilhar uma instância de modelo bloqueada poupa memória em comparação com carregar um modelo em cada thread, mas reduz a concorrência porque as threads serializam no bloqueio e aguardam pela sua vez. Prefere o padrão por thread quando tens memória livre e queres o máximo paralelismo, e recorre a ThreadingLocked quando a memória do modelo for o estrangulamento.

Conclusão#

Ao usares modelos YOLO com o threading do Python, dá a cada thread a sua própria instância de modelo dedicada e nunca partilhes uma única instância entre threads. Instanciar o modelo dentro da thread que o utiliza é a forma mais simples de garantir isto, evitando condições de corrida e mantendo as tuas tarefas de inferência fiáveis.

Para cenários mais avançados e para otimizar ainda mais o desempenho da tua inferência multithread, considera usar o paralelismo baseado em processos com multiprocessing ou tirar partido de uma fila de tarefas com processos de trabalho dedicados.

FAQ#

Como posso evitar condições de corrida ao usar modelos YOLO em um ambiente Python multithread?#

Para evitar condições de corrida ao usar modelos YOLO da Ultralytics em um ambiente Python multithread, instancie um modelo YOLO separado dentro de cada thread. Isso garante que cada thread tenha sua própria instância de modelo isolada, evitando a modificação concorrente do estado do modelo.

Exemplo:

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

Para mais informações sobre como garantir a segurança entre threads, visita a página Inferência Segura entre Threads com Modelos YOLO.

Quais são as melhores práticas para executar inferência de modelo YOLO multithread em Python?#

Para executar a inferência de modelo YOLO multithread com segurança em Python, siga estas melhores práticas:

  1. Instancie modelos YOLO dentro de cada thread, em vez de compartilhar uma única instância de modelo entre threads.
  2. Usa o módulo multiprocessing do Python para processamento paralelo para evitar problemas relacionados com o Global Interpreter Lock (GIL).
  3. Lembre-se de que as bibliotecas C subjacentes do YOLO (PyTorch, OpenCV) liberam automaticamente o GIL durante cálculos pesados, portanto, as threads ainda podem executar inferências simultaneamente.
  4. Considera usar o decorador ThreadingLocked para instâncias de modelos partilhadas quando a memória for uma preocupação.

Exemplo para instanciação de modelo 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()

Para contexto adicional, consulta a secção sobre Inferência Segura entre Threads.

Por que cada thread deve ter sua própria instância de modelo YOLO?#

Cada thread deve ter sua própria instância de modelo YOLO para evitar condições de corrida. Quando uma única instância de modelo é compartilhada entre várias threads, acessos simultâneos podem levar a comportamentos imprevisíveis e modificações no estado interno do modelo. Ao usar instâncias separadas, você garante o isolamento da thread, tornando suas tarefas multithread confiáveis e seguras.

Para orientações detalhadas, consulta as secções Exemplo Não Seguro entre Threads: Instância de Modelo Única e Exemplo Seguro entre Threads.

Como o Global Interpreter Lock (GIL) do Python afeta a inferência do modelo YOLO?#

O Global Interpreter Lock (GIL) do Python permite que apenas uma thread execute bytecode Python de cada vez, o que pode limitar o desempenho de tarefas multithread limitadas por CPU. No entanto, para operações limitadas por E/S (I/O) ou processos que usam bibliotecas que libertam o GIL, como as bibliotecas C subjacentes do YOLO, ainda podes alcançar concorrência. Para um desempenho melhorado, considera usar o paralelismo baseado em processos com o módulo multiprocessing do Python.

Para saberes mais sobre multithreading em Python, vê a secção Compreender o Multithreading em Python.

É mais seguro usar paralelismo baseado em processos em vez de threading para a inferência do modelo YOLO?#

Sim, usar o módulo multiprocessing do Python é mais seguro e frequentemente mais eficiente para executar a inferência de modelos YOLO em paralelo. O paralelismo baseado em processos cria espaços de memória separados, evitando o Global Interpreter Lock (GIL) e reduzindo o risco de problemas de concorrência. Cada processo funcionará de forma independente com a sua própria instância de modelo YOLO.

Para mais detalhes sobre o paralelismo baseado em processos com modelos YOLO, consulta a página sobre Inferência Segura entre Threads.

Comentários