diff --git a/modules/ml/perf/perf_knn.cpp b/modules/ml/perf/perf_knn.cpp new file mode 100644 index 0000000000..f911b6520e --- /dev/null +++ b/modules/ml/perf/perf_knn.cpp @@ -0,0 +1,38 @@ +// 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 "perf_precomp.hpp" + +namespace opencv_test { namespace { + +// KNN brute-force findNearest: dominated by the per-sample L2 distance reduction. +typedef TestBaseWithParam< tuple > KNNFindNearest; // (train samples, dims, K) + +PERF_TEST_P(KNNFindNearest, brute_force, testing::Values( + make_tuple(5000, 128, 5), + make_tuple(10000, 64, 10))) +{ + const int nsamples = get<0>(GetParam()); + const int dims = get<1>(GetParam()); + const int K = get<2>(GetParam()); + const int nquery = 2000; + + Mat train(nsamples, dims, CV_32F), responses(nsamples, 1, CV_32F), query(nquery, dims, CV_32F); + RNG& rng = theRNG(); + rng.fill(train, RNG::UNIFORM, 0.f, 1.f); + rng.fill(query, RNG::UNIFORM, 0.f, 1.f); + for (int i = 0; i < nsamples; i++) + responses.at(i) = (float)(i & 1); + + Ptr knn = KNearest::create(); + knn->setAlgorithmType(KNearest::BRUTE_FORCE); + knn->setDefaultK(K); + knn->train(train, ROW_SAMPLE, responses); + + Mat results, neighbors, dists; + TEST_CYCLE() knn->findNearest(query, K, results, neighbors, dists); + + SANITY_CHECK_NOTHING(); +} + +}} // namespace diff --git a/modules/ml/perf/perf_main.cpp b/modules/ml/perf/perf_main.cpp new file mode 100644 index 0000000000..ccdf300c6e --- /dev/null +++ b/modules/ml/perf/perf_main.cpp @@ -0,0 +1,6 @@ +// 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 "perf_precomp.hpp" + +CV_PERF_TEST_MAIN(ml) diff --git a/modules/ml/perf/perf_precomp.hpp b/modules/ml/perf/perf_precomp.hpp new file mode 100644 index 0000000000..de2c7acaba --- /dev/null +++ b/modules/ml/perf/perf_precomp.hpp @@ -0,0 +1,15 @@ +// 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. +#ifndef __OPENCV_PERF_PRECOMP_HPP__ +#define __OPENCV_PERF_PRECOMP_HPP__ + +#include +#include + +namespace opencv_test { +using namespace perf; +using namespace cv::ml; +} + +#endif diff --git a/modules/ml/src/knearest.cpp b/modules/ml/src/knearest.cpp index bd9137b24b..c4aba028bc 100644 --- a/modules/ml/src/knearest.cpp +++ b/modules/ml/src/knearest.cpp @@ -41,6 +41,7 @@ //M*/ #include "precomp.hpp" +#include "opencv2/core/hal/intrin.hpp" #include "kdtree.hpp" /****************************************************************************************\ @@ -171,13 +172,21 @@ public: const float* u = _samples.ptr(testidx + range.start); float s = 0; - for( i = 0; i <= d - 4; i += 4 ) + i = 0; +#if (CV_SIMD || CV_SIMD_SCALABLE) { - float t0 = u[i] - v[i], t1 = u[i+1] - v[i+1]; - float t2 = u[i+2] - v[i+2], t3 = u[i+3] - v[i+3]; - s += t0*t0 + t1*t1 + t2*t2 + t3*t3; + const int vl = VTraits::vlanes(); + v_float32 a0 = vx_setzero_f32(), a1 = vx_setzero_f32(); + for( ; i <= d - 2*vl; i += 2*vl ) + { + v_float32 d0 = v_sub(vx_load(u + i), vx_load(v + i)); + a0 = v_fma(d0, d0, a0); + v_float32 d1 = v_sub(vx_load(u + i + vl), vx_load(v + i + vl)); + a1 = v_fma(d1, d1, a1); + } + s = v_reduce_sum(v_add(a0, a1)); } - +#endif for( ; i < d; i++ ) { float t0 = u[i] - v[i];