gpt4 book ai didi

C++,当每个工作线程必须执行几个不同的任务时,如何为任务实现线程池

转载 作者:行者123 更新时间:2023-11-30 05:47:07 27 4
gpt4 key购买 nike

我正在分析视频流。对于每个新图像(帧),我依次执行以下 3 个任务:

  1. 缩小图片
  2. 检测人脸
  3. 跟踪图像中最重要的 4 个面孔

为了在 4 CPU 机器上加快速度,我使用了 4 个工作线程。通过以下方式

  1. 主进程获取图像。创建 4 个工作线程,将图像分成 4 个四分之一,每个工作线程重新调整其 1/4 图像像素的大小。主进程等待线程完成并将四分之一组装成最终图像
  2. 主流程创建了 4 个新的人脸检测工作器。我检测到 4 种类型的面孔(男性、女性、婴儿、狗)。每个工作线程负责一种类型。主进程等待工作人员完成并组装结果(所有现有面孔的列表)。
  3. 主流程创建了 4 个新的面部跟踪工作器。选择 4 张最重要的面孔,每个工作人员跟踪 1 张面孔。主进程等待完成。

我的实现的问题是我没有线程池。在每个视频帧(大约每秒 30 次)上,主进程启动并杀死 12 个 worker (4 个 worker x 3 个不同的任务)。所以很多时间都浪费在了线程管理上。目前我使用 _beginthreadex() 方法为特定任务的工作线程提供午餐

所需的解决方案:我只想创建一次 4 个工作线程(每个工作线程能够执行所有 3 个不同的任务)。这些工作人员将贯穿整个视频处理过程。在每个视频帧上,主进程会将图像调整大小的任务交给工作人员,而不是检测和稍后的跟踪。

一个丑陋的实现 是每个工作线程都是一个实现所有 3 个任务的大函数。主进程只是告诉每个工作人员要执行哪个任务(工作人员有一个“切换”语句来选择请求的任务)。这是一个丑陋的解决方案,因为将来当我在管道中处理 30 个不同的任务而不是 3 个时——工作人员的代码将变得庞大。此外,这个解决方案违反了封装规则,因为它要求所有任务都驻留在同一个函数中+对于每个新任务,我需要更改工作人员的代码

一个干净的实现 是主进程为每个工作进程提供一个指向函数(要执行哪个任务)和一些参数的指针。因此,我可以轻松地在我的视频处理管道中添加新任务,而无需更改工作人员的代码,因为工作人员的代码是通用的(执行指向函数的指针并等待带有新指针的请求到达)但这里的问题是每个任务都有不同数量的参数(不同的函数接口(interface)),worker 不知道如何调用/执行给定函数的地址。

在我的案例中,使用线程池的好方法是什么,同时尽可能保持代码的通用性,并能够将其从 3 个任务扩展到 30 个。

附言- 我的代码可以在任何平台上运行(Android、iOS、linux、windows server、windows phone 等)。所以我更喜欢通用解决方案,而不是特定于操作系统或特定于编译器的解决方案

最佳答案

你的错误在于你过于专注于使用函数

一个老式的方法是有一个基类Task具有成员函数 virtual void operator()(); .然后对于任何应该是任务的事情,你都创建了 Task 的子类。包含运行所需的所有相关数据并提供对 operator() 的适当覆盖.

更现代的方法是创建 std::function<void(void)> 的任务实例它不仅适用于上述方法,而且适用于您实际拥有具有该签名以及 lambda 的函数的情况。 (或者因为你正在做多线程,可能需要类似 std::packaged_task<void(void)> 的东西;我还没有真正研究过它们是如何使用的)

无论哪种方式,一旦您的工作线程获得对任务的引用,它们就会简单地调用 task();执行任务。

关于C++,当每个工作线程必须执行几个不同的任务时,如何为任务实现线程池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28669311/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com