【发布时间】:2021-05-21 05:10:53
【问题描述】:
我开发了一个需要同时处理不同图像的 C++ 应用程序。处理算法建立在 OpenCV 之上并使用并行功能。
该应用程序以下列方式工作:对于它拥有的每个图像,它都会产生一个线程来执行处理算法。不幸的是,这种方案似乎不适用于 OpenCV 内部多线程。
简单示例:
#include <iostream>
#include <thread>
#include <chrono>
#include <opencv2/core.hpp>
void run(int thread_id, cv::Mat& mat)
{
auto start = std::chrono::steady_clock::now();
// multithreaded operation on mat
mat.forEach<float>([](float& pixel, int const* position) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
});
auto end = std::chrono::steady_clock::now();
std::cout << "thread " << thread_id << " took "
<< (end - start).count() * 1e-9 << " sec"
<< std::endl;
}
int main()
{
cv::Mat mat1(100, 100, CV_32F), mat2(100, 100, CV_32F);
std::thread t1(run, 1, std::ref(mat1));
std::thread t2(run, 2, std::ref(mat2));
t1.join();
t2.join();
return 0;
}
我的机器上的输出:
thread 1 took 1.42477 sec
thread 2 took 12.1963 sec
似乎第二个操作没有利用多线程。查看我的 CPU 使用率,我感觉 OpenCV 将其所有内部线程分配给第一个操作,而当第二个操作到达时,就没有内部线程了。因此,第二个操作在应用程序线程体中顺序执行。
首先,如果有人已经在 OpenCV 上遇到过类似问题,可以确认我的假设是正确的,我将不胜感激。
其次,有没有办法更智能地调度内部 OpenCV 资源?例如,通过将一半线程分配给第一个操作,将一半分配给第二个操作?
多线程目标
写完我的问题后,我意识到在应用程序级别执行多线程的目的可能还不清楚。有些人可能会争辩说,在应用程序级别按顺序运行这两个操作就足够了,以充分利用内部 OpenCV 多线程。对于我在此处发布的最小示例来说确实如此,但通常并非处理算法的所有部分都可以并行运行。
应用程序级别的多线程背后的想法是尝试同时运行最多“不可并行”的操作:
Operations 1 and 2 sequentially:
[-----seq 1----][-par 2 (full power)-][-----seq 2----][-par 2 (full power)-]
Operations 1 and 2 in parallel:
[-----seq 1----][------------par 2 (half power)------------]
[-----seq 2----][------------par 2 (half power)------------]
seq X = sequential task of operation X
par X = parallelisable task of operation X
我们可以看到应用级多线程减少了总计算时间,因为不同操作的顺序部分是并发运行的。
【问题讨论】:
-
为什么要同时加入线程?为什么不在
std::thread t1(run, 1, std::ref(mat1));之后出现t1.join()? -
@YunusTemurlenk 如果我这样做,程序将等待第一个线程结束,然后再开始第二个线程。这不是我想要的。
-
在这种情况下你应该使用
detach而不是join -
@YunusTemurlenk 我的目标是启动两个线程,等待它们结束,然后结束程序。使用
detach(),我将无法等待它们结束,所以当程序到达return语句时,它们将被突然杀死。 -
您可以使用
cv::setNumThreads()设置opencv 用于并行化的线程数 - 请参阅here。不幸的是,它不像能够将并行化因子传递给Mat::forEach()那样灵活——它只是在opencv中设置了一个类似单例的类的值。
标签: c++ multithreading opencv