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
13using base::TimeTicks;
14using std::fill;
15
16namespace media {
17
18static const int kBenchmarkIterations = 200000;
19static const int kEWMABenchmarkIterations = 50000;
20static const float kScale = 0.5;
21static const int kVectorSize = 8192;
22
23class 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.
94TEST_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.
113TEST_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.
132TEST_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