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