Перейти к содержанию

Потокобезопасный вывод с моделями YOLO

Запуск моделей YOLO в многопоточной среде требует тщательного рассмотрения для обеспечения безопасности потоков. Python threading модуль позволяет запускать несколько потоков одновременно, но когда дело доходит до использования YOLO моделей в этих потоках, необходимо учитывать важные вопросы безопасности. Эта страница проведет вас через создание потокобезопасного вывода моделей YOLO.



Смотреть: Как выполнять потокобезопасный вывод с моделями Ultralytics YOLO в python | Многопоточность 🚀

Понимание работы с потоками в python

Потоки Python — это форма параллелизма, позволяющая вашей программе выполнять несколько операций одновременно. Однако, глобальная блокировка интерпретатора (GIL) Python означает, что только один поток может выполнять байт-код Python в каждый момент времени.

Примеры однопоточной и многопоточной работы

Хотя это звучит как ограничение, потоки все еще могут обеспечивать параллелизм, особенно для операций, связанных с вводом-выводом, или при использовании операций, которые освобождают GIL, таких как операции, выполняемые базовыми библиотеками YOLO на C.

Опасность использования общих экземпляров моделей

Создание экземпляра модели YOLO вне ваших потоков и совместное использование этого экземпляра в нескольких потоках может привести к состояниям гонки, когда внутреннее состояние модели непоследовательно изменяется из-за одновременного доступа. Это особенно проблематично, когда модель или ее компоненты содержат состояние, которое не предназначено для безопасного использования в многопоточной среде.

Пример, небезопасный для многопоточности: один экземпляр модели

При использовании потоков в python важно распознавать закономерности, которые могут привести к проблемам параллелизма. Вот чего следует избегать: совместное использование одного экземпляра модели YOLO несколькими потоками.

# 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("yolo11n.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()

В примере выше, shared_model используется несколькими потоками, что может привести к непредсказуемым результатам, потому что predict могут выполняться одновременно несколькими потоками.

Пример, небезопасный для многопоточности: несколько экземпляров модели

Аналогично, вот небезопасный шаблон с несколькими экземплярами модели 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("yolo11n_1.pt")
shared_model_2 = YOLO("yolo11n_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()

Несмотря на то, что существуют два отдельных экземпляра модели, риск возникновения проблем с параллелизмом все еще существует. Если внутренняя реализация YOLO не является потокобезопасным, использование отдельных экземпляров может не предотвратить состояние гонки, особенно если эти экземпляры совместно используют какие-либо базовые ресурсы или состояния, которые не являются локальными для потока.

Потокобезопасный инференс

Для обеспечения потокобезопасного вывода необходимо создать отдельный экземпляр модели YOLO в каждом потоке. Это гарантирует, что каждый поток имеет свой собственный изолированный экземпляр модели, устраняя риск возникновения гонок данных.

Пример с потокобезопасностью

Вот как создать экземпляр модели YOLO внутри каждого потока для безопасного параллельного вывода:

# 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("yolo11n.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()

В этом примере каждый поток создает свой собственный YOLO экземпляр. Это предотвращает вмешательство одного потока в состояние модели другого, тем самым гарантируя, что каждый поток выполняет вывод безопасно и без неожиданных взаимодействий с другими потоками.

Использование декоратора ThreadingLocked

Ultralytics предоставляет ThreadingLocked Декоратор, который можно использовать для обеспечения потокобезопасного выполнения функций. Этот декоратор использует блокировку, чтобы гарантировать, что только один поток одновременно может выполнять декорированную функцию.

from ultralytics import YOLO
from ultralytics.utils import ThreadingLocked

# Create a model instance
model = YOLO("yolo11n.pt")


# Decorate the predict method 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

Параметр ThreadingLocked Этот декоратор особенно полезен, когда вам нужно совместно использовать экземпляр модели между потоками, но вы хотите убедиться, что только один поток может получить к нему доступ одновременно. Такой подход позволяет сэкономить память по сравнению с созданием нового экземпляра модели для каждого потока, но может снизить параллельность, поскольку потокам придется ждать освобождения блокировки.

Заключение

При использовании моделей YOLO с Python threading, всегда создавайте экземпляры ваших моделей в том потоке, который будет их использовать, чтобы обеспечить потокобезопасность. Эта практика позволяет избежать состояний гонки и гарантирует надежное выполнение ваших задач inference.

Для более сложных сценариев и дальнейшей оптимизации производительности многопоточного инференса рассмотрите возможность использования параллелизма на основе процессов с помощью multiprocessing или использования очереди задач с выделенными рабочими процессами.

Часто задаваемые вопросы

Как избежать состояний гонки при использовании моделей YOLO в многопоточной среде python?

Чтобы предотвратить гонки данных при использовании моделей Ultralytics YOLO в многопоточной среде Python, создайте отдельный экземпляр модели YOLO в каждом потоке. Это гарантирует, что каждый поток имеет свой собственный изолированный экземпляр модели, избегая одновременного изменения состояния модели.

Пример:

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("yolo11n.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()

Для получения дополнительной информации об обеспечении безопасности потоков посетите страницу Вывод, безопасный для потоков, с моделями YOLO.

Каковы лучшие практики для запуска многопоточного вывода модели YOLO в Python?

Чтобы безопасно выполнять многопоточный inference модели YOLO в Python, следуйте этим рекомендациям:

  1. Создавайте экземпляры моделей YOLO в каждом потоке, а не используйте один экземпляр модели совместно для всех потоков.
  2. Используйте multiprocessing модуль для параллельной обработки, чтобы избежать проблем, связанных с Global Interpreter Lock (GIL).
  3. Снятие GIL за счет использования операций, выполняемых базовыми библиотеками C YOLO.
  4. Рассмотрите возможность использования ThreadingLocked Декоратор для совместного использования экземпляров моделей, когда важна экономия памяти.

Пример создания потокобезопасного экземпляра модели:

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("yolo11n.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()

Для получения дополнительной информации обратитесь к разделу о Потокобезопасном выводе.

Почему каждый поток должен иметь свой собственный экземпляр модели YOLO?

Каждый поток должен иметь свой собственный экземпляр модели YOLO, чтобы предотвратить состояние гонки. Когда один экземпляр модели используется совместно несколькими потоками, параллельный доступ может привести к непредсказуемому поведению и изменению внутреннего состояния модели. Используя отдельные экземпляры, вы обеспечиваете изоляцию потоков, что делает ваши многопоточные задачи надежными и безопасными.

Подробные инструкции можно найти в разделах Пример без потокобезопасности: экземпляр одной модели и Пример с потокобезопасностью.

Как глобальная блокировка интерпретатора (GIL) Python влияет на инференс модели YOLO?

Глобальная блокировка интерпретатора (GIL) Python позволяет только одному потоку выполнять байт-код Python за раз, что может ограничить производительность многопоточных задач, связанных с CPU. Однако для операций, связанных с вводом-выводом, или процессов, использующих библиотеки, освобождающие GIL, такие как базовые библиотеки C YOLO, вы все равно можете добиться параллелизма. Для повышения производительности рассмотрите возможность использования параллелизма на основе процессов с помощью модуля multiprocessing Python. multiprocessing модуле.

Для получения дополнительной информации о многопоточности в Python см. раздел Понимание многопоточности Python.

Безопаснее ли использовать параллелизм на основе процессов вместо потоков для логического вывода модели YOLO?

Да, используя Python's multiprocessing модуль является более безопасным и часто более эффективным для параллельного запуска вывода моделей YOLO. Параллелизм на основе процессов создает отдельные пространства памяти, избегая Global Interpreter Lock (GIL) и снижая риск возникновения проблем с параллелизмом. Каждый процесс будет работать независимо со своим собственным экземпляром модели YOLO.

Для получения более подробной информации о параллелизме на основе процессов с моделями YOLO, обратитесь к странице Thread-Safe Inference.



📅 Создано 1 год назад ✏️ Обновлено 3 месяца назад

Комментарии