From 6b04d456b39a145d1996ae0c031ef5e62d2f4e6a Mon Sep 17 00:00:00 2001 From: Teddy-Yangjiale <12411723@mail.sustech.edu.cn> Date: Thu, 23 Jul 2026 10:17:18 +0800 Subject: [PATCH] add accuracy test for fastGemmThin --- modules/dnn/test/test_fast_gemm.cpp | 85 +++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 modules/dnn/test/test_fast_gemm.cpp diff --git a/modules/dnn/test/test_fast_gemm.cpp b/modules/dnn/test/test_fast_gemm.cpp new file mode 100644 index 0000000000..23de8dd0bf --- /dev/null +++ b/modules/dnn/test/test_fast_gemm.cpp @@ -0,0 +1,85 @@ +// This file is part of OpenCV project. +// It is subject to the license terms in the LICENSE file found in the top-level directory +// of this distribution and at http://opencv.org/license.html. + +#include "test_precomp.hpp" + +namespace opencv_test { namespace { + +static Mat referenceMatMul(const Mat& A, const Mat& B, bool trans_a, float alpha) +{ + const int M = trans_a ? A.cols : A.rows; + const int K = trans_a ? A.rows : A.cols; + const int N = B.cols; + Mat expected(M, N, CV_32F); + + for (int m = 0; m < M; m++) + { + float* dst = expected.ptr(m); + for (int n = 0; n < N; n++) + { + float acc = 0.f; + for (int k = 0; k < K; k++) + { + const float a = trans_a ? A.ptr(k)[m] : A.ptr(m)[k]; + acc += a * B.ptr(k)[n]; + } + dst[n] = alpha * acc; + } + } + return expected; +} + +// Exercises the fastGemmThin path (constant-B MatMul): M covers every register +// block width and the multi-block remainder, N covers full strips and partial +// column tails for any VLEN <= 512. +TEST(DNN_FastGemmThin, MatMulAccuracy) +{ + static const int m_values[] = { 1, 2, 3, 4, 5 }; + static const int k_values[] = { 1, 3, 4, 7, 16, 64 }; + static const int n_values[] = { 16, 19, 64, 67, 80, 83 }; + static const float alpha_values[] = { 1.f, -0.5f }; + + RNG rng(0x5EED); + for (int M : m_values) + { + for (int N : n_values) + { + for (int K : k_values) + { + Mat B(K, N, CV_32F); + rng.fill(B, RNG::UNIFORM, -1.f, 1.f); + + for (int trans_a = 0; trans_a <= 1; trans_a++) + { + Mat A(trans_a ? K : M, trans_a ? M : K, CV_32F); + rng.fill(A, RNG::UNIFORM, -1.f, 1.f); + + for (float alpha : alpha_values) + { + LayerParams lp; + lp.type = "MatMul"; + lp.name = "thin_matmul"; + lp.set("transA", trans_a != 0); + lp.set("transB", false); + lp.set("alpha", alpha); + lp.blobs.push_back(B); + + Net net; + net.addLayerToPrev(lp.name, lp.type, lp); + net.setInputsNames(std::vector{ "A" }); + net.setInput(A, "A"); + Mat actual = net.forward(); + Mat expected = referenceMatMul(A, B, trans_a != 0, alpha); + + EXPECT_LE(cv::norm(expected, actual, NORM_INF), 2e-5f * std::max(K, 1)) + << "M=" << M << ", N=" << N << ", K=" << K + << ", trans_a=" << trans_a << ", alpha=" << alpha; + } + } + } + } + } +} + +}} // namespace