Commit 3c748ccf authored by Vladislav Sovrasov's avatar Vladislav Sovrasov

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

parent 82ec76c1
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment