From d22fb5f949092f78608f527a9aa4b4bb5832594a Mon Sep 17 00:00:00 2001 From: Woody Chow Date: Wed, 31 May 2017 18:16:47 +0900 Subject: [PATCH 1/2] Multithread IPP gaussian blur --- modules/imgproc/src/smooth.cpp | 68 +++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 09f790182d..29eb938bff 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -2241,6 +2241,53 @@ static bool openvx_gaussianBlur(InputArray _src, OutputArray _dst, Size ksize, #endif #ifdef HAVE_IPP +#define IPP_GAUSSIANBLUR_PARALLEL 1 + +#ifdef HAVE_IPP_IW + +class ipp_gaussianBlurParallel: public ParallelLoopBody +{ +public: + ipp_gaussianBlurParallel(::ipp::IwiImage &src, ::ipp::IwiImage &dst, int kernelSize, float sigma, ::ipp::IwiBorderType &border, bool *pOk): + m_src(src), m_dst(dst), m_kernelSize(kernelSize), m_sigma(sigma), m_border(border), m_pOk(pOk) { + *m_pOk = true; + } + ~ipp_gaussianBlurParallel() + { + } + + virtual void operator() (const Range& range) const + { + CV_INSTRUMENT_REGION_IPP() + + if(!*m_pOk) + return; + + try + { + ::ipp::IwiRoi roi = ::ipp::IwiRect(0, range.start, m_dst.m_size.width, range.end - range.start); + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, &m_src, &m_dst, m_kernelSize, m_sigma, m_border, &roi); + } + catch(::ipp::IwException e) + { + *m_pOk = false; + return; + } + } +private: + ::ipp::IwiImage &m_src; + ::ipp::IwiImage &m_dst; + + int m_kernelSize; + float m_sigma; + ::ipp::IwiBorderType &m_border; + + volatile bool *m_pOk; + const ipp_gaussianBlurParallel& operator= (const ipp_gaussianBlurParallel&); +}; + +#endif + static bool ipp_GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, double sigma1, double sigma2, int borderType ) { @@ -2272,7 +2319,26 @@ static bool ipp_GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, if(!ippBorder.m_borderType) return false; - CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, &iwSrc, &iwDst, ksize.width, (float)sigma1, ippBorder); + // IW 2017u2 has bug which doesn't allow use of partial inMem with tiling + if((((ippBorder.m_borderFlags)&ippBorderInMem) && ((ippBorder.m_borderFlags)&ippBorderInMem) != ippBorderInMem)) { + return false; + } + + bool ok; + ipp_gaussianBlurParallel invoker(iwSrc, iwDst, ksize.width, (float) sigma1, ippBorder, &ok); + + if(!ok) + return false; + + const Range range(0, (int) iwDst.m_size.height); + const int threads = ippiSuggestThreadsNum(iwDst, 2); + if(IPP_GAUSSIANBLUR_PARALLEL && threads > 1) + parallel_for_(range, invoker, threads*4); + else + invoker(range); + + if(!ok) + return false; } catch (::ipp::IwException ex) { From f743603b0ae0a8ed7a8d1144f1e9836d25afb151 Mon Sep 17 00:00:00 2001 From: Woody Chow Date: Thu, 1 Jun 2017 13:34:50 +0900 Subject: [PATCH 2/2] Fallback to single threaded version of IPP gaussian blur / bilateral filter when the mutlithreaded version cannot be called. --- modules/imgproc/src/smooth.cpp | 63 ++++++++++++++++------------------ 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/modules/imgproc/src/smooth.cpp b/modules/imgproc/src/smooth.cpp index 29eb938bff..f4510a78bd 100644 --- a/modules/imgproc/src/smooth.cpp +++ b/modules/imgproc/src/smooth.cpp @@ -2241,6 +2241,7 @@ static bool openvx_gaussianBlur(InputArray _src, OutputArray _dst, Size ksize, #endif #ifdef HAVE_IPP +#define IPP_DISABLE_FILTERING_INMEM_PARTIAL 1 // IW 2017u2 has bug which doesn't allow use of partial inMem with tiling #define IPP_GAUSSIANBLUR_PARALLEL 1 #ifdef HAVE_IPP_IW @@ -2319,26 +2320,23 @@ static bool ipp_GaussianBlur(InputArray _src, OutputArray _dst, Size ksize, if(!ippBorder.m_borderType) return false; - // IW 2017u2 has bug which doesn't allow use of partial inMem with tiling - if((((ippBorder.m_borderFlags)&ippBorderInMem) && ((ippBorder.m_borderFlags)&ippBorderInMem) != ippBorderInMem)) { - return false; - } - - bool ok; - ipp_gaussianBlurParallel invoker(iwSrc, iwDst, ksize.width, (float) sigma1, ippBorder, &ok); - - if(!ok) - return false; - - const Range range(0, (int) iwDst.m_size.height); + const bool disableThreading = IPP_DISABLE_FILTERING_INMEM_PARTIAL && + ((ippBorder.m_borderFlags)&ippBorderInMem) && ((ippBorder.m_borderFlags)&ippBorderInMem) != ippBorderInMem; const int threads = ippiSuggestThreadsNum(iwDst, 2); - if(IPP_GAUSSIANBLUR_PARALLEL && threads > 1) - parallel_for_(range, invoker, threads*4); - else - invoker(range); + if(!disableThreading && IPP_GAUSSIANBLUR_PARALLEL && threads > 1) { + bool ok; + ipp_gaussianBlurParallel invoker(iwSrc, iwDst, ksize.width, (float) sigma1, ippBorder, &ok); - if(!ok) - return false; + if(!ok) + return false; + const Range range(0, (int) iwDst.m_size.height); + parallel_for_(range, invoker, threads*4); + + if(!ok) + return false; + } else { + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterGaussian, &iwSrc, &iwDst, ksize.width, (float) sigma1, ippBorder); + } } catch (::ipp::IwException ex) { @@ -4321,24 +4319,23 @@ static bool ipp_bilateralFilter(Mat &src, Mat &dst, int d, double sigmaColor, do if(!ippBorder.m_borderType) return false; - // IW 2017u2 has bug which doesn't allow use of partial inMem with tiling - if((((ippBorder.m_borderFlags)&ippBorderInMem) && ((ippBorder.m_borderFlags)&ippBorderInMem) != ippBorderInMem)) - return false; + const bool disableThreading = IPP_DISABLE_FILTERING_INMEM_PARTIAL && + ((ippBorder.m_borderFlags)&ippBorderInMem) && ((ippBorder.m_borderFlags)&ippBorderInMem) != ippBorderInMem; + const int threads = ippiSuggestThreadsNum(iwDst, 2); + if(!disableThreading && IPP_BILATERAL_PARALLEL && threads > 1) { + bool ok = true; + Range range(0, (int)iwDst.m_size.height); + ipp_bilateralFilterParallel invoker(iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ippBorder, &ok); + if(!ok) + return false; - bool ok = true; - int threads = ippiSuggestThreadsNum(iwDst, 2); - Range range(0, (int)iwDst.m_size.height); - ipp_bilateralFilterParallel invoker(iwSrc, iwDst, radius, valSquareSigma, posSquareSigma, ippBorder, &ok); - if(!ok) - return false; - - if(IPP_BILATERAL_PARALLEL && threads > 1) parallel_for_(range, invoker, threads*4); - else - invoker(range); - if(!ok) - return false; + if(!ok) + return false; + } else { + CV_INSTRUMENT_FUN_IPP(::ipp::iwiFilterBilateral, &iwSrc, &iwDst, radius, valSquareSigma, posSquareSigma, ippiFilterBilateralGauss, ippDistNormL1, ippBorder); + } } catch (::ipp::IwException) {