mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
Merge pull request #29380 from tonuonu:perf-knn-findnearest-simd
ml: SIMD for KNN brute-force findNearest 🧑💻🤖
This commit is contained in:
@@ -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<int, int, int> > 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<float>(i) = (float)(i & 1);
|
||||
|
||||
Ptr<KNearest> 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
|
||||
@@ -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)
|
||||
@@ -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 <opencv2/ts.hpp>
|
||||
#include <opencv2/ml.hpp>
|
||||
|
||||
namespace opencv_test {
|
||||
using namespace perf;
|
||||
using namespace cv::ml;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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<float>(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<v_float32>::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];
|
||||
|
||||
Reference in New Issue
Block a user