Salta para o conteúdo

Inferência segura de threads com modelos YOLO

A execução de modelos YOLO num ambiente multi-threaded requer uma consideração cuidadosa para garantir a segurança do thread. Python's threading permite executar várias threads simultaneamente, mas quando se trata de usar modelos YOLO nessas threads, há questões de segurança importantes a serem consideradas. Esta página irá guiar-te através da criação de inferência de modelo YOLO segura para threads.

Compreender Python Threading

Python As threads são uma forma de paralelismo que permite ao teu programa executar várias operações ao mesmo tempo. No entanto, o Global Interpreter Lock (GIL) do Python significa que apenas uma thread pode executar o bytecode Python de cada vez.

Exemplos de um ou vários threads

Embora isso pareça uma limitação, as threads ainda podem fornecer simultaneidade, especialmente para operações I/O-bound ou ao usar operações que liberam o GIL, como aquelas executadas pelas bibliotecas C subjacentes do YOLO.

O perigo das instâncias de modelo partilhadas

Instanciar um modelo YOLO fora dos seus threads e compartilhar essa instância entre vários threads pode levar a condições de corrida, em que o estado interno do modelo é modificado de forma inconsistente devido a acessos simultâneos. 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 seguro de thread: Instância de modelo único

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

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

Exemplo não seguro de thread: Várias instâncias de modelo

Da mesma forma, aqui está um padrão inseguro com várias instâncias do modelo 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()

Mesmo que existam duas instâncias de modelo separadas, o risco de problemas de concorrência ainda existe. Se a implementação interna do YOLO não é thread-safe, a utilização de instâncias separadas pode não evitar condições de corrida, especialmente se estas instâncias partilham quaisquer recursos ou estados subjacentes que não sejam thread-locais.

Inferência segura de threads

Para executar a inferência thread-safe, deves instanciar um modelo YOLO separado em 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 de Thread-Safe

Vê aqui 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("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()

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

Conclusão

Quando utilizas os modelos YOLO com Python's threadingSempre instancia seus modelos dentro da thread que irá usá-los para garantir a segurança da thread. Essa prática evita condições de corrida e garante que suas tarefas de inferência sejam executadas de forma confiável.

Para cenários mais avançados e para otimizar ainda mais o desempenho da inferência multithread, considera a utilização do paralelismo baseado em processos com multiprocessing ou aproveita uma fila de tarefas com processos de trabalho dedicados.

FAQ

Como posso evitar condições de corrida ao utilizar modelos YOLO num ambiente Python multithread?

Para evitar condições de corrida ao usar modelos Ultralytics YOLO em um ambiente Python multi-threaded, instancia um modelo YOLO separado em cada thread. Isso garante que cada thread tenha sua própria instância de modelo isolada, evitando a modificação simultânea 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("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()

Para obter mais informações sobre como garantir a segurança da linha, visita a Inferência segura da linha com YOLO Models.

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

Para executar a inferência de modelo YOLO multi-threaded com segurança em Python, segue estas práticas recomendadas:

  1. Instancia os modelos YOLO em cada thread em vez de partilhar uma única instância de modelo entre threads.
  2. Utiliza Python's multiprocessing para processamento paralelo, a fim de evitar problemas relacionados com o Bloqueio Global do Intérprete (GIL).
  3. Libera o GIL usando operações realizadas pelas bibliotecas C subjacentes do YOLO.

Exemplo de instanciação de modelos 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."""
    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()

Para contexto adicional, consulta a secção sobre Inferência Thread-Safe.

Porque é que cada thread deve ter a sua própria instância do modelo YOLO ?

Cada thread deve ter sua própria instância do modelo YOLO para evitar condições de corrida. Quando uma única instância de modelo é compartilhada entre vários threads, os acessos simultâneos podem levar a um comportamento imprevisível e a modificações do estado interno do modelo. Ao usar instâncias separadas, garante o isolamento do thread, tornando as tarefas multi-thread confiáveis e seguras.

Para obter orientações detalhadas, verifica as secções Exemplo não seguro para threads: Instância de modelo único e Exemplo Thread-Safe.

Como é que o Global Interpreter Lock (GIL) do Python afecta a inferência do modelo YOLO ?

Pythonpermite que apenas uma thread execute Python bytecode de cada vez, o que pode limitar o desempenho de tarefas multi-threading ligadas a CPU. No entanto, para operações vinculadas a E/S ou processos que usam bibliotecas que liberam o GIL, como as bibliotecas C do YOLO, ainda é possível obter simultaneidade. Para melhorar o desempenho, considere o uso de paralelismo baseado em processo com Python's multiprocessing módulo.

Para obter mais informações sobre threading em Python, consulte a secção Compreender Python Threading.

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

Sim, utilizando Python's multiprocessing é mais seguro e frequentemente mais eficiente para executar a inferência do modelo 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 operará independentemente com sua própria instância do modelo YOLO .

Para obter mais detalhes sobre o paralelismo baseado em processos com os modelos YOLO , consulte a página sobre Inferência Thread-Safe.



Criado em 2023-11-12, Atualizado em 2024-07-05
Autores: glenn-jocher (5)

Comentários