OpenCV中parallel_for 和 parallel_for_学习笔记

原地址:http://blog.csdn.net/chouclee/article/details/8682561

 

OpenCV 从2.4.3开始加入了并行计算的函数parallel_for和parallel_for_(更准确地讲,parallel_for以前就存在于tbb模块中,但是OpenCV官网将其列在2.4.3.的New Features中,应该是重新改写过的)。

2.4.3中自带的calcOpticalFlowPyrLK函数也用parallel_for重写过了,之前我一直认为parallel_for就是用来并行计算的,之前也自己写了一些用parallel_for实现的算法。直到今天在opencv官网中看到别人的提问,才发现parallel_for实际上是serial loop,而parallel_for_才是parallel loop(OpenCV官网answer)。

为了比较for循环,parallel_for和parallel_for_ 三者的差异,下面做了一个简单的测试,对一个Mat中所有的元素(按列为单位)做立方操作。


Code

test.hpp

  1. /**@ Test parallel_for and parallel_for_ 
  2. /**@ Author: chouclee 
  3. /**@ 03/17/2013*/  
  4. #include <opencv2/core/internal.hpp>   
  5. namespace cv  
  6. {  
  7. namespace test  
  8. {  
  9.     class parallelTestBody : public ParallelLoopBody//参考官方给出的answer,构造一个并行的循环体类  
  10.     {  
  11.     public:  
  12.         parallelTestBody(Mat& _src)//class constructor  
  13.         {  
  14.             src = &_src;  
  15.         }  
  16.         void operator()(const Range& range) const//重载操作符()  
  17.         {  
  18.             Mat& srcMat = *src;  
  19.             int stepSrc = (int)(srcMat.step/srcMat.elemSize1());//获取每一行的元素总个数(相当于cols*channels,等同于step1)  
  20.             for (int colIdx = range.start; colIdx < range.end; ++colIdx)  
  21.             {  
  22.                 float* pData = (float*)srcMat.col(colIdx).data;  
  23.                 for (int i = 0; i < srcMat.rows; ++i)  
  24.                     pData[i*stepSrc] = std::pow(pData[i*stepSrc],3);  
  25.             }     
  26.         }  
  27.   
  28.     private:  
  29.         Mat* src;  
  30.     };  
  31.   
  32.     struct parallelTestInvoker//构造一个供parallel_for使用的循环结构体  
  33.     {  
  34.         parallelTestInvoker(Mat& _src)//struct constructor  
  35.         {  
  36.             src = &_src;  
  37.         }  
  38.         void operator()(const BlockedRange& range) const//使用BlockedRange需要包含opencv2/core/internal.hpp  
  39.         {  
  40.             Mat& srcMat = *src;  
  41.             int stepSrc = (int)(srcMat.step/srcMat.elemSize1());  
  42.             for (int colIdx = range.begin(); colIdx < range.end(); ++colIdx)  
  43.             {  
  44.                 float* pData = (float*)srcMat.col(colIdx).data;  
  45.                 for (int i = 0; i < srcMat.rows; ++i)  
  46.                     pData[i*stepSrc] = std::pow(pData[i*stepSrc],3);  
  47.             }  
  48.         }  
  49.         Mat* src;  
  50.     };  
  51. }//namesapce test   
  52. void parallelTestWithFor(InputArray _src)//'for' loop  
  53. {  
  54.     CV_Assert(_src.kind() == _InputArray::MAT);  
  55.     Mat src = _src.getMat();  
  56.     CV_Assert(src.isContinuous());  
  57.     int stepSrc = (int)(src.step/src.elemSize1());  
  58.     for (int x = 0; x < src.cols; ++x)  
  59.     {  
  60.         float* pData = (float*)src.col(x).data;  
  61.         for (int y = 0; y < src.rows; ++y)  
  62.             pData[y*stepSrc] = std::pow(pData[y*stepSrc], 3);  
  63.     }  
  64. };  
  65.   
  66. void parallelTestWithParallel_for(InputArray _src)//'parallel_for' loop  
  67. {  
  68.     CV_Assert(_src.kind() == _InputArray::MAT);  
  69.     Mat src = _src.getMat();  
  70.     int totalCols = src.cols;  
  71.     typedef test::parallelTestInvoker parallelTestInvoker;  
  72.     parallel_for(BlockedRange(0, totalCols), parallelTestInvoker(src));  
  73. };  
  74.   
  75. void parallelTestWithParallel_for_(InputArray _src)//'parallel_for_' loop  
  76. {  
  77.     CV_Assert(_src.kind() == _InputArray::MAT);  
  78.     Mat src = _src.getMat();  
  79.     int totalCols = src.cols;  
  80.     typedef test::parallelTestBody parallelTestBody;  
  81.     parallel_for_(Range(0, totalCols), parallelTestBody(src));  
  82. };  
  83. }//namespace cv  
 
 
main.cpp

  1. /**@ Test parallel_for and parallel_for_ 
  2. /**@ Author: chouclee 
  3. /**@ 03/17/2013*/  
  4. #include <opencv2/opencv.hpp>   
  5. #include <time.h>   
  6. #include "test.hpp"   
  7. using namespace cv;  
  8. using namespace std;  
  9.   
  10. int main(int argc, char* argv[])  
  11. {  
  12.     Mat testInput = Mat::ones(40,400000, CV_32F);  
  13.     clock_t start, stop;  
  14.   
  15.     start = clock();  
  16.     parallelTestWithFor(testInput);  
  17.     stop = clock();  
  18.     cout<<"Running time using \'for\':"<<(double)(stop - start)/CLOCKS_PER_SEC*1000<<"ms"<<endl;  
  19.   
  20.     start = clock();  
  21.     parallelTestWithParallel_for(testInput);  
  22.     stop = clock();  
  23.     cout<<"Running time using \'parallel_for\':"<<(double)(stop - start)/CLOCKS_PER_SEC*1000<<"ms"<<endl;  
  24.   
  25.     start = clock();  
  26.     parallelTestWithParallel_for_(testInput);  
  27.     stop = clock();  
  28.     cout<<"Running time using \'parallel_for_\':"<<(double)(stop - start)/CLOCKS_PER_SEC*1000<<"ms"<<endl;  
  29.   
  30.     system("pause");  
  31. }  
 
Result
输入为400000*40时,结果如下:
Debug模式
Running time using 'for': 1376ms
Running time using 'parallel_for': 1316ms
Running time using 'parallel_for_': 553ms
Release模式
Running time using 'for': 463ms
Running time using 'parallel_for': 475ms
Running time using 'parallel_for_': 301ms

输入改为40*400000
Debug模式
Running time using 'for': 1005ms
Running time using 'parallel_for': 1013ms
Running time using 'parallel_for_': 526ms
Release模式
Running time using 'for': 105ms
Running time using 'parallel_for': 106ms
Running time using 'parallel_for_': 81ms

输入改为4000*4000
Debug模式
Running time using 'for': 1138ms
Running time using 'parallel_for': 1136ms
Running time using 'parallel_for_': 411ms
Release模式
Running time using 'for': 234ms
Running time using 'parallel_for': 239ms
Running time using 'parallel_for_': 130ms

大多数情况下,parallel_for比for循环慢那么一丁丁点儿,有时甚至会比for循环快一些,总体上两者差不多,parallel_for_一直都是最快的。但上面的代码只是做测试使用(因此强制按列进行操作),实际上,像上面这种简单的操作,直接对Mat使用for循环和指针递增操作,只需要几十毫秒。但是,对于复杂算法,比如光流或之类的,使用parallel_for(虽然不是并行操作,但代码简洁易于维护,且速度和for循环差不多)或者parallel_for_将是不错的选择。


Reference:

http://answers.opencv.org/question/3730/how-to-use-parallel_for/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值