Merge pull request #30080 from pratham-mcw:invert_opt_5.x

core: add ARMPL HAL backend for cv::invert(DECOMP_LU) - #30080

## Summary

- Follow-up to #[30035](https://github.com/opencv/opencv/pull/30035) to apply the same `cv::invert` optimization to the 5.x branch.
- Adds an ARM Performance Library (ArmPL) HAL backend for cv::invert under DECOMP_LU (cv_hal_LU32f / cv_hal_LU64f), replacing OpenCV's default LU decomposition path with ArmPL's LAPACKE_sgesv / LAPACKE_dgesv for float and double matrices on AArch64.

## Changes
**hal/armpl/include/armpl_hal_core.hpp:**
- Declare armpl_hal_LU32f / armpl_hal_LU64f and register them as cv_hal_LU32f / cv_hal_LU64f.

**hal/armpl/src/armpl_hal_core.cpp:**

- Add armpl_lu() function (works for both float and double), that does the LU decomposition of the matrix:
  - If a right-hand side b is given, then LAPACKE_sgesv/dgesv is called.
  - If no right-hand side is given, it only factorizes the matrix using LAPACKE_sgetrf/dgetrf
- Fall back to OpenCV's default (non-HAL) implementation for small matrices (m < 100).
This commit is contained in:
Pratham Kumar authored and GitHub committed 2026-09-29 08:53:10 +03:00
1 parent e6f8c94063
commit 08f84c19c2
2 files changed
+70

No files matched your search

+8
View File
@@ -108,6 +108,14 @@ int armpl_hal_gemm64fc(const double* src1, size_t src1_step, const double* src2,
#undef cv_hal_gemm64fc
#define cv_hal_gemm64fc armpl_hal_gemm64fc
int armpl_hal_LU32f(float* a, size_t a_step, int m, float* b, size_t b_step, int n, int* info);
int armpl_hal_LU64f(double* a, size_t a_step, int m, double* b, size_t b_step, int n, int* info);
#undef cv_hal_LU32f
#define cv_hal_LU32f armpl_hal_LU32f
#undef cv_hal_LU64f
#define cv_hal_LU64f armpl_hal_LU64f
#endif // HAVE_ARMPL
#endif // OPENCV_ARMPL_HAL_CORE_HPP
+62
View File
@@ -4,6 +4,7 @@
#include <fftw3.h>
#include <cblas.h>
#include <lapacke.h>
#include <algorithm>
#include <complex>
#include <cstring>
@@ -11,6 +12,7 @@
#include <cmath>
#define ARMPL_GEMM_MIN_WORK_VOLUME 10000
#define ARMPL_LU_SMALL_MATRIX_THRESH 100
namespace {
@@ -172,6 +174,66 @@ int armpl_hal_gemm64fc(const double *src1, size_t src1_step, const double *src2,
reinterpret_cast<const cplx*>(src3), src3_step, beta, reinterpret_cast<cplx*>(dst), dst_step, m, n, k, flags);
}
static inline armpl_int_t armpl_lapacke_gesv(int m, int n, float *a, int lda, armpl_int_t *ipiv, float *b, int ldb){
return LAPACKE_sgesv(LAPACK_ROW_MAJOR, m, n, a, lda, ipiv, b, ldb);
}
static inline armpl_int_t armpl_lapacke_gesv(int m, int n, double *a, int lda, armpl_int_t *ipiv, double *b, int ldb){
return LAPACKE_dgesv(LAPACK_ROW_MAJOR, m, n, a, lda, ipiv, b, ldb);
}
static inline armpl_int_t armpl_lapacke_getrf(int m, float *a, int lda, armpl_int_t *ipiv){
return LAPACKE_sgetrf(LAPACK_ROW_MAJOR, m, m, a, lda, ipiv);
}
static inline armpl_int_t armpl_lapacke_getrf(int m, double *a, int lda, armpl_int_t *ipiv){
return LAPACKE_dgetrf(LAPACK_ROW_MAJOR, m, m, a, lda, ipiv);
}
template <typename fptype> static inline int
armpl_lu(fptype *a, size_t a_step, int m, fptype *b, size_t b_step, int n, int *info)
{
if(!info)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
int lda = (int)(a_step / sizeof(fptype));
std::vector<armpl_int_t> ipiv(m);
armpl_int_t linfo;
if (b)
{
int ldb = (int)(b_step / sizeof(fptype));
linfo = armpl_lapacke_gesv(m, n, a, lda, ipiv.data(), b, ldb);
}
else
{
linfo = armpl_lapacke_getrf(m, a, lda, ipiv.data());
}
if (linfo < 0)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
if (linfo == 0)
{
int sign = 0;
for (int i = 0; i < m; i++)
sign ^= (ipiv[i] != i + 1);
*info = sign ? -1 : 1;
}
else
*info = 0;
return CV_HAL_ERROR_OK;
}
int armpl_hal_LU32f(float *a, size_t a_step, int m, float *b, size_t b_step, int n, int *info) {
if (m < ARMPL_LU_SMALL_MATRIX_THRESH)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
return armpl_lu(a, a_step, m, b, b_step, n, info);
}
int armpl_hal_LU64f(double *a, size_t a_step, int m, double *b, size_t b_step, int n, int *info) {
if (m < ARMPL_LU_SMALL_MATRIX_THRESH)
return CV_HAL_ERROR_NOT_IMPLEMENTED;
return armpl_lu(a, a_step, m, b, b_step, n, info);
}
enum ArmPLDFTMode
{
ARMPL_DFT_C2C,