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

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

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

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.



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

Comentários