Skip to content

Commit 5f1b6ee

Browse files
committed
Merge pull request opencv#9017 from sovrasov:parallel_for_cxx11
2 parents 27c7ef2 + 08db55f commit 5f1b6ee

File tree

4 files changed

+71
-1
lines changed

4 files changed

+71
-1
lines changed

doc/tutorials/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.markdown

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ The first thing is to declare a custom class that inherits from @ref cv::Paralle
153153
`virtual void operator ()(const cv::Range& range) const`.
154154

155155
The range in the `operator ()` represents the subset of pixels that will be treated by an individual thread.
156-
This splitting is done automatically to distribuate equally the computation load. We have to convert the pixel index coordinate
156+
This splitting is done automatically to distribute equally the computation load. We have to convert the pixel index coordinate
157157
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
158158
the image.
159159

@@ -167,6 +167,11 @@ nstripes parameter in @ref cv::parallel_for_. For instance, if your processor ha
167167
or setting `nstripes=2` should be the same as by default it will use all the processor threads available but will split the
168168
workload only on two threads.
169169

170+
@note
171+
C++ 11 standard allows to simplify the parallel implementation by get rid of the `ParallelMandelbrot` class and replacing it with lambda expression:
172+
173+
@snippet how_to_use_OpenCV_parallel_for_.cpp mandelbrot-parallel-call-cxx11
174+
170175
Results
171176
-----------
172177

modules/core/include/opencv2/core/cvdef.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,20 @@ Cv64suf;
354354
#endif
355355

356356

357+
/****************************************************************************************\
358+
* C++ 11 *
359+
\****************************************************************************************/
360+
#ifndef CV_CXX_11
361+
# if __cplusplus >= 201103L || defined(_MSC_VER) && _MSC_VER >= 1600
362+
# define CV_CXX_11 1
363+
# endif
364+
#else
365+
# if CV_CXX_11 == 0
366+
# undef CV_CXX_11
367+
# endif
368+
#endif
369+
370+
357371
/****************************************************************************************\
358372
* C++ Move semantics *
359373
\****************************************************************************************/

modules/core/include/opencv2/core/utility.hpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@
5656
#include "opencv2/core.hpp"
5757
#include <ostream>
5858

59+
#ifdef CV_CXX_11
60+
#include <functional>
61+
#endif
62+
5963
namespace cv
6064
{
6165

@@ -478,6 +482,28 @@ class CV_EXPORTS ParallelLoopBody
478482
*/
479483
CV_EXPORTS void parallel_for_(const Range& range, const ParallelLoopBody& body, double nstripes=-1.);
480484

485+
#ifdef CV_CXX_11
486+
class ParallelLoopBodyLambdaWrapper : public ParallelLoopBody
487+
{
488+
private:
489+
std::function<void(const Range&)> m_functor;
490+
public:
491+
ParallelLoopBodyLambdaWrapper(std::function<void(const Range&)> functor) :
492+
m_functor(functor)
493+
{ }
494+
495+
virtual void operator() (const cv::Range& range) const
496+
{
497+
m_functor(range);
498+
}
499+
};
500+
501+
inline void parallel_for_(const Range& range, std::function<void(const Range&)> functor, double nstripes=-1.)
502+
{
503+
parallel_for_(range, ParallelLoopBodyLambdaWrapper(functor), nstripes);
504+
}
505+
#endif
506+
481507
/////////////////////////////// forEach method of cv::Mat ////////////////////////////
482508
template<typename _Tp, typename Functor> inline
483509
void Mat::forEach_impl(const Functor& operation) {

samples/cpp/tutorial_code/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,35 @@ int main()
101101
//! [mandelbrot-transformation]
102102

103103
double t1 = (double) getTickCount();
104+
105+
#ifdef CV_CXX_11
106+
107+
//! [mandelbrot-parallel-call-cxx11]
108+
parallel_for_(Range(0, mandelbrotImg.rows*mandelbrotImg.cols), [&](const Range& range){
109+
for (int r = range.start; r < range.end; r++)
110+
{
111+
int i = r / mandelbrotImg.cols;
112+
int j = r % mandelbrotImg.cols;
113+
114+
float x0 = j / scaleX + x1;
115+
float y0 = i / scaleY + y1;
116+
117+
complex<float> z0(x0, y0);
118+
uchar value = (uchar) mandelbrotFormula(z0);
119+
mandelbrotImg.ptr<uchar>(i)[j] = value;
120+
}
121+
});
122+
//! [mandelbrot-parallel-call-cxx11]
123+
124+
#else
125+
104126
//! [mandelbrot-parallel-call]
105127
ParallelMandelbrot parallelMandelbrot(mandelbrotImg, x1, y1, scaleX, scaleY);
106128
parallel_for_(Range(0, mandelbrotImg.rows*mandelbrotImg.cols), parallelMandelbrot);
107129
//! [mandelbrot-parallel-call]
130+
131+
#endif
132+
108133
t1 = ((double) getTickCount() - t1) / getTickFrequency();
109134
cout << "Parallel Mandelbrot: " << t1 << " s" << endl;
110135

0 commit comments

Comments
 (0)