tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

av1_k_means_test.cc (10433B)


      1 /*
      2 * Copyright (c) 2020, Alliance for Open Media. All rights reserved.
      3 *
      4 * This source code is subject to the terms of the BSD 2 Clause License and
      5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
      6 * was not distributed with this source code in the LICENSE file, you can
      7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
      8 * Media Patent License 1.0 was not distributed with this source code in the
      9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
     10 */
     11 
     12 #include <cstdlib>
     13 #include <new>
     14 #include <tuple>
     15 
     16 #include "config/aom_config.h"
     17 #include "config/av1_rtcd.h"
     18 
     19 #include "aom/aom_codec.h"
     20 #include "aom/aom_integer.h"
     21 #include "aom_mem/aom_mem.h"
     22 #include "aom_ports/aom_timer.h"
     23 #include "aom_ports/mem.h"
     24 #include "av1/encoder/palette.h"
     25 #include "gtest/gtest.h"
     26 #include "test/acm_random.h"
     27 #include "test/register_state_check.h"
     28 #include "test/util.h"
     29 
     30 namespace AV1Kmeans {
     31 using av1_calc_indices_dim1_func = void (*)(const int16_t *data,
     32                                            const int16_t *centroids,
     33                                            uint8_t *indices,
     34                                            int64_t *total_dist, int n, int k);
     35 using av1_calc_indices_dim2_func = void (*)(const int16_t *data,
     36                                            const int16_t *centroids,
     37                                            uint8_t *indices,
     38                                            int64_t *total_dist, int n, int k);
     39 
     40 using av1_calc_indices_dim1Param =
     41    std::tuple<av1_calc_indices_dim1_func, BLOCK_SIZE>;
     42 
     43 using av1_calc_indices_dim2Param =
     44    std::tuple<av1_calc_indices_dim2_func, BLOCK_SIZE>;
     45 
     46 class AV1KmeansTest1
     47    : public ::testing::TestWithParam<av1_calc_indices_dim1Param> {
     48 public:
     49  ~AV1KmeansTest1() override;
     50  void SetUp() override;
     51 
     52 protected:
     53  void RunCheckOutput(av1_calc_indices_dim1_func test_impl, BLOCK_SIZE bsize,
     54                      int centroids);
     55  void RunSpeedTest(av1_calc_indices_dim1_func test_impl, BLOCK_SIZE bsize,
     56                    int centroids);
     57  bool CheckResult(int n) {
     58    for (int idx = 0; idx < n; ++idx) {
     59      if (indices1_[idx] != indices2_[idx]) {
     60        printf("%d ", idx);
     61        printf("%d != %d ", indices1_[idx], indices2_[idx]);
     62        return false;
     63      }
     64    }
     65    return true;
     66  }
     67 
     68  libaom_test::ACMRandom rnd_;
     69  int16_t data_[4096];
     70  int16_t centroids_[8];
     71  uint8_t indices1_[4096];
     72  uint8_t indices2_[4096];
     73 };
     74 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AV1KmeansTest1);
     75 
     76 AV1KmeansTest1::~AV1KmeansTest1() = default;
     77 
     78 void AV1KmeansTest1::SetUp() {
     79  rnd_.Reset(libaom_test::ACMRandom::DeterministicSeed());
     80  for (int i = 0; i < 4096; ++i) {
     81    data_[i] = (int)rnd_.Rand8() << 4;
     82  }
     83  for (int i = 0; i < 8; i++) {
     84    centroids_[i] = (int)rnd_.Rand8() << 4;
     85  }
     86 }
     87 
     88 void AV1KmeansTest1::RunCheckOutput(av1_calc_indices_dim1_func test_impl,
     89                                    BLOCK_SIZE bsize, int k) {
     90  const int w = block_size_wide[bsize];
     91  const int h = block_size_high[bsize];
     92  const int n = w * h;
     93  int64_t total_dist_dim1, total_dist_impl;
     94  av1_calc_indices_dim1_c(data_, centroids_, indices1_, &total_dist_dim1, n, k);
     95  test_impl(data_, centroids_, indices2_, &total_dist_impl, n, k);
     96 
     97  ASSERT_EQ(total_dist_dim1, total_dist_impl);
     98  ASSERT_EQ(CheckResult(n), true)
     99      << " block " << bsize << " index " << n << " Centroids " << k;
    100 }
    101 
    102 void AV1KmeansTest1::RunSpeedTest(av1_calc_indices_dim1_func test_impl,
    103                                  BLOCK_SIZE bsize, int k) {
    104  const int w = block_size_wide[bsize];
    105  const int h = block_size_high[bsize];
    106  const int n = w * h;
    107  const int num_loops = 1000000000 / n;
    108 
    109  av1_calc_indices_dim1_func funcs[2] = { av1_calc_indices_dim1_c, test_impl };
    110  double elapsed_time[2] = { 0 };
    111  for (int i = 0; i < 2; ++i) {
    112    aom_usec_timer timer;
    113    aom_usec_timer_start(&timer);
    114    av1_calc_indices_dim1_func func = funcs[i];
    115    for (int j = 0; j < num_loops; ++j) {
    116      func(data_, centroids_, indices1_, /*total_dist=*/nullptr, n, k);
    117    }
    118    aom_usec_timer_mark(&timer);
    119    double time = static_cast<double>(aom_usec_timer_elapsed(&timer));
    120    elapsed_time[i] = 1000.0 * time / num_loops;
    121  }
    122  printf("av1_calc_indices_dim1 indices= %d centroids=%d: %7.2f/%7.2fns", n, k,
    123         elapsed_time[0], elapsed_time[1]);
    124  printf("(%3.2f)\n", elapsed_time[0] / elapsed_time[1]);
    125 }
    126 
    127 TEST_P(AV1KmeansTest1, CheckOutput) {
    128  // centroids = 2..8
    129  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 2);
    130  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 3);
    131  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 4);
    132  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 5);
    133  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 6);
    134  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 7);
    135  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 8);
    136 }
    137 
    138 TEST_P(AV1KmeansTest1, DISABLED_Speed) {
    139  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 2);
    140  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 3);
    141  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 4);
    142  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 5);
    143  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 6);
    144  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 7);
    145  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 8);
    146 }
    147 
    148 class AV1KmeansTest2
    149    : public ::testing::TestWithParam<av1_calc_indices_dim2Param> {
    150 public:
    151  ~AV1KmeansTest2() override;
    152  void SetUp() override;
    153 
    154 protected:
    155  void RunCheckOutput(av1_calc_indices_dim2_func test_impl, BLOCK_SIZE bsize,
    156                      int centroids);
    157  void RunSpeedTest(av1_calc_indices_dim2_func test_impl, BLOCK_SIZE bsize,
    158                    int centroids);
    159  bool CheckResult(int n) {
    160    bool flag = true;
    161    for (int idx = 0; idx < n; ++idx) {
    162      if (indices1_[idx] != indices2_[idx]) {
    163        printf("%d ", idx);
    164        printf("%d != %d ", indices1_[idx], indices2_[idx]);
    165        flag = false;
    166      }
    167    }
    168    if (flag == false) {
    169      return false;
    170    }
    171    return true;
    172  }
    173 
    174  libaom_test::ACMRandom rnd_;
    175  int16_t data_[4096 * 2];
    176  int16_t centroids_[8 * 2];
    177  uint8_t indices1_[4096];
    178  uint8_t indices2_[4096];
    179 };
    180 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AV1KmeansTest2);
    181 
    182 AV1KmeansTest2::~AV1KmeansTest2() = default;
    183 
    184 void AV1KmeansTest2::SetUp() {
    185  rnd_.Reset(libaom_test::ACMRandom::DeterministicSeed());
    186  for (int i = 0; i < 4096 * 2; ++i) {
    187    data_[i] = (int)rnd_.Rand8();
    188  }
    189  for (int i = 0; i < 8 * 2; i++) {
    190    centroids_[i] = (int)rnd_.Rand8();
    191  }
    192 }
    193 
    194 void AV1KmeansTest2::RunCheckOutput(av1_calc_indices_dim2_func test_impl,
    195                                    BLOCK_SIZE bsize, int k) {
    196  const int w = block_size_wide[bsize];
    197  const int h = block_size_high[bsize];
    198  const int n = w * h;
    199  int64_t total_dist_dim2, total_dist_impl;
    200  av1_calc_indices_dim2_c(data_, centroids_, indices1_, &total_dist_dim2, n, k);
    201  test_impl(data_, centroids_, indices2_, &total_dist_impl, n, k);
    202 
    203  ASSERT_EQ(total_dist_dim2, total_dist_impl);
    204  ASSERT_EQ(CheckResult(n), true)
    205      << " block " << bsize << " index " << n << " Centroids " << k;
    206 }
    207 
    208 void AV1KmeansTest2::RunSpeedTest(av1_calc_indices_dim2_func test_impl,
    209                                  BLOCK_SIZE bsize, int k) {
    210  const int w = block_size_wide[bsize];
    211  const int h = block_size_high[bsize];
    212  const int n = w * h;
    213  const int num_loops = 1000000000 / n;
    214 
    215  av1_calc_indices_dim2_func funcs[2] = { av1_calc_indices_dim2_c, test_impl };
    216  double elapsed_time[2] = { 0 };
    217  for (int i = 0; i < 2; ++i) {
    218    aom_usec_timer timer;
    219    aom_usec_timer_start(&timer);
    220    av1_calc_indices_dim2_func func = funcs[i];
    221    for (int j = 0; j < num_loops; ++j) {
    222      func(data_, centroids_, indices1_, /*total_dist=*/nullptr, n, k);
    223    }
    224    aom_usec_timer_mark(&timer);
    225    double time = static_cast<double>(aom_usec_timer_elapsed(&timer));
    226    elapsed_time[i] = 1000.0 * time / num_loops;
    227  }
    228  printf("av1_calc_indices_dim2 indices= %d centroids=%d: %7.2f/%7.2fns", n, k,
    229         elapsed_time[0], elapsed_time[1]);
    230  printf("(%3.2f)\n", elapsed_time[0] / elapsed_time[1]);
    231 }
    232 
    233 TEST_P(AV1KmeansTest2, CheckOutput) {
    234  // centroids = 2..8
    235  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 2);
    236  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 3);
    237  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 4);
    238  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 5);
    239  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 6);
    240  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 7);
    241  RunCheckOutput(GET_PARAM(0), GET_PARAM(1), 8);
    242 }
    243 
    244 TEST_P(AV1KmeansTest2, DISABLED_Speed) {
    245  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 2);
    246  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 3);
    247  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 4);
    248  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 5);
    249  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 6);
    250  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 7);
    251  RunSpeedTest(GET_PARAM(0), GET_PARAM(1), 8);
    252 }
    253 
    254 #if HAVE_SSE2 || HAVE_AVX2 || HAVE_NEON
    255 const BLOCK_SIZE kValidBlockSize[] = { BLOCK_8X8,   BLOCK_8X16,  BLOCK_8X32,
    256                                       BLOCK_16X8,  BLOCK_16X16, BLOCK_16X32,
    257                                       BLOCK_32X8,  BLOCK_32X16, BLOCK_32X32,
    258                                       BLOCK_32X64, BLOCK_64X32, BLOCK_64X64,
    259                                       BLOCK_16X64, BLOCK_64X16 };
    260 #endif
    261 
    262 #if HAVE_SSE2
    263 INSTANTIATE_TEST_SUITE_P(
    264    SSE2, AV1KmeansTest1,
    265    ::testing::Combine(::testing::Values(&av1_calc_indices_dim1_sse2),
    266                       ::testing::ValuesIn(kValidBlockSize)));
    267 INSTANTIATE_TEST_SUITE_P(
    268    SSE2, AV1KmeansTest2,
    269    ::testing::Combine(::testing::Values(&av1_calc_indices_dim2_sse2),
    270                       ::testing::ValuesIn(kValidBlockSize)));
    271 #endif
    272 
    273 #if HAVE_AVX2
    274 INSTANTIATE_TEST_SUITE_P(
    275    AVX2, AV1KmeansTest1,
    276    ::testing::Combine(::testing::Values(&av1_calc_indices_dim1_avx2),
    277                       ::testing::ValuesIn(kValidBlockSize)));
    278 INSTANTIATE_TEST_SUITE_P(
    279    AVX2, AV1KmeansTest2,
    280    ::testing::Combine(::testing::Values(&av1_calc_indices_dim2_avx2),
    281                       ::testing::ValuesIn(kValidBlockSize)));
    282 #endif
    283 
    284 #if HAVE_NEON
    285 INSTANTIATE_TEST_SUITE_P(
    286    NEON, AV1KmeansTest1,
    287    ::testing::Combine(::testing::Values(&av1_calc_indices_dim1_neon),
    288                       ::testing::ValuesIn(kValidBlockSize)));
    289 INSTANTIATE_TEST_SUITE_P(
    290    NEON, AV1KmeansTest2,
    291    ::testing::Combine(::testing::Values(&av1_calc_indices_dim2_neon),
    292                       ::testing::ValuesIn(kValidBlockSize)));
    293 #endif
    294 
    295 }  // namespace AV1Kmeans