Commit 5f1b6ee8 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

Merge pull request #9017 from sovrasov:parallel_for_cxx11

parents 27c7ef28 08db55fb
......@@ -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
-----------
......
......@@ -354,6 +354,20 @@ Cv64suf;
#endif
/****************************************************************************************\
* C++ 11 *
\****************************************************************************************/
#ifndef CV_CXX_11
# if __cplusplus >= 201103L || defined(_MSC_VER) && _MSC_VER >= 1600
# define CV_CXX_11 1
# endif
#else
# if CV_CXX_11 == 0
# undef CV_CXX_11
# endif
#endif
/****************************************************************************************\
* C++ Move semantics *
\****************************************************************************************/
......
......@@ -56,6 +56,10 @@
#include "opencv2/core.hpp"
#include <ostream>
#ifdef CV_CXX_11
#include <functional>
#endif
namespace cv
{
......@@ -478,6 +482,28 @@ public:
*/
CV_EXPORTS void parallel_for_(const Range& range, const ParallelLoopBody& body, double nstripes=-1.);
#ifdef CV_CXX_11
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();
#ifdef CV_CXX_11
//! [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