mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
core: add an ability to use cxx11 lambda as a parallel_for_ body
This commit is contained in:
parent
82ec76c123
commit
3c748ccf10
@ -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…
Reference in New Issue
Block a user