目录
OpenCV提供了多线程处理的API。从OpenCV 4.5版本开始,它引入了对C++11标准的并行算法的支持。这意味着你可以使用多线程来加速你的OpenCV代码。在OpenCV中,利用parallel_for_接口实现并行加速。
先看一个案例,以下代码中,有两个函数:
注意:opencv使用的版本是4.5。
- #include
- using namespace cv;
- #include
// 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_使用简单,无非就是把适合并行的“核函数”部分写到合适位置,例如:
- 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;
- }
- }
- });
以下是串行处理代码,和上面并行代码对比,写法其实差不多。
- 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;
- }
- }