core: add an ability to use cxx11 lambda as a parallel_for_ body

pull/9017/head
Vladislav Sovrasov 8 years ago
parent 82ec76c123
commit 3c748ccf10
  1. 7
      doc/tutorials/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.markdown
  2. 26
      modules/core/include/opencv2/core/utility.hpp
  3. 25
      samples/cpp/tutorial_code/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.cpp

@ -153,7 +153,7 @@ The first thing is to declare a custom class that inherits from @ref cv::Paralle
`virtual void operator ()(const cv::Range& range) const`.
The range in the `operator ()` represents the subset of pixels that will be treated by an individual thread.
This splitting is done automatically to distribuate equally the computation load. We have to convert the pixel index coordinate
This splitting is done automatically to distribute equally the computation load. We have to convert the pixel index coordinate
to a 2D `[row, col]` coordinate. Also note that we have to keep a reference on the mat image to be able to modify in-place
the image.
@ -167,6 +167,11 @@ nstripes parameter in @ref cv::parallel_for_. For instance, if your processor ha
or setting `nstripes=2` should be the same as by default it will use all the processor threads available but will split the
workload only on two threads.
@note
C++ 11 standard allows to simplify the parallel implementation by get rid of the `ParallelMandelbrot` class and replacing it with lambda expression:
@snippet how_to_use_OpenCV_parallel_for_.cpp mandelbrot-parallel-call-cxx11
Results
-----------

@ -56,6 +56,10 @@
#include "opencv2/core.hpp"
#include <ostream>
#if __cplusplus >= 201103L
#include <functional>
#endif
namespace cv
{
@ -478,6 +482,28 @@ public:
*/
CV_EXPORTS void parallel_for_(const Range& range, const ParallelLoopBody& body, double nstripes=-1.);
#if __cplusplus >= 201103L
class ParallelLoopBodyLambdaWrapper : public ParallelLoopBody
{
private:
std::function<void(const Range&)> m_functor;
public:
ParallelLoopBodyLambdaWrapper(std::function<void(const Range&)> functor) :
m_functor(functor)
{ }
virtual void operator() (const cv::Range& range) const
{
m_functor(range);
}
};
inline void parallel_for_(const Range& range, std::function<void(const Range&)> functor, double nstripes=-1.)
{
parallel_for_(range, ParallelLoopBodyLambdaWrapper(functor), nstripes);
}
#endif
/////////////////////////////// forEach method of cv::Mat ////////////////////////////
template<typename _Tp, typename Functor> inline
void Mat::forEach_impl(const Functor& operation) {

@ -101,10 +101,35 @@ int main()
//! [mandelbrot-transformation]
double t1 = (double) getTickCount();
#if __cplusplus >= 201103L
//! [mandelbrot-parallel-call-cxx11]
parallel_for_(Range(0, mandelbrotImg.rows*mandelbrotImg.cols), [&](const Range& range){
for (int r = range.start; r < range.end; r++)
{
int i = r / mandelbrotImg.cols;
int j = r % mandelbrotImg.cols;
float x0 = j / scaleX + x1;
float y0 = i / scaleY + y1;
complex<float> z0(x0, y0);
uchar value = (uchar) mandelbrotFormula(z0);
mandelbrotImg.ptr<uchar>(i)[j] = value;
}
});
//! [mandelbrot-parallel-call-cxx11]
#else
//! [mandelbrot-parallel-call]
ParallelMandelbrot parallelMandelbrot(mandelbrotImg, x1, y1, scaleX, scaleY);
parallel_for_(Range(0, mandelbrotImg.rows*mandelbrotImg.cols), parallelMandelbrot);
//! [mandelbrot-parallel-call]
#endif
t1 = ((double) getTickCount() - t1) / getTickFrequency();
cout << "Parallel Mandelbrot: " << t1 << " s" << endl;

Loading…
Cancel
Save