Home | History | Annotate | Download | only in base
      1 // Copyright 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/memory/aligned_memory.h"
      6 #include "base/memory/scoped_ptr.h"
      7 #include "base/time/time.h"
      8 #include "media/base/vector_math.h"
      9 #include "media/base/vector_math_testing.h"
     10 #include "testing/gtest/include/gtest/gtest.h"
     11 #include "testing/perf/perf_test.h"
     12 
     13 using base::TimeTicks;
     14 using std::fill;
     15 
     16 namespace media {
     17 
     18 static const int kBenchmarkIterations = 200000;
     19 static const int kEWMABenchmarkIterations = 50000;
     20 static const float kScale = 0.5;
     21 static const int kVectorSize = 8192;
     22 
     23 class VectorMathPerfTest : public testing::Test {
     24  public:
     25   VectorMathPerfTest() {
     26     // Initialize input and output vectors.
     27     input_vector_.reset(static_cast<float*>(base::AlignedAlloc(
     28         sizeof(float) * kVectorSize, vector_math::kRequiredAlignment)));
     29     output_vector_.reset(static_cast<float*>(base::AlignedAlloc(
     30         sizeof(float) * kVectorSize, vector_math::kRequiredAlignment)));
     31     fill(input_vector_.get(), input_vector_.get() + kVectorSize, 1.0f);
     32     fill(output_vector_.get(), output_vector_.get() + kVectorSize, 0.0f);
     33   }
     34 
     35   void RunBenchmark(void (*fn)(const float[], float, int, float[]),
     36                     bool aligned,
     37                     const std::string& test_name,
     38                     const std::string& trace_name) {
     39     TimeTicks start = TimeTicks::HighResNow();
     40     for (int i = 0; i < kBenchmarkIterations; ++i) {
     41       fn(input_vector_.get(),
     42          kScale,
     43          kVectorSize - (aligned ? 0 : 1),
     44          output_vector_.get());
     45     }
     46     double total_time_milliseconds =
     47         (TimeTicks::HighResNow() - start).InMillisecondsF();
     48     perf_test::PrintResult(test_name,
     49                            "",
     50                            trace_name,
     51                            kBenchmarkIterations / total_time_milliseconds,
     52                            "runs/ms",
     53                            true);
     54   }
     55 
     56   void RunBenchmark(
     57       std::pair<float, float> (*fn)(float, const float[], int, float),
     58       int len,
     59       const std::string& test_name,
     60       const std::string& trace_name) {
     61     TimeTicks start = TimeTicks::HighResNow();
     62     for (int i = 0; i < kEWMABenchmarkIterations; ++i) {
     63       fn(0.5f, input_vector_.get(), len, 0.1f);
     64     }
     65     double total_time_milliseconds =
     66         (TimeTicks::HighResNow() - start).InMillisecondsF();
     67     perf_test::PrintResult(test_name,
     68                            "",
     69                            trace_name,
     70                            kEWMABenchmarkIterations / total_time_milliseconds,
     71                            "runs/ms",
     72                            true);
     73   }
     74 
     75  protected:
     76   scoped_ptr<float, base::AlignedFreeDeleter> input_vector_;
     77   scoped_ptr<float, base::AlignedFreeDeleter> output_vector_;
     78 
     79   DISALLOW_COPY_AND_ASSIGN(VectorMathPerfTest);
     80 };
     81 
     82 // Define platform dependent function names for SIMD optimized methods.
     83 #if defined(ARCH_CPU_X86_FAMILY)
     84 #define FMAC_FUNC FMAC_SSE
     85 #define FMUL_FUNC FMUL_SSE
     86 #define EWMAAndMaxPower_FUNC EWMAAndMaxPower_SSE
     87 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(USE_NEON)
     88 #define FMAC_FUNC FMAC_NEON
     89 #define FMUL_FUNC FMUL_NEON
     90 #define EWMAAndMaxPower_FUNC EWMAAndMaxPower_NEON
     91 #endif
     92 
     93 // Benchmark for each optimized vector_math::FMAC() method.
     94 TEST_F(VectorMathPerfTest, FMAC) {
     95   // Benchmark FMAC_C().
     96   RunBenchmark(
     97       vector_math::FMAC_C, true, "vector_math_fmac", "unoptimized");
     98 #if defined(FMAC_FUNC)
     99   // Benchmark FMAC_FUNC() with unaligned size.
    100   ASSERT_NE((kVectorSize - 1) % (vector_math::kRequiredAlignment /
    101                                  sizeof(float)), 0U);
    102   RunBenchmark(
    103       vector_math::FMAC_FUNC, false, "vector_math_fmac", "optimized_unaligned");
    104   // Benchmark FMAC_FUNC() with aligned size.
    105   ASSERT_EQ(kVectorSize % (vector_math::kRequiredAlignment / sizeof(float)),
    106             0U);
    107   RunBenchmark(
    108       vector_math::FMAC_FUNC, true, "vector_math_fmac", "optimized_aligned");
    109 #endif
    110 }
    111 
    112 // Benchmark for each optimized vector_math::FMUL() method.
    113 TEST_F(VectorMathPerfTest, FMUL) {
    114   // Benchmark FMUL_C().
    115   RunBenchmark(
    116       vector_math::FMUL_C, true, "vector_math_fmul", "unoptimized");
    117 #if defined(FMUL_FUNC)
    118   // Benchmark FMUL_FUNC() with unaligned size.
    119   ASSERT_NE((kVectorSize - 1) % (vector_math::kRequiredAlignment /
    120                                  sizeof(float)), 0U);
    121   RunBenchmark(
    122       vector_math::FMUL_FUNC, false, "vector_math_fmul", "optimized_unaligned");
    123   // Benchmark FMUL_FUNC() with aligned size.
    124   ASSERT_EQ(kVectorSize % (vector_math::kRequiredAlignment / sizeof(float)),
    125             0U);
    126   RunBenchmark(
    127       vector_math::FMUL_FUNC, true, "vector_math_fmul", "optimized_aligned");
    128 #endif
    129 }
    130 
    131 // Benchmark for each optimized vector_math::EWMAAndMaxPower() method.
    132 TEST_F(VectorMathPerfTest, EWMAAndMaxPower) {
    133   // Benchmark EWMAAndMaxPower_C().
    134   RunBenchmark(vector_math::EWMAAndMaxPower_C,
    135                kVectorSize,
    136                "vector_math_ewma_and_max_power",
    137                "unoptimized");
    138 #if defined(EWMAAndMaxPower_FUNC)
    139   // Benchmark EWMAAndMaxPower_FUNC() with unaligned size.
    140   ASSERT_NE((kVectorSize - 1) % (vector_math::kRequiredAlignment /
    141                                  sizeof(float)), 0U);
    142   RunBenchmark(vector_math::EWMAAndMaxPower_FUNC,
    143                kVectorSize - 1,
    144                "vector_math_ewma_and_max_power",
    145                "optimized_unaligned");
    146   // Benchmark EWMAAndMaxPower_FUNC() with aligned size.
    147   ASSERT_EQ(kVectorSize % (vector_math::kRequiredAlignment / sizeof(float)),
    148             0U);
    149   RunBenchmark(vector_math::EWMAAndMaxPower_FUNC,
    150                kVectorSize,
    151                "vector_math_ewma_and_max_power",
    152                "optimized_aligned");
    153 #endif
    154 }
    155 
    156 } // namespace media
    157