From f2a748245e747d0b33dd9335ea25674b3474ca7d Mon Sep 17 00:00:00 2001 From: Pratham Kumar Date: Tue, 22 Sep 2026 14:04:28 +0530 Subject: [PATCH] core: accelerate cv::gemm with ARMPL cblas_sgemm/cblas_dgemm --- hal/armpl/include/armpl_hal_core.hpp | 22 ++++ hal/armpl/src/armpl_hal_core.cpp | 166 +++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) diff --git a/hal/armpl/include/armpl_hal_core.hpp b/hal/armpl/include/armpl_hal_core.hpp index d2d505cd51..4546a29db7 100644 --- a/hal/armpl/include/armpl_hal_core.hpp +++ b/hal/armpl/include/armpl_hal_core.hpp @@ -86,6 +86,28 @@ int armpl_hal_dctFree2D(cvhalDFT *context); #undef cv_hal_dctFree2D #define cv_hal_dctFree2D armpl_hal_dctFree2D +int armpl_hal_gemm32f(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m, int n, int k, int flags); +int armpl_hal_gemm64f(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m, int n, int k, int flags); +int armpl_hal_gemm32fc(const float* src1, size_t src1_step, const float* src2, size_t src2_step, + float alpha, const float* src3, size_t src3_step, float beta, float* dst, size_t dst_step, + int m, int n, int k, int flags); +int armpl_hal_gemm64fc(const double* src1, size_t src1_step, const double* src2, size_t src2_step, + double alpha, const double* src3, size_t src3_step, double beta, double* dst, size_t dst_step, + int m, int n, int k, int flags); + +#undef cv_hal_gemm32f +#define cv_hal_gemm32f armpl_hal_gemm32f +#undef cv_hal_gemm64f +#define cv_hal_gemm64f armpl_hal_gemm64f +#undef cv_hal_gemm32fc +#define cv_hal_gemm32fc armpl_hal_gemm32fc +#undef cv_hal_gemm64fc +#define cv_hal_gemm64fc armpl_hal_gemm64fc + #endif // HAVE_ARMPL #endif // OPENCV_ARMPL_HAL_CORE_HPP diff --git a/hal/armpl/src/armpl_hal_core.cpp b/hal/armpl/src/armpl_hal_core.cpp index bb5ad02d5e..e4fc339645 100644 --- a/hal/armpl/src/armpl_hal_core.cpp +++ b/hal/armpl/src/armpl_hal_core.cpp @@ -3,9 +3,175 @@ #include "armpl_hal_core.hpp" #include +#include +#include +#include #include #include #include + +#define ARMPL_GEMM_MIN_WORK_VOLUME 10000 + +namespace { + +template static inline void +armpl_transpose(const fptype *src, size_t src_ld, fptype *dst, size_t dst_ld, size_t m, size_t n) +{ + for (size_t i = 0; i < m; i++) + for (size_t j = 0; j < n; j++) + dst[j*dst_ld + i] = src[i*src_ld + j]; +} + +template static inline void +armpl_copy_matrix(const fptype *src, size_t src_ld, fptype *dst, size_t dst_ld, size_t m, size_t n) +{ + for (size_t i = 0; i < m; i++) + std::copy(src + i*src_ld, src + i*src_ld + n, dst + i*dst_ld); +} + +template static inline void +armpl_set_value(fptype *dst, size_t dst_ld, fptype value, size_t m, size_t n) +{ + for (size_t i = 0; i < m; i++) + std::fill(dst + i*dst_ld, dst + i*dst_ld + n, value); +} + +static inline void +armpl_cblas_gemm(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, int a_m, int d_n, int a_n, + float alpha, const float *src1, int ldsrc1, const float *src2, int ldsrc2, + float beta, float *dst, int lddst) +{ + cblas_sgemm(CblasRowMajor, transA, transB, a_m, d_n, a_n, alpha, src1, ldsrc1, src2, ldsrc2, beta, dst, lddst); +} + +static inline void +armpl_cblas_gemm(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, int a_m, int d_n, int a_n, + double alpha, const double *src1, int ldsrc1, const double *src2, int ldsrc2, + double beta, double *dst, int lddst) +{ + cblas_dgemm(CblasRowMajor, transA, transB, a_m, d_n, a_n, alpha, src1, ldsrc1, src2, ldsrc2, beta, dst, lddst); +} + +static inline void +armpl_cblas_gemm(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, int a_m, int d_n, int a_n, + std::complex alpha, const std::complex *src1, int ldsrc1, + const std::complex *src2, int ldsrc2, + std::complex beta, std::complex *dst, int lddst) +{ + cblas_cgemm(CblasRowMajor, transA, transB, a_m, d_n, a_n, &alpha, src1, ldsrc1, src2, ldsrc2, &beta, dst, lddst); +} + +static inline void +armpl_cblas_gemm(CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, int a_m, int d_n, int a_n, + std::complex alpha, const std::complex *src1, int ldsrc1, + const std::complex *src2, int ldsrc2, + std::complex beta, std::complex *dst, int lddst) +{ + cblas_zgemm(CblasRowMajor, transA, transB, a_m, d_n, a_n, &alpha, src1, ldsrc1, src2, ldsrc2, &beta, dst, lddst); +} + +template static inline int +armpl_gemm_impl(const elemtype *src1, size_t src1_step, const elemtype *src2, size_t src2_step, scalartype alpha, + const elemtype *src3, size_t src3_step, scalartype beta, elemtype *dst, size_t dst_step, + int a_m, int a_n, int d_n, int flags) +{ + int ldsrc1 = (int)(src1_step / sizeof(elemtype)); + int ldsrc2 = (int)(src2_step / sizeof(elemtype)); + int ldsrc3 = (int)(src3_step / sizeof(elemtype)); + int lddst = (int)(dst_step / sizeof(elemtype)); + int c_m, c_n, d_m; + CBLAS_TRANSPOSE transA, transB; + elemtype eAlpha = (elemtype)alpha; + elemtype eBeta = (elemtype)beta; + + transB = (flags & CV_HAL_GEMM_2_T) ? CblasTrans : CblasNoTrans; + d_m = (flags & CV_HAL_GEMM_1_T) ? a_n : a_m; + + if (flags & CV_HAL_GEMM_3_T) + { + c_m = d_n; + c_n = d_m; + } + else + { + c_m = d_m; + c_n = d_n; + } + + if (flags & CV_HAL_GEMM_1_T) + { + transA = CblasTrans; + std::swap(a_n, a_m); + } + else + { + transA = CblasNoTrans; + } + + if (src3 != dst && beta != 0.0 && src3_step != 0) + { + if (flags & CV_HAL_GEMM_3_T) + armpl_transpose(src3, ldsrc3, dst, lddst, c_m, c_n); + else + armpl_copy_matrix(src3, ldsrc3, dst, lddst, c_m, c_n); + } + else if (src3 == dst && (flags & CV_HAL_GEMM_3_T)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + + else if (src3_step == 0 && beta != 0.0) + armpl_set_value(dst, lddst, elemtype(), d_m, d_n); + + armpl_cblas_gemm(transA, transB, a_m, d_n, a_n, eAlpha, src1, ldsrc1, src2, ldsrc2, eBeta, dst, lddst); + + return CV_HAL_ERROR_OK; +} +} + +static inline bool armpl_gemm_below_min_volume(int m, int n, int k) +{ + return (double)m * n * k < ARMPL_GEMM_MIN_WORK_VOLUME; +} + +int armpl_hal_gemm32f(const float *src1, size_t src1_step, const float *src2, size_t src2_step, float alpha, + const float *src3, size_t src3_step, float beta, float *dst, size_t dst_step, + int m, int n, int k, int flags) +{ + if (armpl_gemm_below_min_volume(m, n, k)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return armpl_gemm_impl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m, n, k, flags); +} + +int armpl_hal_gemm64f(const double *src1, size_t src1_step, const double *src2, size_t src2_step, double alpha, + const double *src3, size_t src3_step, double beta, double *dst, size_t dst_step, + int m, int n, int k, int flags) +{ + if (armpl_gemm_below_min_volume(m, n, k)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + return armpl_gemm_impl(src1, src1_step, src2, src2_step, alpha, src3, src3_step, beta, dst, dst_step, m, n, k, flags); +} + +int armpl_hal_gemm32fc(const float *src1, size_t src1_step, const float *src2, size_t src2_step, float alpha, + const float *src3, size_t src3_step, float beta, float *dst, size_t dst_step, + int m, int n, int k, int flags) +{ + if (armpl_gemm_below_min_volume(m, n, k)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + typedef std::complex cplx; + return armpl_gemm_impl(reinterpret_cast(src1), src1_step, reinterpret_cast(src2), src2_step, alpha, + reinterpret_cast(src3), src3_step, beta, reinterpret_cast(dst), dst_step, m, n, k, flags); +} + +int armpl_hal_gemm64fc(const double *src1, size_t src1_step, const double *src2, size_t src2_step, double alpha, + const double *src3, size_t src3_step, double beta, double *dst, size_t dst_step, + int m, int n, int k, int flags) +{ + if (armpl_gemm_below_min_volume(m, n, k)) + return CV_HAL_ERROR_NOT_IMPLEMENTED; + typedef std::complex cplx; + return armpl_gemm_impl(reinterpret_cast(src1), src1_step, reinterpret_cast(src2), src2_step, alpha, + reinterpret_cast(src3), src3_step, beta, reinterpret_cast(dst), dst_step, m, n, k, flags); +} + enum ArmPLDFTMode { ARMPL_DFT_C2C,