From a5cd62f7bfbc0b67c59f54c05d7bbe669581fff6 Mon Sep 17 00:00:00 2001 From: Alexander Alekhin Date: Thu, 18 Jan 2018 18:11:30 +0300 Subject: [PATCH] core(perf): refactor kmeans test - don't use RNG for "task size" parameters (N, K, dims) - add "good" kmeans test data (without singularities: K > unique points) --- modules/core/perf/perf_math.cpp | 127 +++++++++++++++++++++++++------- 1 file changed, 101 insertions(+), 26 deletions(-) diff --git a/modules/core/perf/perf_math.cpp b/modules/core/perf/perf_math.cpp index eb3fbb0b24..944db96a47 100644 --- a/modules/core/perf/perf_math.cpp +++ b/modules/core/perf/perf_math.cpp @@ -3,14 +3,11 @@ using namespace std; using namespace cv; using namespace perf; -using std::tr1::make_tuple; -using std::tr1::get; + +namespace { typedef perf::TestBaseWithParam VectorLength; -typedef std::tr1::tuple MaxDim_MaxPoints_t; -typedef perf::TestBaseWithParam MaxDim_MaxPoints; - PERF_TEST_P(VectorLength, phase32f, testing::Values(128, 1000, 128*1024, 512*1024, 1024*1024)) { size_t length = GetParam(); @@ -39,47 +36,125 @@ PERF_TEST_P(VectorLength, phase64f, testing::Values(128, 1000, 128*1024, 512*102 SANITY_CHECK(angle, 5e-5); } -PERF_TEST_P( MaxDim_MaxPoints, kmeans, - testing::Combine( testing::Values( 16, 32, 64 ), - testing::Values( 300, 400, 500) ) ) +typedef perf::TestBaseWithParam< testing::tuple > KMeans; + +PERF_TEST_P_(KMeans, single_iter) { RNG& rng = theRNG(); - const int MAX_DIM = get<0>(GetParam()); - const int MAX_POINTS = get<1>(GetParam()); + const int K = testing::get<0>(GetParam()); + const int dims = testing::get<1>(GetParam()); + const int N = testing::get<2>(GetParam()); const int attempts = 5; - Mat labels, centers; - int i, N = 0, N0 = 0, K = 0, dims = 0; - dims = rng.uniform(1, MAX_DIM+1); - N = rng.uniform(1, MAX_POINTS+1); - N0 = rng.uniform(1, MAX(N/10, 2)); - K = rng.uniform(1, N+1); + Mat data(N, dims, CV_32F); + rng.fill(data, RNG::UNIFORM, -0.1, 0.1); + const int N0 = K; Mat data0(N0, dims, CV_32F); rng.fill(data0, RNG::UNIFORM, -1, 1); - Mat data(N, dims, CV_32F); - for( i = 0; i < N; i++ ) - data0.row(rng.uniform(0, N0)).copyTo(data.row(i)); + for (int i = 0; i < N; i++) + { + int base = rng.uniform(0, N0); + cv::add(data0.row(base), data.row(i), data.row(i)); + } declare.in(data); + Mat labels, centers; + + TEST_CYCLE() + { + kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 1, 0), + attempts, KMEANS_PP_CENTERS, centers); + } + + SANITY_CHECK_NOTHING(); +} + +PERF_TEST_P_(KMeans, good) +{ + RNG& rng = theRNG(); + const int K = testing::get<0>(GetParam()); + const int dims = testing::get<1>(GetParam()); + const int N = testing::get<2>(GetParam()); + const int attempts = 5; + + Mat data(N, dims, CV_32F); + rng.fill(data, RNG::UNIFORM, -0.1, 0.1); + + const int N0 = K; + Mat data0(N0, dims, CV_32F); + rng.fill(data0, RNG::UNIFORM, -1, 1); + + for (int i = 0; i < N; i++) + { + int base = rng.uniform(0, N0); + cv::add(data0.row(base), data.row(i), data.row(i)); + } + + declare.in(data); + + Mat labels, centers; + TEST_CYCLE() { kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0), attempts, KMEANS_PP_CENTERS, centers); } - Mat clusterPointsNumber = Mat::zeros(1, K, CV_32S); + SANITY_CHECK_NOTHING(); +} - for( i = 0; i < labels.rows; i++ ) +PERF_TEST_P_(KMeans, with_duplicates) +{ + RNG& rng = theRNG(); + const int K = testing::get<0>(GetParam()); + const int dims = testing::get<1>(GetParam()); + const int N = testing::get<2>(GetParam()); + const int attempts = 5; + + Mat data(N, dims, CV_32F, Scalar::all(0)); + + const int N0 = std::max(2, K * 2 / 3); + Mat data0(N0, dims, CV_32F); + rng.fill(data0, RNG::UNIFORM, -1, 1); + + for (int i = 0; i < N; i++) { - int clusterIdx = labels.at(i); - clusterPointsNumber.at(clusterIdx)++; + int base = rng.uniform(0, N0); + data0.row(base).copyTo(data.row(i)); } - Mat sortedClusterPointsNumber; - cv::sort(clusterPointsNumber, sortedClusterPointsNumber, cv::SORT_EVERY_ROW + cv::SORT_ASCENDING); + declare.in(data); + + Mat labels, centers; + + TEST_CYCLE() + { + kmeans(data, K, labels, TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS, 30, 0), + attempts, KMEANS_PP_CENTERS, centers); + } + + SANITY_CHECK_NOTHING(); +} + +INSTANTIATE_TEST_CASE_P(/*nothing*/ , KMeans, + testing::Values( + // K clusters, dims, N points + testing::make_tuple(2, 3, 100000), + testing::make_tuple(4, 3, 500), + testing::make_tuple(4, 3, 1000), + testing::make_tuple(4, 3, 10000), + testing::make_tuple(8, 3, 1000), + testing::make_tuple(8, 16, 1000), + testing::make_tuple(8, 64, 1000), + testing::make_tuple(16, 16, 1000), + testing::make_tuple(16, 32, 1000), + testing::make_tuple(32, 16, 1000), + testing::make_tuple(32, 32, 1000), + testing::make_tuple(100, 2, 1000) + ) +); - SANITY_CHECK(sortedClusterPointsNumber); }