当前位置:   article > 正文

OpenCV中parallel_for__opencv parallel for

opencv parallel for

OpenCV 中,并行框架按照以下顺序提供:

  • 英特尔线程构建块(第三方库,应显式启用),如TBB
  • C =并行C / C ++编程语言扩展(第三方库,应明确启用)
  • OpenMP
  • APPLE GCD
  • Windows RT
  • Windows并发
  • Pthreads

         OpenCV库中可以使用多个并行框架。一些并行库是第三方库,必须在CMake(例如TBB,C =)中进行显式构建和启用,其他可以自动与平台(例如APPLE GCD)一起使用,但是您应该可以使用这些库来访问并行框架直接或通过启用CMake中的选项并重建库。

       在使用opencv的过程中,对图片的处理计算量还是很大的,所以在实施运行的程序中如何高效的计算会节省很多时间。现有的方法有很多,如OpenMp,TBB,OpenCL,当然还有Nvidia的CUDA。但是OpenMP在windows的VS上支持的很好,设置简单,效果也还不错,但是在Linux虽然也支持,
       但是我用Cmake时,感觉效果并不明显。TBB和OpenCL没有直接用过。CUDA是个好东西,但是并不太适合毫秒级别的程序运行,单一张图片在cpu和gpu之间的传输时间就已经达到300ms(我用的是opencv的cuda库函数);在TX2上直接对cuda进行编程,数据的传输也是在50ms(不包含初始化)以上,根本不能拿来做实时的运算。所以如何在cpu上更加高效的计算变得尤为重要。偶然间发现了opencv的并行计算函数parallel_for_,它整合了上述的多个组件。

步骤:

1、声明ParallelLoopBody 子类(取名为FillParallel),并实现其纯虚函数 virtual void operator() (const Range& range) const的功能;

2、实例化子类(FillParallel)的对象(取名为 fill) ;

3、调用 cv::parallel_for_()方式进行并行计算。
 

  1. #include <iostream>
  2. #include <opencv2/core.hpp>
  3. class MyParallelClass : public cv::ParallelLoopBody
  4. {
  5. };
  6. struct MyParallelStruct : public cv::ParallelLoopBody
  7. {
  8. };
  9. class ParallelAdd : public cv::ParallelLoopBody
  10. {
  11. public:
  12. ParallelAdd(const cv::Mat& _src1, const cv::Mat& _src2, float* _src3)
  13. {
  14. src1 = _src1;
  15. src2 = _src2;
  16. src3 = _src3;
  17. CV_Assert((src1.rows == src2.rows) && (src1.cols == src2.cols));
  18. rows = src1.rows;
  19. cols = src1.cols;
  20. }
  21. void operator()(const cv::Range& range) const
  22. {
  23. size_t step = src1.step1();
  24. for (int row = range.start; row < range.end; ++row)
  25. {
  26. for (int col = 0; col < src1.cols; ++col)
  27. {
  28. const float* p1 = src1.ptr<float>(row, col);
  29. const float* p2 = src2.ptr<float>(row, col);
  30. src3[row * step + col] = (*p1) * (*p2);
  31. }
  32. }
  33. }
  34. private:
  35. cv::Mat src1;
  36. cv::Mat src2;
  37. float* src3;
  38. int rows;
  39. int cols;
  40. };
  41. int main()
  42. {
  43. cv::Mat m1(cv::Mat::ones(5000, 5000, CV_32F));
  44. cv::Mat m2(cv::Mat::ones(5000, 5000, CV_32F));
  45. int64 t1 = cv::getTickCount();
  46. //直接调用
  47. cv::Mat r3(m1.rows, m1.cols, m1.type());
  48. cv::Ptr<ParallelAdd> add= cv::makePtr<ParallelAdd>(m1, m2, (float*)r3.data);
  49. (*add)(cv::Range(0, m1.rows)); //直接调用,没有并发
  50. //add->operator()(cv::Range(0, m1.cols));
  51. int64 t2 = cv::getTickCount();
  52. std::cout << "time: " << (t2 - t1)/cv::getTickFrequency() * 1000 << " ms" << std::endl;
  53. cv::Mat r4(m1.size(), m1.type());
  54. cv::parallel_for_(cv::Range(0, m1.rows), ParallelAdd(m1, m2, (float*)r3.data));//隐式调用,并发
  55. int64 t3 = cv::getTickCount();
  56. std::cout << "parallel time: " << (t3 - t2) / cv::getTickFrequency() * 1000 << " ms" << std::endl;
  57. int64 t4 = cv::getTickCount();
  58. cv::Mat r5 = m1.mul(m2);
  59. std::cout << "mat mul: " << (t4 - t3) / cv::getTickFrequency() * 1000 << " ms" << std::endl;
  60. return 1;
  61. }
  62. time: 1074.81 ms
  63. parallel time: 160.62 ms
  64. mat mul: 0.775 ms

总结:使用 parallel_for_ 并发的方式的确比直接调用快一些,但是没有使用 OpenCV 自带的标准函数 mul 函数速度快,因为,OpenCV 实现的函数库不仅仅经过了并行处理,还是用了更强大的底层优化,所以,只要是 OpenCV 一般都是优先使用,除非自己写的比 OpenCV 的还牛逼一些。

最重要的注意点:

T1 = T2 + T3;

可以为T1 = T2.operator+(T3);

也可以为T1  = operator+(T2,T3);

但是这两种方式不能同时声明定义,因为这会出现二义性。造成程序不知道该执行那个函数。在进行运算符重载的时候千万要注意造成二义性的情况。


 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/657427
推荐阅读
相关标签
  

闽ICP备14008679号