1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 08:13:04 +04:00

IPP for OpenCV 2017u2 initial enabling patch;

This commit is contained in:
Pavel Vlasov
2017-04-13 15:50:23 +03:00
parent 1c728258e0
commit 35c7216846
27 changed files with 2087 additions and 1848 deletions
@@ -671,7 +671,11 @@ namespace cudev
namespace ipp
{
#if OPENCV_ABI_COMPATIBILITY > 300
CV_EXPORTS unsigned long long getIppFeatures();
#else
CV_EXPORTS int getIppFeatures();
#endif
CV_EXPORTS void setIppStatus(int status, const char * const funcname = NULL, const char * const filename = NULL,
int line = 0);
CV_EXPORTS int getIppStatus();
+234 -19
View File
@@ -185,28 +185,78 @@ CV_EXPORTS void scalarToRawData(const cv::Scalar& s, void* buf, int type, int un
* Structures and macros for integration with IPP *
\****************************************************************************************/
#ifdef HAVE_IPP
#include "ipp.h"
// Temporary disabled named IPP region. Accuracy
#define IPP_DISABLE_PYRAMIDS_UP 1 // Different results
#define IPP_DISABLE_PYRAMIDS_DOWN 1 // Different results
#define IPP_DISABLE_PYRAMIDS_BUILD 1 // Different results
#define IPP_DISABLE_WARPAFFINE 1 // Different results
#define IPP_DISABLE_WARPPERSPECTIVE 1 // Different results
#define IPP_DISABLE_REMAP 1 // Different results
#define IPP_DISABLE_MORPH_ADV 1 // mask flipping in IPP
#define IPP_DISABLE_SORT_IDX 0 // different order in index tables
#define IPP_DISABLE_YUV_RGB 1 // accuracy difference
#define IPP_DISABLE_RGB_YUV 1 // breaks OCL accuracy tests
#define IPP_DISABLE_RGB_HSV 1 // breaks OCL accuracy tests
#define IPP_DISABLE_RGB_LAB 1 // breaks OCL accuracy tests
#define IPP_DISABLE_LAB_RGB 1 // breaks OCL accuracy tests
#define IPP_DISABLE_RGB_XYZ 1 // big accuracy difference
#define IPP_DISABLE_XYZ_RGB 1 // big accuracy difference
#define IPP_DISABLE_HAAR 1 // improper integration/results
#define IPP_DISABLE_HOUGH 1 // improper integration/results
#define IPP_DISABLE_RESIZE_8U 1 // Incompatible accuracy
#define IPP_DISABLE_RESIZE_NEAREST 1 // Accuracy mismatch (max diff 1)
#define IPP_DISABLE_RESIZE_AREA 1 // Accuracy mismatch (max diff 1)
// Temporary disabled named IPP region. Performance
#define IPP_DISABLE_PERF_COPYMAKE 1 // performance variations
#define IPP_DISABLE_PERF_LUT 1 // there are no performance benefits (PR #2653)
#define IPP_DISABLE_PERF_TRUE_DIST_MT 1 // cv::distanceTransform OpenCV MT performance is better
#define IPP_DISABLE_PERF_CANNY_MT 1 // cv::Canny OpenCV MT performance is better
#define IPP_DISABLE_PERF_HISTU32F_SSE42 1 // cv::calcHist optimizations problem
#define IPP_DISABLE_PERF_MORPH_SSE42 1 // cv::erode, cv::dilate optimizations problem
#define IPP_DISABLE_PERF_MAG_SSE42 1 // cv::magnitude optimizations problem
#define IPP_DISABLE_PERF_BOX16S_SSE42 1 // cv::boxFilter optimizations problem
#define IPP_DISABLE_BLOCK 0 // legacy switch
#ifdef HAVE_IPP
#include "ippversion.h"
#ifndef IPP_VERSION_UPDATE // prior to 7.1
#define IPP_VERSION_UPDATE 0
#endif
#define IPP_VERSION_X100 (IPP_VERSION_MAJOR * 100 + IPP_VERSION_MINOR*10 + IPP_VERSION_UPDATE)
// General define for ipp function disabling
#define IPP_DISABLE_BLOCK 0
#ifdef HAVE_IPP_ICV_ONLY
#define ICV_BASE
#if IPP_VERSION_X100 >= 201700
#include "ippicv.h"
#else
#include "ipp.h"
#endif
#else
#include "ipp.h"
#endif
#ifdef HAVE_IPP_IW
#include "iw++/iw.hpp"
#endif
#ifdef CV_MALLOC_ALIGN
#undef CV_MALLOC_ALIGN
#endif
#define CV_MALLOC_ALIGN 32 // required for AVX optimization
#if IPP_VERSION_X100 >= 201700
#define CV_IPP_MALLOC(SIZE) ippMalloc_L(SIZE)
#else
#define CV_IPP_MALLOC(SIZE) ippMalloc((int)SIZE)
#endif
#define setIppErrorStatus() cv::ipp::setIppStatus(-1, CV_Func, __FILE__, __LINE__)
static inline IppiSize ippiSize(int width, int height)
static inline IppiSize ippiSize(size_t width, size_t height)
{
IppiSize size = { width, height };
IppiSize size = { (int)width, (int)height };
return size;
}
@@ -216,6 +266,20 @@ static inline IppiSize ippiSize(const cv::Size & _size)
return size;
}
#if IPP_VERSION_X100 >= 201700
static inline IppiSizeL ippiSizeL(size_t width, size_t height)
{
IppiSizeL size = { (IppSizeL)width, (IppSizeL)height };
return size;
}
static inline IppiSizeL ippiSizeL(const cv::Size & _size)
{
IppiSizeL size = { _size.width, _size.height };
return size;
}
#endif
static inline IppiPoint ippiPoint(const cv::Point & _point)
{
IppiPoint point = { _point.x, _point.y };
@@ -230,34 +294,177 @@ static inline IppiPoint ippiPoint(int x, int y)
static inline IppiBorderType ippiGetBorderType(int borderTypeNI)
{
return borderTypeNI == cv::BORDER_CONSTANT ? ippBorderConst :
borderTypeNI == cv::BORDER_WRAP ? ippBorderWrap :
borderTypeNI == cv::BORDER_REPLICATE ? ippBorderRepl :
borderTypeNI == cv::BORDER_REFLECT_101 ? ippBorderMirror :
borderTypeNI == cv::BORDER_REFLECT ? ippBorderMirrorR : (IppiBorderType)-1;
return borderTypeNI == cv::BORDER_CONSTANT ? ippBorderConst :
borderTypeNI == cv::BORDER_TRANSPARENT ? ippBorderTransp :
borderTypeNI == cv::BORDER_REPLICATE ? ippBorderRepl :
borderTypeNI == cv::BORDER_REFLECT_101 ? ippBorderMirror :
(IppiBorderType)-1;
}
static inline IppiMaskSize ippiGetMaskSize(int kx, int ky)
{
return (kx == 1 && ky == 3) ? ippMskSize1x3 :
(kx == 1 && ky == 5) ? ippMskSize1x5 :
(kx == 3 && ky == 1) ? ippMskSize3x1 :
(kx == 3 && ky == 3) ? ippMskSize3x3 :
(kx == 5 && ky == 1) ? ippMskSize5x1 :
(kx == 5 && ky == 5) ? ippMskSize5x5 :
(IppiMaskSize)-1;
}
static inline IppDataType ippiGetDataType(int depth)
{
depth = CV_MAT_DEPTH(depth);
return depth == CV_8U ? ipp8u :
depth == CV_8S ? ipp8s :
depth == CV_16U ? ipp16u :
depth == CV_16S ? ipp16s :
depth == CV_32S ? ipp32s :
depth == CV_32F ? ipp32f :
depth == CV_64F ? ipp64f : (IppDataType)-1;
depth == CV_64F ? ipp64f :
(IppDataType)-1;
}
// IPP temporary buffer hepler
#ifdef HAVE_IPP_IW
static inline IwiDerivativeType ippiGetDerivType(int dx, int dy, bool nvert)
{
return (dx == 1 && dy == 0) ? ((nvert)?iwiDerivNVerFirst:iwiDerivVerFirst) :
(dx == 0 && dy == 1) ? iwiDerivHorFirst :
(dx == 2 && dy == 0) ? iwiDerivVerSecond :
(dx == 0 && dy == 2) ? iwiDerivHorSecond :
(IwiDerivativeType)-1;
}
static inline void ippiGetImage(const cv::Mat &src, ::ipp::IwiImage &dst)
{
::ipp::IwiBorderSize inMemBorder;
if(src.isSubmatrix()) // already have physical border
{
cv::Size origSize;
cv::Point offset;
src.locateROI(origSize, offset);
inMemBorder.borderLeft = (Ipp32u)offset.x;
inMemBorder.borderTop = (Ipp32u)offset.y;
inMemBorder.borderRight = (Ipp32u)(origSize.width - src.cols - offset.x);
inMemBorder.borderBottom = (Ipp32u)(origSize.height - src.rows - offset.y);
}
dst.Init(ippiSize(src.size()), ippiGetDataType(src.depth()), src.channels(), inMemBorder, (void*)src.ptr(), src.step);
}
static inline ::ipp::IwiImage ippiGetImage(const cv::Mat &src)
{
::ipp::IwiImage image;
ippiGetImage(src, image);
return image;
}
static inline IppiBorderType ippiGetBorder(::ipp::IwiImage &image, int ocvBorderType, IppiBorderSize &borderSize)
{
int inMemFlags = 0;
IppiBorderType border = ippiGetBorderType(ocvBorderType & ~cv::BORDER_ISOLATED);
if((int)border == -1)
return (IppiBorderType)0;
if(!(ocvBorderType & cv::BORDER_ISOLATED))
{
if(image.m_inMemSize.borderLeft)
{
if(image.m_inMemSize.borderLeft >= borderSize.borderLeft)
inMemFlags |= ippBorderInMemLeft;
else
return (IppiBorderType)0;
}
else
borderSize.borderLeft = 0;
if(image.m_inMemSize.borderTop)
{
if(image.m_inMemSize.borderTop >= borderSize.borderTop)
inMemFlags |= ippBorderInMemTop;
else
return (IppiBorderType)0;
}
else
borderSize.borderTop = 0;
if(image.m_inMemSize.borderRight)
{
if(image.m_inMemSize.borderRight >= borderSize.borderRight)
inMemFlags |= ippBorderInMemRight;
else
return (IppiBorderType)0;
}
else
borderSize.borderRight = 0;
if(image.m_inMemSize.borderBottom)
{
if(image.m_inMemSize.borderBottom >= borderSize.borderBottom)
inMemFlags |= ippBorderInMemBottom;
else
return (IppiBorderType)0;
}
else
borderSize.borderBottom = 0;
}
else
borderSize.borderLeft = borderSize.borderRight = borderSize.borderTop = borderSize.borderBottom = 0;
return (IppiBorderType)(border|inMemFlags);
}
static inline ::ipp::IwValue ippiGetValue(const cv::Scalar &scalar)
{
return ::ipp::IwValue(scalar[0], scalar[1], scalar[2], scalar[3]);
}
static inline int ippiSuggestThreadsNum(const ::ipp::IwiImage &image, double multiplier)
{
int threads = cv::getNumThreads();
if(image.m_size.height > threads)
{
size_t opMemory = (int)(image.m_step*image.m_size.height*multiplier);
int l2cache = 0;
#if IPP_VERSION_X100 >= 201700
ippGetL2CacheSize(&l2cache);
#endif
if(!l2cache)
l2cache = 1 << 18;
return IPP_MAX(1, (IPP_MIN((int)(opMemory/l2cache), threads)));
}
return 1;
}
#endif
static inline int ippiSuggestThreadsNum(const cv::Mat &image, double multiplier)
{
int threads = cv::getNumThreads();
if(image.rows > threads)
{
size_t opMemory = (int)(image.total()*multiplier);
int l2cache = 0;
#if IPP_VERSION_X100 >= 201700
ippGetL2CacheSize(&l2cache);
#endif
if(!l2cache)
l2cache = 1 << 18;
return IPP_MAX(1, (IPP_MIN((int)(opMemory/l2cache), threads)));
}
return 1;
}
// IPP temporary buffer helper
template<typename T>
class IppAutoBuffer
{
public:
IppAutoBuffer() { m_pBuffer = NULL; }
IppAutoBuffer(int size) { Alloc(size); }
~IppAutoBuffer() { Release(); }
T* Alloc(int size) { m_pBuffer = (T*)ippMalloc(size); return m_pBuffer; }
void Release() { if(m_pBuffer) ippFree(m_pBuffer); }
IppAutoBuffer() { m_size = 0; m_pBuffer = NULL; }
IppAutoBuffer(size_t size) { m_size = 0; m_pBuffer = NULL; allocate(size); }
~IppAutoBuffer() { deallocate(); }
T* allocate(size_t size) { if(m_size < size) { deallocate(); m_pBuffer = (T*)CV_IPP_MALLOC(size); m_size = size; } return m_pBuffer; }
void deallocate() { if(m_pBuffer) { ippFree(m_pBuffer); m_pBuffer = NULL; } m_size = 0; }
inline T* get() { return (T*)m_pBuffer;}
inline operator T* () { return (T*)m_pBuffer;}
inline operator const T* () const { return (const T*)m_pBuffer;}
private:
@@ -265,9 +472,17 @@ private:
IppAutoBuffer(IppAutoBuffer &) {}
IppAutoBuffer& operator =(const IppAutoBuffer &) {return *this;}
T* m_pBuffer;
size_t m_size;
T* m_pBuffer;
};
// Extracts border interpolation type without flags
#if IPP_VERSION_MAJOR >= 2017
#define IPP_BORDER_INTER(BORDER) (IppiBorderType)((BORDER)&0xF|((((BORDER)&ippBorderInMem) == ippBorderInMem)?ippBorderInMem:0));
#else
#define IPP_BORDER_INTER(BORDER) (IppiBorderType)((BORDER)&0xF);
#endif
#else
#define IPP_VERSION_X100 0
#endif
+1 -1
View File
@@ -139,7 +139,7 @@ OCL_PERF_TEST_P(CopyToFixture, CopyToWithMaskUninit,
dst.release();
startTimer();
src.copyTo(dst, mask);
cv::ocl::finish();
cvtest::ocl::perf::safeFinish();
stopTimer();
}
+1 -1
View File
@@ -5512,7 +5512,7 @@ public:
size_t elemSize1 = dst.elemSize1();
CV_DbgAssert(elemSize1 == 1);
lutBuffer = (uchar*)ippMalloc(256 * (int)elemSize1 * 4);
lutBuffer = (uchar*)CV_IPP_MALLOC(256 * (int)elemSize1 * 4);
lutTable[0] = lutBuffer + 0;
lutTable[1] = lutBuffer + 1 * 256 * elemSize1;
lutTable[2] = lutBuffer + 2 * 256 * elemSize1;
+1 -7
View File
@@ -298,13 +298,7 @@ void Mat::copyTo( OutputArray _dst ) const
const uchar* sptr = data;
uchar* dptr = dst.data;
CV_IPP_RUN(
(size_t)cols*elemSize() <= (size_t)INT_MAX &&
(size_t)step <= (size_t)INT_MAX &&
(size_t)dst.step <= (size_t)INT_MAX
,
CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R, sptr, (int)step, dptr, (int)dst.step, ippiSize((int)(cols*elemSize()), rows)) >= 0
)
CV_IPP_RUN_FAST(CV_INSTRUMENT_FUN_IPP(ippiCopy_8u_C1R_L, sptr, (int)step, dptr, (int)dst.step, ippiSizeL((int)(cols*elemSize()), rows)) >= 0)
Size sz = getContinuousSize(*this, dst);
size_t len = sz.width*elemSize();
+18 -18
View File
@@ -1580,13 +1580,13 @@ public:
return;
}
IppiDFTSpec_C_32fc* pDFTSpec = (IppiDFTSpec_C_32fc*)ippMalloc( sizeSpec );
IppiDFTSpec_C_32fc* pDFTSpec = (IppiDFTSpec_C_32fc*)CV_IPP_MALLOC( sizeSpec );
if ( sizeInit > 0 )
pMemInit = (Ipp8u*)ippMalloc( sizeInit );
pMemInit = (Ipp8u*)CV_IPP_MALLOC( sizeInit );
if ( sizeBuffer > 0 )
pBuffer = (Ipp8u*)ippMalloc( sizeBuffer );
pBuffer = (Ipp8u*)CV_IPP_MALLOC( sizeBuffer );
status = ippiDFTInit_C_32fc( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit );
@@ -1661,13 +1661,13 @@ public:
return;
}
IppiDFTSpec_R_32f* pDFTSpec = (IppiDFTSpec_R_32f*)ippMalloc( sizeSpec );
IppiDFTSpec_R_32f* pDFTSpec = (IppiDFTSpec_R_32f*)CV_IPP_MALLOC( sizeSpec );
if ( sizeInit > 0 )
pMemInit = (Ipp8u*)ippMalloc( sizeInit );
pMemInit = (Ipp8u*)CV_IPP_MALLOC( sizeInit );
if ( sizeBuffer > 0 )
pBuffer = (Ipp8u*)ippMalloc( sizeBuffer );
pBuffer = (Ipp8u*)CV_IPP_MALLOC( sizeBuffer );
status = ippiDFTInit_R_32f( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit );
@@ -1767,13 +1767,13 @@ static bool ippi_DFT_C_32F(const uchar * src, size_t src_step, uchar * dst, size
if ( status < 0 )
return false;
IppiDFTSpec_C_32fc* pDFTSpec = (IppiDFTSpec_C_32fc*)ippMalloc( sizeSpec );
IppiDFTSpec_C_32fc* pDFTSpec = (IppiDFTSpec_C_32fc*)CV_IPP_MALLOC( sizeSpec );
if ( sizeInit > 0 )
pMemInit = (Ipp8u*)ippMalloc( sizeInit );
pMemInit = (Ipp8u*)CV_IPP_MALLOC( sizeInit );
if ( sizeBuffer > 0 )
pBuffer = (Ipp8u*)ippMalloc( sizeBuffer );
pBuffer = (Ipp8u*)CV_IPP_MALLOC( sizeBuffer );
status = ippiDFTInit_C_32fc( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit );
@@ -1823,13 +1823,13 @@ static bool ippi_DFT_R_32F(const uchar * src, size_t src_step, uchar * dst, size
if ( status < 0 )
return false;
IppiDFTSpec_R_32f* pDFTSpec = (IppiDFTSpec_R_32f*)ippMalloc( sizeSpec );
IppiDFTSpec_R_32f* pDFTSpec = (IppiDFTSpec_R_32f*)CV_IPP_MALLOC( sizeSpec );
if ( sizeInit > 0 )
pMemInit = (Ipp8u*)ippMalloc( sizeInit );
pMemInit = (Ipp8u*)CV_IPP_MALLOC( sizeInit );
if ( sizeBuffer > 0 )
pBuffer = (Ipp8u*)ippMalloc( sizeBuffer );
pBuffer = (Ipp8u*)CV_IPP_MALLOC( sizeBuffer );
status = ippiDFTInit_R_32f( srcRoiSize, norm_flag, ippAlgHintNone, pDFTSpec, pMemInit );
@@ -3852,20 +3852,20 @@ public:
return;
}
pDCTSpec = (Ipp8u*)ippMalloc(specSize);
pDCTSpec = (Ipp8u*)CV_IPP_MALLOC(specSize);
if(!pDCTSpec && specSize)
{
*ok = false;
return;
}
pBuffer = (Ipp8u*)ippMalloc(bufferSize);
pBuffer = (Ipp8u*)CV_IPP_MALLOC(bufferSize);
if(!pBuffer && bufferSize)
{
*ok = false;
IPP_RETURN
}
pInitBuf = (Ipp8u*)ippMalloc(initSize);
pInitBuf = (Ipp8u*)CV_IPP_MALLOC(initSize);
if(!pInitBuf && initSize)
{
*ok = false;
@@ -3981,17 +3981,17 @@ static bool ippi_DCT_32f(const uchar * src, size_t src_step, uchar * dst, size_t
if(ippDctGetSize(srcRoiSize, &specSize, &initSize, &bufferSize) < 0)
return false;
pDCTSpec = (Ipp8u*)ippMalloc(specSize);
pDCTSpec = (Ipp8u*)CV_IPP_MALLOC(specSize);
if(!pDCTSpec && specSize)
return false;
pBuffer = (Ipp8u*)ippMalloc(bufferSize);
pBuffer = (Ipp8u*)CV_IPP_MALLOC(bufferSize);
if(!pBuffer && bufferSize)
{
IPP_RELEASE
return false;
}
pInitBuf = (Ipp8u*)ippMalloc(initSize);
pInitBuf = (Ipp8u*)CV_IPP_MALLOC(initSize);
if(!pInitBuf && initSize)
{
IPP_RELEASE
+199 -168
View File
@@ -3955,50 +3955,6 @@ void cv::reduce(InputArray _src, OutputArray _dst, int dim, int op, int dtype)
namespace cv
{
#ifdef HAVE_IPP
#define USE_IPP_SORT
typedef IppStatus (CV_STDCALL * IppSortFunc)(void *, int);
typedef IppSortFunc IppFlipFunc;
static IppSortFunc getSortFunc(int depth, bool sortDescending)
{
if (!sortDescending)
return depth == CV_8U ? (IppSortFunc)ippsSortAscend_8u_I :
#if IPP_DISABLE_BLOCK
depth == CV_16U ? (IppSortFunc)ippsSortAscend_16u_I :
depth == CV_16S ? (IppSortFunc)ippsSortAscend_16s_I :
depth == CV_32S ? (IppSortFunc)ippsSortAscend_32s_I :
depth == CV_32F ? (IppSortFunc)ippsSortAscend_32f_I :
depth == CV_64F ? (IppSortFunc)ippsSortAscend_64f_I :
#endif
0;
else
return depth == CV_8U ? (IppSortFunc)ippsSortDescend_8u_I :
#if IPP_DISABLE_BLOCK
depth == CV_16U ? (IppSortFunc)ippsSortDescend_16u_I :
depth == CV_16S ? (IppSortFunc)ippsSortDescend_16s_I :
depth == CV_32S ? (IppSortFunc)ippsSortDescend_32s_I :
depth == CV_32F ? (IppSortFunc)ippsSortDescend_32f_I :
depth == CV_64F ? (IppSortFunc)ippsSortDescend_64f_I :
#endif
0;
}
static IppFlipFunc getFlipFunc(int depth)
{
CV_SUPPRESS_DEPRECATED_START
return
depth == CV_8U || depth == CV_8S ? (IppFlipFunc)ippsFlip_8u_I :
depth == CV_16U || depth == CV_16S ? (IppFlipFunc)ippsFlip_16u_I :
depth == CV_32S || depth == CV_32F ? (IppFlipFunc)ippsFlip_32f_I :
depth == CV_64F ? (IppFlipFunc)ippsFlip_64f_I : 0;
CV_SUPPRESS_DEPRECATED_END
}
#endif
template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
{
AutoBuffer<T> buf;
@@ -4017,17 +3973,6 @@ template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
}
bptr = (T*)buf;
#ifdef USE_IPP_SORT
int depth = src.depth();
IppSortFunc ippSortFunc = 0;
IppFlipFunc ippFlipFunc = 0;
CV_IPP_CHECK()
{
ippSortFunc = getSortFunc(depth, sortDescending);
ippFlipFunc = getFlipFunc(depth);
}
#endif
for( int i = 0; i < n; i++ )
{
T* ptr = bptr;
@@ -4047,41 +3992,12 @@ template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
ptr[j] = src.ptr<T>(j)[i];
}
#ifdef USE_IPP_SORT
if (!ippSortFunc || CV_INSTRUMENT_FUN_IPP(ippSortFunc, ptr, len) < 0)
#endif
std::sort( ptr, ptr + len );
if( sortDescending )
{
#ifdef USE_IPP_SORT
if (depth == CV_8U)
setIppErrorStatus();
#endif
std::sort( ptr, ptr + len );
if( sortDescending )
{
#ifdef USE_IPP_SORT
if (!ippFlipFunc || CV_INSTRUMENT_FUN_IPP(ippFlipFunc, ptr, len) < 0)
#endif
{
#ifdef USE_IPP_SORT
setIppErrorStatus();
#endif
for( int j = 0; j < len/2; j++ )
std::swap(ptr[j], ptr[len-1-j]);
}
#ifdef USE_IPP_SORT
else
{
CV_IMPL_ADD(CV_IMPL_IPP);
}
#endif
}
for( int j = 0; j < len/2; j++ )
std::swap(ptr[j], ptr[len-1-j]);
}
#ifdef USE_IPP_SORT
else
{
CV_IMPL_ADD(CV_IMPL_IPP);
}
#endif
if( !sortRows )
for( int j = 0; j < len; j++ )
@@ -4089,6 +4005,94 @@ template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
}
}
#ifdef HAVE_IPP
typedef IppStatus (CV_STDCALL *IppSortFunc)(void *pSrcDst, int len, Ipp8u *pBuffer);
static IppSortFunc getSortFunc(int depth, bool sortDescending)
{
if (!sortDescending)
return depth == CV_8U ? (IppSortFunc)ippsSortRadixAscend_8u_I :
depth == CV_16U ? (IppSortFunc)ippsSortRadixAscend_16u_I :
depth == CV_16S ? (IppSortFunc)ippsSortRadixAscend_16s_I :
depth == CV_32S ? (IppSortFunc)ippsSortRadixAscend_32s_I :
depth == CV_32F ? (IppSortFunc)ippsSortRadixAscend_32f_I :
depth == CV_64F ? (IppSortFunc)ippsSortRadixAscend_64f_I :
0;
else
return depth == CV_8U ? (IppSortFunc)ippsSortRadixDescend_8u_I :
depth == CV_16U ? (IppSortFunc)ippsSortRadixDescend_16u_I :
depth == CV_16S ? (IppSortFunc)ippsSortRadixDescend_16s_I :
depth == CV_32S ? (IppSortFunc)ippsSortRadixDescend_32s_I :
depth == CV_32F ? (IppSortFunc)ippsSortRadixDescend_32f_I :
depth == CV_64F ? (IppSortFunc)ippsSortRadixDescend_64f_I :
0;
}
static bool ipp_sort(const Mat& src, Mat& dst, int flags)
{
CV_INSTRUMENT_REGION_IPP()
bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW;
bool sortDescending = (flags & CV_SORT_DESCENDING) != 0;
bool inplace = (src.data == dst.data);
int depth = src.depth();
IppDataType type = ippiGetDataType(depth);
IppSortFunc ippsSortRadix_I = getSortFunc(depth, sortDescending);
if(!ippsSortRadix_I)
return false;
if(sortRows)
{
AutoBuffer<Ipp8u> buffer;
int bufferSize;
if(ippsSortRadixGetBufferSize(src.cols, type, &bufferSize) < 0)
return false;
buffer.allocate(bufferSize);
if(!inplace)
src.copyTo(dst);
for(int i = 0; i < dst.rows; i++)
{
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)dst.ptr(i), dst.cols, buffer) < 0)
return false;
}
}
else
{
AutoBuffer<Ipp8u> buffer;
int bufferSize;
if(ippsSortRadixGetBufferSize(src.rows, type, &bufferSize) < 0)
return false;
buffer.allocate(bufferSize);
Mat row(1, src.rows, src.type());
Mat srcSub;
Mat dstSub;
Rect subRect(0,0,1,src.rows);
for(int i = 0; i < src.cols; i++)
{
subRect.x = i;
srcSub = Mat(src, subRect);
dstSub = Mat(dst, subRect);
srcSub.copyTo(row);
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)row.ptr(), dst.rows, buffer) < 0)
return false;
row = row.reshape(1, dstSub.rows);
row.copyTo(dstSub);
}
}
return true;
}
#endif
template<typename _Tp> class LessThanIdx
{
public:
@@ -4097,30 +4101,6 @@ public:
const _Tp* arr;
};
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(void *, int *, int);
static IppSortIndexFunc getSortIndexFunc(int depth, bool sortDescending)
{
if (!sortDescending)
return depth == CV_8U ? (IppSortIndexFunc)ippsSortIndexAscend_8u_I :
depth == CV_16U ? (IppSortIndexFunc)ippsSortIndexAscend_16u_I :
depth == CV_16S ? (IppSortIndexFunc)ippsSortIndexAscend_16s_I :
depth == CV_32S ? (IppSortIndexFunc)ippsSortIndexAscend_32s_I :
depth == CV_32F ? (IppSortIndexFunc)ippsSortIndexAscend_32f_I :
depth == CV_64F ? (IppSortIndexFunc)ippsSortIndexAscend_64f_I : 0;
else
return depth == CV_8U ? (IppSortIndexFunc)ippsSortIndexDescend_8u_I :
depth == CV_16U ? (IppSortIndexFunc)ippsSortIndexDescend_16u_I :
depth == CV_16S ? (IppSortIndexFunc)ippsSortIndexDescend_16s_I :
depth == CV_32S ? (IppSortIndexFunc)ippsSortIndexDescend_32s_I :
depth == CV_32F ? (IppSortIndexFunc)ippsSortIndexDescend_32f_I :
depth == CV_64F ? (IppSortIndexFunc)ippsSortIndexDescend_64f_I : 0;
}
#endif
template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags )
{
AutoBuffer<T> buf;
@@ -4142,17 +4122,6 @@ template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags )
T* bptr = (T*)buf;
int* _iptr = (int*)ibuf;
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
int depth = src.depth();
IppSortIndexFunc ippFunc = 0;
IppFlipFunc ippFlipFunc = 0;
CV_IPP_CHECK()
{
ippFunc = getSortIndexFunc(depth, sortDescending);
ippFlipFunc = getFlipFunc(depth);
}
#endif
for( int i = 0; i < n; i++ )
{
T* ptr = bptr;
@@ -4171,40 +4140,12 @@ template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags )
for( int j = 0; j < len; j++ )
iptr[j] = j;
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
if (sortRows || !ippFunc || ippFunc(ptr, iptr, len) < 0)
#endif
std::sort( iptr, iptr + len, LessThanIdx<T>(ptr) );
if( sortDescending )
{
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
setIppErrorStatus();
#endif
std::sort( iptr, iptr + len, LessThanIdx<T>(ptr) );
if( sortDescending )
{
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
if (!ippFlipFunc || ippFlipFunc(iptr, len) < 0)
#endif
{
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
setIppErrorStatus();
#endif
for( int j = 0; j < len/2; j++ )
std::swap(iptr[j], iptr[len-1-j]);
}
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
else
{
CV_IMPL_ADD(CV_IMPL_IPP);
}
#endif
}
for( int j = 0; j < len/2; j++ )
std::swap(iptr[j], iptr[len-1-j]);
}
#if defined USE_IPP_SORT && IPP_DISABLE_BLOCK
else
{
CV_IMPL_ADD(CV_IMPL_IPP);
}
#endif
if( !sortRows )
for( int j = 0; j < len; j++ )
@@ -4212,24 +4153,110 @@ template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags )
}
}
typedef void (*SortFunc)(const Mat& src, Mat& dst, int flags);
#ifdef HAVE_IPP
#if !IPP_DISABLE_SORT_IDX
typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(const void* pSrc, Ipp32s srcStrideBytes, Ipp32s *pDstIndx, int len, Ipp8u *pBuffer);
static IppSortIndexFunc getSortIndexFunc(int depth, bool sortDescending)
{
if (!sortDescending)
return depth == CV_8U ? (IppSortIndexFunc)ippsSortRadixIndexAscend_8u :
depth == CV_16U ? (IppSortIndexFunc)ippsSortRadixIndexAscend_16u :
depth == CV_16S ? (IppSortIndexFunc)ippsSortRadixIndexAscend_16s :
depth == CV_32S ? (IppSortIndexFunc)ippsSortRadixIndexAscend_32s :
depth == CV_32F ? (IppSortIndexFunc)ippsSortRadixIndexAscend_32f :
0;
else
return depth == CV_8U ? (IppSortIndexFunc)ippsSortRadixIndexDescend_8u :
depth == CV_16U ? (IppSortIndexFunc)ippsSortRadixIndexDescend_16u :
depth == CV_16S ? (IppSortIndexFunc)ippsSortRadixIndexDescend_16s :
depth == CV_32S ? (IppSortIndexFunc)ippsSortRadixIndexDescend_32s :
depth == CV_32F ? (IppSortIndexFunc)ippsSortRadixIndexDescend_32f :
0;
}
static bool ipp_sortIdx( const Mat& src, Mat& dst, int flags )
{
CV_INSTRUMENT_REGION_IPP()
bool sortRows = (flags & 1) == CV_SORT_EVERY_ROW;
bool sortDescending = (flags & CV_SORT_DESCENDING) != 0;
int depth = src.depth();
IppDataType type = ippiGetDataType(depth);
Ipp32s elemSize = (Ipp32s)src.elemSize1();
IppSortIndexFunc ippsSortRadixIndex = getSortIndexFunc(depth, sortDescending);
if(!ippsSortRadixIndex)
return false;
if(sortRows)
{
AutoBuffer<Ipp8u> buffer;
int bufferSize;
if(ippsSortRadixIndexGetBufferSize(src.cols, type, &bufferSize) < 0)
return false;
buffer.allocate(bufferSize);
for(int i = 0; i < src.rows; i++)
{
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (void*)src.ptr(i), elemSize, (Ipp32s*)dst.ptr(i), src.cols, buffer) < 0)
return false;
}
}
else
{
Mat dstRow(1, dst.rows, dst.type());
Mat dstSub;
Rect subRect(0,0,1,src.rows);
AutoBuffer<Ipp8u> buffer;
int bufferSize;
if(ippsSortRadixIndexGetBufferSize(src.rows, type, &bufferSize) < 0)
return false;
buffer.allocate(bufferSize);
Ipp32s pixStride = elemSize*dst.cols;
for(int i = 0; i < src.cols; i++)
{
subRect.x = i;
dstSub = Mat(dst, subRect);
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadixIndex, (void*)src.ptr(0, i), pixStride, (Ipp32s*)dstRow.ptr(), src.rows, buffer) < 0)
return false;
dstRow = dstRow.reshape(1, dstSub.rows);
dstRow.copyTo(dstSub);
}
}
return true;
}
#endif
#endif
typedef void (*SortFunc)(const Mat& src, Mat& dst, int flags);
}
void cv::sort( InputArray _src, OutputArray _dst, int flags )
{
CV_INSTRUMENT_REGION()
Mat src = _src.getMat();
CV_Assert( src.dims <= 2 && src.channels() == 1 );
_dst.create( src.size(), src.type() );
Mat dst = _dst.getMat();
CV_IPP_RUN_FAST(ipp_sort(src, dst, flags));
static SortFunc tab[] =
{
sort_<uchar>, sort_<schar>, sort_<ushort>, sort_<short>,
sort_<int>, sort_<float>, sort_<double>, 0
};
Mat src = _src.getMat();
SortFunc func = tab[src.depth()];
CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 );
_dst.create( src.size(), src.type() );
Mat dst = _dst.getMat();
CV_Assert( func != 0 );
func( src, dst, flags );
}
@@ -4237,20 +4264,24 @@ void cv::sortIdx( InputArray _src, OutputArray _dst, int flags )
{
CV_INSTRUMENT_REGION()
static SortFunc tab[] =
{
sortIdx_<uchar>, sortIdx_<schar>, sortIdx_<ushort>, sortIdx_<short>,
sortIdx_<int>, sortIdx_<float>, sortIdx_<double>, 0
};
Mat src = _src.getMat();
SortFunc func = tab[src.depth()];
CV_Assert( src.dims <= 2 && src.channels() == 1 && func != 0 );
CV_Assert( src.dims <= 2 && src.channels() == 1 );
Mat dst = _dst.getMat();
if( dst.data == src.data )
_dst.release();
_dst.create( src.size(), CV_32S );
dst = _dst.getMat();
#if !IPP_DISABLE_SORT_IDX
CV_IPP_RUN_FAST(ipp_sortIdx(src, dst, flags));
#endif
static SortFunc tab[] =
{
sortIdx_<uchar>, sortIdx_<schar>, sortIdx_<ushort>, sortIdx_<short>,
sortIdx_<int>, sortIdx_<float>, sortIdx_<double>, 0
};
SortFunc func = tab[src.depth()];
CV_Assert( func != 0 );
func( src, dst, flags );
}
+30 -9
View File
@@ -1738,19 +1738,19 @@ IntrumentationRegion::~IntrumentationRegion()
namespace ipp
{
#ifdef HAVE_IPP
struct IPPInitSingleton
{
public:
IPPInitSingleton()
{
useIPP = true;
ippStatus = 0;
funcname = NULL;
filename = NULL;
linen = 0;
ippFeatures = 0;
useIPP = true;
ippStatus = 0;
funcname = NULL;
filename = NULL;
linen = 0;
ippFeatures = 0;
#ifdef HAVE_IPP
const char* pIppEnv = getenv("OPENCV_IPP");
cv::String env = pIppEnv;
if(env.size())
@@ -1783,7 +1783,7 @@ public:
}
IPP_INITIALIZER(ippFeatures)
#endif
ippFeatures = ippGetEnabledCpuFeatures();
}
bool useIPP;
@@ -1792,18 +1792,27 @@ public:
const char *funcname;
const char *filename;
int linen;
int ippFeatures;
Ipp64u ippFeatures;
};
static IPPInitSingleton& getIPPSingleton()
{
CV_SINGLETON_LAZY_INIT_REF(IPPInitSingleton, new IPPInitSingleton())
}
#endif
#if OPENCV_ABI_COMPATIBILITY > 300
unsigned long long getIppFeatures()
#else
int getIppFeatures()
#endif
{
#ifdef HAVE_IPP
#if OPENCV_ABI_COMPATIBILITY > 300
return getIPPSingleton().ippFeatures;
#else
return (int)getIPPSingleton().ippFeatures;
#endif
#else
return 0;
#endif
@@ -1811,20 +1820,32 @@ int getIppFeatures()
void setIppStatus(int status, const char * const _funcname, const char * const _filename, int _line)
{
#ifdef HAVE_IPP
getIPPSingleton().ippStatus = status;
getIPPSingleton().funcname = _funcname;
getIPPSingleton().filename = _filename;
getIPPSingleton().linen = _line;
#else
CV_UNUSED(status); CV_UNUSED(_funcname); CV_UNUSED(_filename); CV_UNUSED(_line);
#endif
}
int getIppStatus()
{
#ifdef HAVE_IPP
return getIPPSingleton().ippStatus;
#else
return 0;
#endif
}
String getIppErrorLocation()
{
#ifdef HAVE_IPP
return format("%s:%d %s", getIPPSingleton().filename ? getIPPSingleton().filename : "", getIPPSingleton().linen, getIPPSingleton().funcname ? getIPPSingleton().funcname : "");
#else
return String();
#endif
}
bool useIPP()