1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 15:23:05 +04:00

core: rework code locality

- to reduce binaries size of FFmpeg Windows wrapper
- MinGW linker doesn't support -ffunction-sections (used for FFmpeg Windows wrapper)
- move code to improve locality with its used dependencies
- move UMat::dot() to matmul.dispatch.cpp (Mat::dot() is already there)
- move UMat::inv() to lapack.cpp
- move UMat::mul() to arithm.cpp
- move UMat:eye() to matrix_operations.cpp (near setIdentity() implementation)
- move normalize(): convert_scale.cpp => norm.cpp
- move convertAndUnrollScalar(): arithm.cpp => copy.cpp
- move scalarToRawData(): array.cpp => copy.cpp
- move transpose(): matrix_operations.cpp => matrix_transform.cpp
- move flip(), rotate(): copy.cpp => matrix_transform.cpp (rotate90 uses flip and transpose)
- add 'OPENCV_CORE_EXCLUDE_C_API' CMake variable to exclude compilation of C-API functions from the core module
- matrix_wrap.cpp: add compile-time checks for CUDA/OpenGL calls
- the steps above allow to reduce FFmpeg wrapper size for ~1.5Mb (initial size of OpenCV part is about 3Mb)
This commit is contained in:
Alexander Alekhin
2021-02-23 00:22:06 +00:00
parent 7bcb51eded
commit 65eb946756
19 changed files with 1206 additions and 1108 deletions
+17 -279
View File
@@ -226,6 +226,23 @@ void cv::setIdentity( InputOutputArray _m, const Scalar& s )
}
}
namespace cv {
UMat UMat::eye(int rows, int cols, int type)
{
return UMat::eye(Size(cols, rows), type);
}
UMat UMat::eye(Size size, int type)
{
UMat m(size, type);
setIdentity(m);
return m;
}
} // namespace
//////////////////////////////////////////// trace ///////////////////////////////////////////
cv::Scalar cv::trace( InputArray _m )
@@ -260,285 +277,6 @@ cv::Scalar cv::trace( InputArray _m )
return cv::sum(m.diag());
}
////////////////////////////////////// transpose /////////////////////////////////////////
namespace cv
{
template<typename T> static void
transpose_( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz )
{
int i=0, j, m = sz.width, n = sz.height;
#if CV_ENABLE_UNROLLED
for(; i <= m - 4; i += 4 )
{
T* d0 = (T*)(dst + dstep*i);
T* d1 = (T*)(dst + dstep*(i+1));
T* d2 = (T*)(dst + dstep*(i+2));
T* d3 = (T*)(dst + dstep*(i+3));
for( j = 0; j <= n - 4; j += 4 )
{
const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
d1[j] = s0[1]; d1[j+1] = s1[1]; d1[j+2] = s2[1]; d1[j+3] = s3[1];
d2[j] = s0[2]; d2[j+1] = s1[2]; d2[j+2] = s2[2]; d2[j+3] = s3[2];
d3[j] = s0[3]; d3[j+1] = s1[3]; d3[j+2] = s2[3]; d3[j+3] = s3[3];
}
for( ; j < n; j++ )
{
const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
d0[j] = s0[0]; d1[j] = s0[1]; d2[j] = s0[2]; d3[j] = s0[3];
}
}
#endif
for( ; i < m; i++ )
{
T* d0 = (T*)(dst + dstep*i);
j = 0;
#if CV_ENABLE_UNROLLED
for(; j <= n - 4; j += 4 )
{
const T* s0 = (const T*)(src + i*sizeof(T) + sstep*j);
const T* s1 = (const T*)(src + i*sizeof(T) + sstep*(j+1));
const T* s2 = (const T*)(src + i*sizeof(T) + sstep*(j+2));
const T* s3 = (const T*)(src + i*sizeof(T) + sstep*(j+3));
d0[j] = s0[0]; d0[j+1] = s1[0]; d0[j+2] = s2[0]; d0[j+3] = s3[0];
}
#endif
for( ; j < n; j++ )
{
const T* s0 = (const T*)(src + i*sizeof(T) + j*sstep);
d0[j] = s0[0];
}
}
}
template<typename T> static void
transposeI_( uchar* data, size_t step, int n )
{
for( int i = 0; i < n; i++ )
{
T* row = (T*)(data + step*i);
uchar* data1 = data + i*sizeof(T);
for( int j = i+1; j < n; j++ )
std::swap( row[j], *(T*)(data1 + step*j) );
}
}
typedef void (*TransposeFunc)( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz );
typedef void (*TransposeInplaceFunc)( uchar* data, size_t step, int n );
#define DEF_TRANSPOSE_FUNC(suffix, type) \
static void transpose_##suffix( const uchar* src, size_t sstep, uchar* dst, size_t dstep, Size sz ) \
{ transpose_<type>(src, sstep, dst, dstep, sz); } \
\
static void transposeI_##suffix( uchar* data, size_t step, int n ) \
{ transposeI_<type>(data, step, n); }
DEF_TRANSPOSE_FUNC(8u, uchar)
DEF_TRANSPOSE_FUNC(16u, ushort)
DEF_TRANSPOSE_FUNC(8uC3, Vec3b)
DEF_TRANSPOSE_FUNC(32s, int)
DEF_TRANSPOSE_FUNC(16uC3, Vec3s)
DEF_TRANSPOSE_FUNC(32sC2, Vec2i)
DEF_TRANSPOSE_FUNC(32sC3, Vec3i)
DEF_TRANSPOSE_FUNC(32sC4, Vec4i)
DEF_TRANSPOSE_FUNC(32sC6, Vec6i)
DEF_TRANSPOSE_FUNC(32sC8, Vec8i)
static TransposeFunc transposeTab[] =
{
0, transpose_8u, transpose_16u, transpose_8uC3, transpose_32s, 0, transpose_16uC3, 0,
transpose_32sC2, 0, 0, 0, transpose_32sC3, 0, 0, 0, transpose_32sC4,
0, 0, 0, 0, 0, 0, 0, transpose_32sC6, 0, 0, 0, 0, 0, 0, 0, transpose_32sC8
};
static TransposeInplaceFunc transposeInplaceTab[] =
{
0, transposeI_8u, transposeI_16u, transposeI_8uC3, transposeI_32s, 0, transposeI_16uC3, 0,
transposeI_32sC2, 0, 0, 0, transposeI_32sC3, 0, 0, 0, transposeI_32sC4,
0, 0, 0, 0, 0, 0, 0, transposeI_32sC6, 0, 0, 0, 0, 0, 0, 0, transposeI_32sC8
};
#ifdef HAVE_OPENCL
static bool ocl_transpose( InputArray _src, OutputArray _dst )
{
const ocl::Device & dev = ocl::Device::getDefault();
const int TILE_DIM = 32, BLOCK_ROWS = 8;
int type = _src.type(), cn = CV_MAT_CN(type), depth = CV_MAT_DEPTH(type),
rowsPerWI = dev.isIntel() ? 4 : 1;
UMat src = _src.getUMat();
_dst.create(src.cols, src.rows, type);
UMat dst = _dst.getUMat();
String kernelName("transpose");
bool inplace = dst.u == src.u;
if (inplace)
{
CV_Assert(dst.cols == dst.rows);
kernelName += "_inplace";
}
else
{
// check required local memory size
size_t required_local_memory = (size_t) TILE_DIM*(TILE_DIM+1)*CV_ELEM_SIZE(type);
if (required_local_memory > ocl::Device::getDefault().localMemSize())
return false;
}
ocl::Kernel k(kernelName.c_str(), ocl::core::transpose_oclsrc,
format("-D T=%s -D T1=%s -D cn=%d -D TILE_DIM=%d -D BLOCK_ROWS=%d -D rowsPerWI=%d%s",
ocl::memopTypeToStr(type), ocl::memopTypeToStr(depth),
cn, TILE_DIM, BLOCK_ROWS, rowsPerWI, inplace ? " -D INPLACE" : ""));
if (k.empty())
return false;
if (inplace)
k.args(ocl::KernelArg::ReadWriteNoSize(dst), dst.rows);
else
k.args(ocl::KernelArg::ReadOnly(src),
ocl::KernelArg::WriteOnlyNoSize(dst));
size_t localsize[2] = { TILE_DIM, BLOCK_ROWS };
size_t globalsize[2] = { (size_t)src.cols, inplace ? ((size_t)src.rows + rowsPerWI - 1) / rowsPerWI : (divUp((size_t)src.rows, TILE_DIM) * BLOCK_ROWS) };
if (inplace && dev.isIntel())
{
localsize[0] = 16;
localsize[1] = dev.maxWorkGroupSize() / localsize[0];
}
return k.run(2, globalsize, localsize, false);
}
#endif
#ifdef HAVE_IPP
static bool ipp_transpose( Mat &src, Mat &dst )
{
CV_INSTRUMENT_REGION_IPP();
int type = src.type();
typedef IppStatus (CV_STDCALL * IppiTranspose)(const void * pSrc, int srcStep, void * pDst, int dstStep, IppiSize roiSize);
typedef IppStatus (CV_STDCALL * IppiTransposeI)(const void * pSrcDst, int srcDstStep, IppiSize roiSize);
IppiTranspose ippiTranspose = 0;
IppiTransposeI ippiTranspose_I = 0;
if (dst.data == src.data && dst.cols == dst.rows)
{
CV_SUPPRESS_DEPRECATED_START
ippiTranspose_I =
type == CV_8UC1 ? (IppiTransposeI)ippiTranspose_8u_C1IR :
type == CV_8UC3 ? (IppiTransposeI)ippiTranspose_8u_C3IR :
type == CV_8UC4 ? (IppiTransposeI)ippiTranspose_8u_C4IR :
type == CV_16UC1 ? (IppiTransposeI)ippiTranspose_16u_C1IR :
type == CV_16UC3 ? (IppiTransposeI)ippiTranspose_16u_C3IR :
type == CV_16UC4 ? (IppiTransposeI)ippiTranspose_16u_C4IR :
type == CV_16SC1 ? (IppiTransposeI)ippiTranspose_16s_C1IR :
type == CV_16SC3 ? (IppiTransposeI)ippiTranspose_16s_C3IR :
type == CV_16SC4 ? (IppiTransposeI)ippiTranspose_16s_C4IR :
type == CV_32SC1 ? (IppiTransposeI)ippiTranspose_32s_C1IR :
type == CV_32SC3 ? (IppiTransposeI)ippiTranspose_32s_C3IR :
type == CV_32SC4 ? (IppiTransposeI)ippiTranspose_32s_C4IR :
type == CV_32FC1 ? (IppiTransposeI)ippiTranspose_32f_C1IR :
type == CV_32FC3 ? (IppiTransposeI)ippiTranspose_32f_C3IR :
type == CV_32FC4 ? (IppiTransposeI)ippiTranspose_32f_C4IR : 0;
CV_SUPPRESS_DEPRECATED_END
}
else
{
ippiTranspose =
type == CV_8UC1 ? (IppiTranspose)ippiTranspose_8u_C1R :
type == CV_8UC3 ? (IppiTranspose)ippiTranspose_8u_C3R :
type == CV_8UC4 ? (IppiTranspose)ippiTranspose_8u_C4R :
type == CV_16UC1 ? (IppiTranspose)ippiTranspose_16u_C1R :
type == CV_16UC3 ? (IppiTranspose)ippiTranspose_16u_C3R :
type == CV_16UC4 ? (IppiTranspose)ippiTranspose_16u_C4R :
type == CV_16SC1 ? (IppiTranspose)ippiTranspose_16s_C1R :
type == CV_16SC3 ? (IppiTranspose)ippiTranspose_16s_C3R :
type == CV_16SC4 ? (IppiTranspose)ippiTranspose_16s_C4R :
type == CV_32SC1 ? (IppiTranspose)ippiTranspose_32s_C1R :
type == CV_32SC3 ? (IppiTranspose)ippiTranspose_32s_C3R :
type == CV_32SC4 ? (IppiTranspose)ippiTranspose_32s_C4R :
type == CV_32FC1 ? (IppiTranspose)ippiTranspose_32f_C1R :
type == CV_32FC3 ? (IppiTranspose)ippiTranspose_32f_C3R :
type == CV_32FC4 ? (IppiTranspose)ippiTranspose_32f_C4R : 0;
}
IppiSize roiSize = { src.cols, src.rows };
if (ippiTranspose != 0)
{
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose, src.ptr(), (int)src.step, dst.ptr(), (int)dst.step, roiSize) >= 0)
return true;
}
else if (ippiTranspose_I != 0)
{
if (CV_INSTRUMENT_FUN_IPP(ippiTranspose_I, dst.ptr(), (int)dst.step, roiSize) >= 0)
return true;
}
return false;
}
#endif
}
void cv::transpose( InputArray _src, OutputArray _dst )
{
CV_INSTRUMENT_REGION();
int type = _src.type(), esz = CV_ELEM_SIZE(type);
CV_Assert( _src.dims() <= 2 && esz <= 32 );
CV_OCL_RUN(_dst.isUMat(),
ocl_transpose(_src, _dst))
Mat src = _src.getMat();
if( src.empty() )
{
_dst.release();
return;
}
_dst.create(src.cols, src.rows, src.type());
Mat dst = _dst.getMat();
// handle the case of single-column/single-row matrices, stored in STL vectors.
if( src.rows != dst.cols || src.cols != dst.rows )
{
CV_Assert( src.size() == dst.size() && (src.cols == 1 || src.rows == 1) );
src.copyTo(dst);
return;
}
CV_IPP_RUN_FAST(ipp_transpose(src, dst))
if( dst.data == src.data )
{
TransposeInplaceFunc func = transposeInplaceTab[esz];
CV_Assert( func != 0 );
CV_Assert( dst.cols == dst.rows );
func( dst.ptr(), dst.step, dst.rows );
}
else
{
TransposeFunc func = transposeTab[esz];
CV_Assert( func != 0 );
func( src.ptr(), src.step, dst.ptr(), dst.step, src.size() );
}
}
////////////////////////////////////// completeSymm /////////////////////////////////////////