Безопасные для потоков выводы с помощью моделей YOLO
Запуск моделей YOLO в многопоточной среде требует тщательного рассмотрения для обеспечения безопасности потоков. Python's threading
Модуль позволяет запускать несколько потоков одновременно, но когда дело доходит до использования моделей YOLO в этих потоках, возникают важные вопросы безопасности, о которых следует помнить. На этой странице вы узнаете, как создать безопасный для потоков вывод моделей YOLO .
Понимание Python Threading
Python Потоки - это форма параллелизма, позволяющая вашей программе выполнять несколько операций одновременно. Однако глобальная блокировка интерпретатора (GIL) на сайте Python означает, что только один поток может одновременно выполнять байткод Python .
Хотя это звучит как ограничение, потоки все же могут обеспечить параллелизм, особенно при выполнении операций ввода-вывода или при использовании операций, освобождающих GIL, например, операций, выполняемых библиотеками YOLO's, лежащими в основе языка 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's threading
Чтобы обеспечить безопасность потоков, всегда инстанцируйте модели в потоке, который будет их использовать. Такая практика позволяет избежать условий гонки и обеспечивает надежное выполнение задач вывода.
Для более сложных сценариев и дальнейшей оптимизации производительности многопоточных выводов рассмотрите возможность использования параллелизма на основе процессов с многопроцессорной обработкой или использования очереди задач с выделенными рабочими процессами.
ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ
Как избежать условий гонки при использовании моделей 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()
Дополнительную информацию об обеспечении безопасности потоков можно найти в статье Thread-Safe Inference with YOLO Models.
Каковы лучшие практики для выполнения многопоточного YOLO вывода моделей в Python?
Чтобы безопасно выполнять многопоточный вывод моделей YOLO в Python, следуйте следующим рекомендациям:
- Инстанцируйте модели YOLO в каждом потоке, а не делите один экземпляр модели между потоками.
- Используйте Python's
multiprocessing
модуль для параллельной обработки, чтобы избежать проблем, связанных с глобальной блокировкой интерпретатора (GIL). - Освобождение GIL с помощью операций, выполняемых YOLO's базовыми библиотеками C.
- Рассмотрите возможность использования
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 ?
Глобальная блокировка интерпретатора Python(GIL) позволяет только одному потоку выполнять байткод Python одновременно, что может ограничить производительность многопоточных задач CPU. Однако для операций ввода-вывода или процессов, использующих библиотеки, освобождающие GIL, как, например, базовые библиотеки YOLO на языке C, вы все же можете добиться параллелизма. Для повышения производительности рассмотрите возможность использования параллелизма на основе процессов с помощью Python multiprocessing
модуль.
Подробнее о резьбе в Python см. в разделе "Понимание резьбы Python ".
Безопаснее ли использовать параллелизм на основе процессов вместо потоков для вывода моделей YOLO ?
Да, используя Python's multiprocessing
модуль является более безопасным и зачастую более эффективным для параллельного выполнения вывода модели YOLO . Параллелизм на основе процессов создает отдельные пространства памяти, что позволяет избежать глобальной блокировки интерпретатора (GIL) и снизить риск возникновения проблем с параллелизмом. Каждый процесс будет работать независимо со своим экземпляром модели YOLO .
Более подробную информацию о параллелизме на основе процессов в моделях YOLO можно найти на странице Thread-Safe Inference.