1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-21 19:33:03 +04:00

Merge pull request #29477 from intel-staging:ipp/sort_enabling

Enable ipp calls for sort, sortIdx#29477

Follow up on https://github.com/opencv/opencv/pull/29184
Also introduced parallelization to sort similar to #29192
Performance is up to ~17x faster per our measurements
+ ~127KB to binary size.

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Andrei Fedorov
2026-07-10 07:39:21 +02:00
committed by GitHub
parent 7507accf2e
commit 93cd614472
+63 -52
View File
@@ -6,11 +6,8 @@
#include "opencv2/core/mat.hpp"
#include "opencl_kernels_core.hpp"
#undef HAVE_IPP
#undef CV_IPP_RUN_FAST
#define CV_IPP_RUN_FAST(f, ...)
#undef CV_IPP_RUN
#define CV_IPP_RUN(c, f, ...)
#define IPP_DISABLE_REDUCE 1
#define IPP_DISABLE_SORT 0
/*************************************************************************************************\
Matrix Operations
@@ -512,7 +509,7 @@ typedef void (*ReduceFunc)( const Mat& src, Mat& dst );
#define reduceMinR32f reduceR_<float, float, OpMin<float> >
#define reduceMinR64f reduceR_<double,double,OpMin<double> >
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
static inline bool ipp_reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& dstmat)
{
int sstep = (int)srcmat.step, stype = srcmat.type(),
@@ -601,7 +598,7 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds
#define reduceSum2C32f32f reduceC_<float, float, OpAddSqr<float>, OpSqr<float> >
#define reduceSum2C64f64f reduceC_<double,double,OpAddSqr<double>,OpSqr<double> >
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
#define reduceSumC8u64f reduceSumC_8u16u16s32f_64f
#define reduceSumC16u64f reduceSumC_8u16u16s32f_64f
#define reduceSumC16s64f reduceSumC_8u16u16s32f_64f
@@ -611,14 +608,14 @@ static inline void reduceSumC_8u16u16s32f_64f(const cv::Mat& srcmat, cv::Mat& ds
#define reduceSumC16u64f reduceC_<ushort,double,OpAdd<double> >
#define reduceSumC16s64f reduceC_<short, double,OpAdd<double> >
#define reduceSumC32f64f reduceC_<float, double,OpAdd<double> >
#endif
#define reduceSum2C8u64f reduceC_<uchar, double,OpAddSqr<int>, OpSqr<int> >
#define reduceSum2C16u64f reduceC_<ushort,double,OpAddSqr<double>,OpSqr<double> >
#define reduceSum2C16s64f reduceC_<short, double,OpAddSqr<double>,OpSqr<double> >
#define reduceSum2C32f64f reduceC_<float, double,OpAddSqr<double>,OpSqr<double> >
#endif
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
#define REDUCE_OP(favor, optype, type1, type2) \
static inline bool ipp_reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstmat) \
{ \
@@ -643,7 +640,7 @@ static inline void reduce##optype##C##favor(const cv::Mat& srcmat, cv::Mat& dstm
}
#endif
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
REDUCE_OP(8u, Max, uchar, uchar)
REDUCE_OP(16u, Max, ushort, ushort)
REDUCE_OP(16s, Max, short, short)
@@ -656,7 +653,7 @@ REDUCE_OP(32f, Max, float, float)
#endif
#define reduceMaxC64f reduceC_<double,double,OpMax<double> >
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_REDUCE
REDUCE_OP(8u, Min, uchar, uchar)
REDUCE_OP(16u, Min, ushort, ushort)
REDUCE_OP(16s, Min, short, short)
@@ -1042,7 +1039,7 @@ template<typename T> static void sort_( const Mat& src, Mat& dst, int flags )
}
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_SORT
typedef IppStatus (CV_STDCALL *IppSortFunc)(void *pSrcDst, int len, Ipp8u *pBuffer);
static IppSortFunc getSortFunc(int depth, bool sortDescending)
@@ -1079,54 +1076,64 @@ static bool ipp_sort(const Mat& src, Mat& dst, int flags)
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.data()) < 0)
return false;
}
}
int n, len;
if( sortRows )
n = src.rows, len = src.cols;
else
n = src.cols, len = src.rows;
int bufferSize;
if(ippsSortRadixGetBufferSize(len, type, &bufferSize) < 0)
return false;
// Each row/column sorts independently, so parallelize over n like sort_ does.
// IPP scratch (buffer) and per-column temporaries are thread-local; a shared flag
// records IPP failures since the lambda cannot return from ipp_sort.
volatile bool ok = true;
parallel_for_(Range(0, n), [&](const Range& range)
{
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;
AutoBuffer<Ipp8u> buffer(bufferSize);
Mat row;
Rect subRect(0,0,1,src.rows);
if( !sortRows )
row.create(1, src.rows, src.type());
for(int i = 0; i < src.cols; i++)
for( int i = range.start; i < range.end; i++ )
{
subRect.x = i;
srcSub = Mat(src, subRect);
dstSub = Mat(dst, subRect);
srcSub.copyTo(row);
if( !ok )
break;
void* ptr;
if( sortRows )
{
uchar* dptr = dst.ptr(i);
if( !inplace )
memcpy(dptr, src.ptr(i), src.cols * src.elemSize());
ptr = dptr;
}
else
{
subRect.x = i;
Mat(src, subRect).copyTo(row);
ptr = row.ptr();
}
if(CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, (void*)row.ptr(), dst.rows, buffer.data()) < 0)
return false;
if( CV_INSTRUMENT_FUN_IPP(ippsSortRadix_I, ptr, len, buffer.data()) < 0 )
{
ok = false;
break;
}
row = row.reshape(1, dstSub.rows);
row.copyTo(dstSub);
if( !sortRows )
{
Mat dstSub(dst, subRect);
row = row.reshape(1, dstSub.rows);
row.copyTo(dstSub);
row = row.reshape(1, 1);
}
}
}
});
return true;
return ok;
}
#endif
@@ -1190,7 +1197,7 @@ template<typename T> static void sortIdx_( const Mat& src, Mat& dst, int flags )
}
}
#ifdef HAVE_IPP
#if defined(HAVE_IPP) && !IPP_DISABLE_SORT
typedef IppStatus (CV_STDCALL *IppSortIndexFunc)(const void* pSrc, Ipp32s srcStrideBytes, Ipp32s *pDstIndx, int len, Ipp8u *pBuffer);
static IppSortIndexFunc getSortIndexFunc(int depth, bool sortDescending)
@@ -1281,7 +1288,9 @@ void cv::sort( InputArray _src, OutputArray _dst, int flags )
CV_Assert( src.dims <= 2 && src.channels() == 1 );
_dst.create( src.size(), src.type() );
Mat dst = _dst.getMat();
#if !IPP_DISABLE_SORT
CV_IPP_RUN_FAST(ipp_sort(src, dst, flags));
#endif
static SortFunc tab[CV_DEPTH_MAX] =
{
@@ -1306,7 +1315,9 @@ void cv::sortIdx( InputArray _src, OutputArray _dst, int flags )
_dst.create( src.size(), CV_32S );
dst = _dst.getMat();
#if !IPP_DISABLE_SORT
CV_IPP_RUN_FAST(ipp_sortIdx(src, dst, flags));
#endif
static SortFunc tab[CV_DEPTH_MAX] =
{