【目标检测】YOLO系列之:YOLO线程安全推理

发布于:2024-12-19 ⋅ 阅读:(13) ⋅ 点赞:(0)

1、引言

小屌丝:鱼哥,鱼哥,大动作 了
小鱼:啥啊,大动作
小屌丝:最近咱们在岛链附近的活动新闻啊
在这里插入图片描述

小鱼:嗯~ 这个新闻,确实很震撼
小屌丝:鱼哥,没想到你也关注了。
小鱼:那还用说,这是必须得。
小屌丝:鱼哥,那你预测预测接下来的动态
小鱼:安全推理
小屌丝:… 看来鱼哥很自信啊
小鱼:千秋大业,静待官宣。
小屌丝:鱼哥,可以啊。
小鱼:嗯,那就聊一聊YOLO的线程安全的事情
小屌丝:感情你现在要跟我说YOLO啊
小鱼:不然呢,我跟你说泡澡?
小屌丝:那还是说YOLO吧
小鱼:这就对了。

2、线程安全

2.1 Python线程

Python 线程是一种并行形式,允许程序同时运行多个操作。不过,Python 的全局解释器锁(GIL)意味着一次只能有一个线程执行Python 字节码。
为了便于理解,可直接看下面的流程图。

在这里插入图片描述
虽然这听起来像是一种限制,但线程仍然可以提供并发性,尤其是在 I/O 绑定操作或使用释放 GIL 的操作(如由YOLO 的底层 C 库执行的操作)时。

2.2 共享模型实例的危险

在线程外实例化YOLO 模型并在多个线程间共享该实例可能会导致竞赛条件,即由于并发访问,模型的内部状态会被不一致地修改。

当模型或其组件持有的状态不是设计为线程安全的状态时,这种情况尤其容易出现问题。

2.2.1 非线程安全示例:单个模型实例

在Python 中使用线程时,识别可能导致并发问题的模式非常重要。以下是应该避免的情况:在多个线程中共享单个YOLO 模型实例。


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)

# 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 可由多个线程同时执行。

2.2.2 非线程安全示例:多个模型实例

同样,这里基于多个模型的示例。


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)

# 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 不是线程安全的,使用单独的实例可能无法防止竞赛条件,特别是如果这些实例共享任何非线程本地的底层资源或状态。

2.3 线程安全推理

2.3.1 目的

要执行线程安全推理,应在每个线程中实例化一个单独的YOLO 模型。
这样可以确保每个线程都有自己独立的模型实例,从而消除出现竞赛条件的风险。

2.3.2 线程安全示例

接下来介绍如何在每个线程内实例化YOLO 模型,以实现安全的并行推理:

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)

# 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 实例。
  • 这可以防止任何线程干扰另一个线程的模型状态,从而确保每个线程都能安全地执行推理,而不会与其他线程发生意外的交互。

在这里插入图片描述

2.4 避坑指南

2.4.1 在多线程Python 环境中使用YOLO 模型时,如何避免竞赛条件

在多线程Python 环境中使用Ultralytics YOLO 模型时,为防止出现竞赛条件,应在每个线程中实例化一个单独的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)

Thread(target=thread_safe_predict, args=("image1.jpg",)).start()
Thread(target=thread_safe_predict, args=("image2.jpg",)).start()

2.4.2 在Python 中运行多线程YOLO 模型推理的最佳实践是什么

要在Python 中安全运行多线程YOLO 模型推理,请遵循以下最佳实践:

  • 在每个线程中实例化YOLO 模型,而不是跨线程共享单个模型实例。
  • 使用Python 的 multiprocessing 模块进行并行处理,以避免与全局解释器锁(GIL)相关的问题。
  • 通过使用YOLO 底层 C 库执行的操作释放 GIL。

线程安全模型实例化示例

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)

# Initiate multiple threads
Thread(target=thread_safe_predict, args=("image1.jpg",)).start()
Thread(target=thread_safe_predict, args=("image2.jpg",)).start()

2.4.3 Python 的全局解释器锁定(GIL)对YOLO 模型推断有何影响

Python全局解释器锁(GIL)只允许一个线程同时执行Python 字节码,这会限制与CPU 绑定的多线程任务的性能。

不过,对于 I/O 绑定操作或使用释放 GIL 的库的进程(如YOLO 的 C 库),仍然可以实现并发。

为提高性能,可考虑使用Python 的基于进程的并行功能,如 multiprocessing 模块。

3、总结

当使用YOLO 型号与Python’时 threading为了确保线程安全,我们总是在使用模型的线程中实例化模型。这种做法可以避免竞赛条件,确保推理任务可靠运行。

对于更高级的应用场景,要进一步优化多线程推理性能,可以考虑使用基于进程的并行性与 multiprocessing 或利用带有专用工作进程的任务队列。

我是小鱼

  • CSDN 博客专家
  • 阿里云 专家博主
  • 51CTO博客专家
  • 企业认证金牌面试官
  • 多个名企认证&特邀讲师等
  • 名企签约职场面试培训、职场规划师
  • 多个国内主流技术社区的认证专家博主
  • 多款主流产品(阿里云等)评测一等奖获得者

关注小鱼,学习【机器视觉与目标检测】最新最全的领域知识。


网站公告

今日签到

点亮在社区的每一天
去签到