Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: media/base/sinc_resampler_unittest.cc

Issue 10960023: Add ARM NEON intrinsic optimizations for SincResampler. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // MSVC++ requires this to be set before any other includes to get M_PI. 5 // MSVC++ requires this to be set before any other includes to get M_PI.
6 #define _USE_MATH_DEFINES 6 #define _USE_MATH_DEFINES
7 7
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 EXPECT_CALL(mock_source, ProvideInput(_, _)) 88 EXPECT_CALL(mock_source, ProvideInput(_, _))
89 .Times(1).WillOnce(ClearBuffer()); 89 .Times(1).WillOnce(ClearBuffer());
90 resampler.Resample(resampled_destination.get(), resampler.ChunkSize() / 2); 90 resampler.Resample(resampled_destination.get(), resampler.ChunkSize() / 2);
91 for (int i = 0; i < resampler.ChunkSize() / 2; ++i) 91 for (int i = 0; i < resampler.ChunkSize() / 2; ++i)
92 ASSERT_EQ(resampled_destination[i], 0); 92 ASSERT_EQ(resampled_destination[i], 0);
93 } 93 }
94 94
95 // Ensure various optimized Convolve() methods return the same value. Only run 95 // Ensure various optimized Convolve() methods return the same value. Only run
96 // this test if other optimized methods exist, otherwise the default Convolve() 96 // this test if other optimized methods exist, otherwise the default Convolve()
97 // will be tested by the parameterized SincResampler tests below. 97 // will be tested by the parameterized SincResampler tests below.
98 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__)
99 TEST(SincResamplerTest, Convolve) { 98 TEST(SincResamplerTest, Convolve) {
100 // Initialize a dummy resampler. 99 // Initialize a dummy resampler.
101 MockSource mock_source; 100 MockSource mock_source;
102 SincResampler resampler( 101 SincResampler resampler(
103 kSampleRateRatio, 102 kSampleRateRatio,
104 base::Bind(&MockSource::ProvideInput, base::Unretained(&mock_source))); 103 base::Bind(&MockSource::ProvideInput, base::Unretained(&mock_source)));
105 104
106 // Convolve_SSE() is slightly more precise than Convolve_C(), so comparison 105 // Convolve_SSE() is slightly more precise than Convolve_C(), so comparison
107 // must be done using an epsilon. 106 // must be done using an epsilon.
108 static const double kEpsilon = 0.00000005; 107 static const double kEpsilon = 0.00000005;
109 108
110 // Use a kernel from SincResampler as input and kernel data, this has the 109 // Use a kernel from SincResampler as input and kernel data, this has the
111 // benefit of already being properly sized and aligned for Convolve_SSE(). 110 // benefit of already being properly sized and aligned for Convolve_SSE().
112 double result = resampler.Convolve_C( 111 double result = resampler.Convolve_C(
113 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), 112 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(),
114 resampler.kernel_storage_.get(), kKernelInterpolationFactor); 113 resampler.kernel_storage_.get(), kKernelInterpolationFactor);
115 double result2 = resampler.Convolve_SSE( 114
115 double result2 = result;
Ami GONE FROM CHROMIUM 2012/09/21 04:41:41 I don't like this b/c it'll make the test claim to
DaleCurtis 2012/09/24 19:54:37 Done.
116 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__)
117 result2 = resampler.Convolve_SSE(
116 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), 118 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(),
117 resampler.kernel_storage_.get(), kKernelInterpolationFactor); 119 resampler.kernel_storage_.get(), kKernelInterpolationFactor);
120 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(__ARM_NEON__) && defined(USE_NEON)
Ami GONE FROM CHROMIUM 2012/09/21 04:41:41 Here and elsewhere, I think __ARM_NEON__ is unnece
DaleCurtis 2012/09/24 19:54:37 Done.
121 result2 = resampler.Convolve_NEON(
122 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(),
123 resampler.kernel_storage_.get(), kKernelInterpolationFactor);
124 #endif
118 EXPECT_NEAR(result2, result, kEpsilon); 125 EXPECT_NEAR(result2, result, kEpsilon);
119 126
120 // Test Convolve_SSE() w/ unaligned input pointer. 127 // Test Convolve() w/ unaligned input pointer.
121 result = resampler.Convolve_C( 128 result = resampler.Convolve_C(
122 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), 129 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(),
123 resampler.kernel_storage_.get(), kKernelInterpolationFactor); 130 resampler.kernel_storage_.get(), kKernelInterpolationFactor);
131 #if defined(ARCH_CPU_X86_FAMILY) && defined(__SSE__)
124 result2 = resampler.Convolve_SSE( 132 result2 = resampler.Convolve_SSE(
125 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(), 133 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(),
126 resampler.kernel_storage_.get(), kKernelInterpolationFactor); 134 resampler.kernel_storage_.get(), kKernelInterpolationFactor);
135 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(__ARM_NEON__) && defined(USE_NEON)
136 result2 = resampler.Convolve_NEON(
137 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(),
138 resampler.kernel_storage_.get(), kKernelInterpolationFactor);
139 #endif
127 EXPECT_NEAR(result2, result, kEpsilon); 140 EXPECT_NEAR(result2, result, kEpsilon);
128 } 141 }
129 #endif
130 142
131 // Benchmark for the various Convolve() methods. Make sure to build with 143 // Benchmark for the various Convolve() methods. Make sure to build with
132 // branding=Chrome so that DCHECKs are compiled out when benchmarking. Original 144 // branding=Chrome so that DCHECKs are compiled out when benchmarking. Original
133 // benchmarks were run with --convolve-iterations=50000000. 145 // benchmarks were run with --convolve-iterations=50000000.
134 TEST(SincResamplerTest, ConvolveBenchmark) { 146 TEST(SincResamplerTest, ConvolveBenchmark) {
135 // Initialize a dummy resampler. 147 // Initialize a dummy resampler.
136 MockSource mock_source; 148 MockSource mock_source;
137 SincResampler resampler( 149 SincResampler resampler(
138 kSampleRateRatio, 150 kSampleRateRatio,
139 base::Bind(&MockSource::ProvideInput, base::Unretained(&mock_source))); 151 base::Bind(&MockSource::ProvideInput, base::Unretained(&mock_source)));
140 152
141 // Retrieve benchmark iterations from command line. 153 // Retrieve benchmark iterations from command line.
142 int convolve_iterations = 10; 154 int convolve_iterations = 50000000;
Ami GONE FROM CHROMIUM 2012/09/21 04:41:41 what now?
DaleCurtis 2012/09/24 19:54:37 Was just for benchmarking on the try bot, but sadl
143 std::string iterations(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 155 std::string iterations(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
144 kConvolveIterations)); 156 kConvolveIterations));
145 if (!iterations.empty()) 157 if (!iterations.empty())
146 base::StringToInt(iterations, &convolve_iterations); 158 base::StringToInt(iterations, &convolve_iterations);
147 159
148 printf("Benchmarking %d iterations:\n", convolve_iterations); 160 printf("Benchmarking %d iterations:\n", convolve_iterations);
149 161
150 // Benchmark Convolve_C(). 162 // Benchmark Convolve_C().
151 base::TimeTicks start = base::TimeTicks::HighResNow(); 163 base::TimeTicks start = base::TimeTicks::HighResNow();
152 for (int i = 0; i < convolve_iterations; ++i) { 164 for (int i = 0; i < convolve_iterations; ++i) {
(...skipping 25 matching lines...) Expand all
178 resampler.Convolve_SSE( 190 resampler.Convolve_SSE(
179 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(), 191 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(),
180 resampler.kernel_storage_.get(), kKernelInterpolationFactor); 192 resampler.kernel_storage_.get(), kKernelInterpolationFactor);
181 } 193 }
182 double total_time_sse_aligned_ms = 194 double total_time_sse_aligned_ms =
183 (base::TimeTicks::HighResNow() - start).InMillisecondsF(); 195 (base::TimeTicks::HighResNow() - start).InMillisecondsF();
184 printf("Convolve_SSE (aligned) took %.2fms; which is %.2fx faster than" 196 printf("Convolve_SSE (aligned) took %.2fms; which is %.2fx faster than"
185 " Convolve_C and %.2fx faster than Convolve_SSE (unaligned).\n", 197 " Convolve_C and %.2fx faster than Convolve_SSE (unaligned).\n",
186 total_time_sse_aligned_ms, total_time_c_ms / total_time_sse_aligned_ms, 198 total_time_sse_aligned_ms, total_time_c_ms / total_time_sse_aligned_ms,
187 total_time_sse_unaligned_ms / total_time_sse_aligned_ms); 199 total_time_sse_unaligned_ms / total_time_sse_aligned_ms);
200 #elif defined(ARCH_CPU_ARM_FAMILY) && defined(__ARM_NEON__) && defined(USE_NEON)
Ami GONE FROM CHROMIUM 2012/09/21 04:41:41 Like with the original SSE CL, IWBN to include ben
DaleCurtis 2012/09/24 19:54:37 Done.
201 // Benchmark Convolve_NEON() with unaligned input pointer.
202 start = base::TimeTicks::HighResNow();
203 for (int j = 0; j < convolve_iterations; ++j) {
204 resampler.Convolve_NEON(
205 resampler.kernel_storage_.get() + 1, resampler.kernel_storage_.get(),
206 resampler.kernel_storage_.get(), kKernelInterpolationFactor);
207 }
208 double total_time_sse_unaligned_ms =
Ami GONE FROM CHROMIUM 2012/09/22 02:38:27 there are a bunch of variables here and below that
DaleCurtis 2012/09/24 19:54:37 Done.
209 (base::TimeTicks::HighResNow() - start).InMillisecondsF();
210 printf("Convolve_NEON (unaligned) took %.2fms; which is %.2fx faster than"
211 " Convolve_C.\n", total_time_sse_unaligned_ms,
212 total_time_c_ms / total_time_sse_unaligned_ms);
213
214 // Benchmark Convolve_NEON() with aligned input pointer.
215 start = base::TimeTicks::HighResNow();
216 for (int j = 0; j < convolve_iterations; ++j) {
217 resampler.Convolve_NEON(
218 resampler.kernel_storage_.get(), resampler.kernel_storage_.get(),
219 resampler.kernel_storage_.get(), kKernelInterpolationFactor);
220 }
221 double total_time_sse_aligned_ms =
222 (base::TimeTicks::HighResNow() - start).InMillisecondsF();
223 printf("Convolve_NEON (aligned) took %.2fms; which is %.2fx faster than"
224 " Convolve_C and %.2fx faster than Convolve_SSE (unaligned).\n",
Ami GONE FROM CHROMIUM 2012/09/22 02:38:27 s/SSE/NEON/, I think :)
DaleCurtis 2012/09/24 19:54:37 Done.
225 total_time_sse_aligned_ms, total_time_c_ms / total_time_sse_aligned_ms,
226 total_time_sse_unaligned_ms / total_time_sse_aligned_ms);
188 #endif 227 #endif
189 } 228 }
190 229
191 // Fake audio source for testing the resampler. Generates a sinusoidal linear 230 // Fake audio source for testing the resampler. Generates a sinusoidal linear
192 // chirp (http://en.wikipedia.org/wiki/Chirp) which can be tuned to stress the 231 // chirp (http://en.wikipedia.org/wiki/Chirp) which can be tuned to stress the
193 // resampler for the specific sample rate conversion being used. 232 // resampler for the specific sample rate conversion being used.
194 class SinusoidalLinearChirpSource { 233 class SinusoidalLinearChirpSource {
195 public: 234 public:
196 SinusoidalLinearChirpSource(int sample_rate, int samples, 235 SinusoidalLinearChirpSource(int sample_rate, int samples,
197 double max_frequency) 236 double max_frequency)
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 std::tr1::make_tuple(11025, 192000, kResamplingRMSError, -62.61), 419 std::tr1::make_tuple(11025, 192000, kResamplingRMSError, -62.61),
381 std::tr1::make_tuple(16000, 192000, kResamplingRMSError, -63.14), 420 std::tr1::make_tuple(16000, 192000, kResamplingRMSError, -63.14),
382 std::tr1::make_tuple(22050, 192000, kResamplingRMSError, -62.42), 421 std::tr1::make_tuple(22050, 192000, kResamplingRMSError, -62.42),
383 std::tr1::make_tuple(32000, 192000, kResamplingRMSError, -63.38), 422 std::tr1::make_tuple(32000, 192000, kResamplingRMSError, -63.38),
384 std::tr1::make_tuple(44100, 192000, kResamplingRMSError, -62.63), 423 std::tr1::make_tuple(44100, 192000, kResamplingRMSError, -62.63),
385 std::tr1::make_tuple(48000, 192000, kResamplingRMSError, -73.44), 424 std::tr1::make_tuple(48000, 192000, kResamplingRMSError, -73.44),
386 std::tr1::make_tuple(96000, 192000, kResamplingRMSError, -73.52), 425 std::tr1::make_tuple(96000, 192000, kResamplingRMSError, -73.52),
387 std::tr1::make_tuple(192000, 192000, kResamplingRMSError, -73.52))); 426 std::tr1::make_tuple(192000, 192000, kResamplingRMSError, -73.52)));
388 427
389 } // namespace media 428 } // namespace media
OLDNEW
« no previous file with comments | « media/base/sinc_resampler.cc ('k') | media/media.gyp » ('j') | media/media.gyp » ('J')

Powered by Google App Engine
This is Rietveld 408576698