mirror of
https://github.com/opencv/opencv.git
synced 2026-07-21 19:33:03 +04:00
84d900cfda
Vectorize the per-sample squared-Euclidean distance in BruteForceImpl::findNearestCore with universal intrinsics (two independent v_fma accumulators + scalar tail). The scalar reduction accumulates in float in strict order, which the compiler cannot auto-vectorize without -ffast-math; independent SIMD accumulators break that serial-accumulation dependency. Accumulates in float exactly as before (only summation order changes, ~1e-7, below stored float precision); selected neighbors and distances matched scalar on all test data, ML_KNearest tests pass. Real findNearest A/B: 3.76x M4, 3.47x Threadripper, 3.73x Xeon, 4.10x A76, 2.82x A55 (in-order). Adds modules/ml/perf with a findNearest perf test.
39 lines
1.3 KiB
C++
39 lines
1.3 KiB
C++
// 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
|