目录
一、前言
二、加速案例
三、代码分析
一、前言
OpenCV提供了多线程处理的API。从OpenCV 4.5版本开始,它引入了对C++11标准的并行算法的支持。这意味着你可以使用多线程来加速你的OpenCV代码。在OpenCV中,利用parallel_for_接口实现并行加速。
二、加速案例
先看一个案例,以下代码中,有两个函数:
- my_test1() 函数就是一个最常见的串行处理函数(默认随便将10000个数进行加减乘除);
- my_test2() 函数是利用parallel_for_实现并行处理。
注意:opencv使用的版本是4.5。
#include<opencv2/opencv.hpp>
using namespace cv;
#include <numeric> // std::iota
const int g_num = 10000;
// 单线程
void my_test1(double* p_arr)
{
for (size_t i = 0; i < g_num; i++)
{
int p_arr_i = p_arr[i];
for (size_t j = 0; j < g_num; j++)
{
double num1 = p_arr_i * (j > 10 ? 10 : j);
double num2 = std::pow(num1, 2);
double num3 = std::sqrt(num2);
p_arr[i] = num3;
p_arr[i] = p_arr_i * num3;
p_arr[i] = p_arr[i] / num3;
}
}
}
// 多线程
void my_test2(double* p_arr)
{
parallel_for_(Range(0, g_num), [&](const Range& r)
{
for (int oc = r.start; oc < r.end; oc++)
{
// 类似于cuda核函数部分
int p_arr_i = p_arr[oc];
for (size_t j = 0; j < g_num; j++)
{
double num1 = p_arr_i * (j > 10 ? 10 : j);
double num2 = std::pow(num1, 2);
double num3 = std::sqrt(num2);
p_arr[oc] = num3;
p_arr[oc] = p_arr_i * num3;
p_arr[oc] = p_arr[oc] / num3;
}
}
});
}
int main()
{
double numbers[g_num];
int st = 0;
std::iota(numbers, numbers + g_num, st); // 100 101 102 103
double t = (double)getTickCount();
my_test1(numbers);
t = (double)getTickCount() - t;
double t2 = (double)getTickCount();
my_test2(numbers);
t2 = (double)getTickCount() - t2;
printf("my_test1 costs time = %.1fms\n", t * 1000 / getTickFrequency());
printf("my_test2 costs time = %.1fms\n", t2 * 1000 / getTickFrequency());
system("pause");
return 0;
}
如下图,my_test2函数执行速度是my_test1的10倍!
三、代码分析
对于opencv这个多线程加速(其他加速框架,例如cuda也是同理),任务必须足够复杂再有加速效果,例如:数组中,每个像素+1这种简单的任务,还不如for循环单线程快。另外就是,opencv这个并行API:parallel_for_使用简单,无非就是把适合并行的“核函数”部分写到合适位置,例如:文章来源:https://www.toymoban.com/news/detail-775808.html
parallel_for_(Range(0, g_num), [&](const Range& r)
{
for (int oc = r.start; oc < r.end; oc++)
{
// 代码中并行部分,类似于核函数部分
int p_arr_i = p_arr[oc];
for (size_t j = 0; j < g_num; j++)
{
double num1 = p_arr_i * (j > 10 ? 10 : j);
double num2 = std::pow(num1, 2);
double num3 = std::sqrt(num2);
p_arr[oc] = num3;
p_arr[oc] = p_arr_i * num3;
p_arr[oc] = p_arr[oc] / num3;
}
}
});
以下是串行处理代码,和上面并行代码对比,写法其实差不多。文章来源地址https://www.toymoban.com/news/detail-775808.html
for (size_t i = 0; i < g_num; i++)
{
int p_arr_i = p_arr[i];
for (size_t j = 0; j < g_num; j++)
{
double num1 = p_arr_i * (j > 10 ? 10 : j);
double num2 = std::pow(num1, 2);
double num3 = std::sqrt(num2);
p_arr[i] = num3;
p_arr[i] = p_arr_i * num3;
p_arr[i] = p_arr[i] / num3;
}
}
到了这里,关于opencv之并行计算多线程parallel_for_的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!