PX4 Firmware
PX4 Autopilot Software http://px4.io
test_microbench_math.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (C) 2018-2019 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file test_microbench_math.cpp
36  * Tests for the microbench math library.
37  */
38 
39 #include <unit_test.h>
40 
41 #include <time.h>
42 #include <stdlib.h>
43 #include <unistd.h>
44 #include <math.h>
45 
46 #include <drivers/drv_hrt.h>
47 #include <perf/perf_counter.h>
48 #include <px4_platform_common/px4_config.h>
49 #include <px4_platform_common/micro_hal.h>
50 
51 namespace MicroBenchMath
52 {
53 
54 #ifdef __PX4_NUTTX
55 #include <nuttx/irq.h>
56 static irqstate_t flags;
57 #endif
58 
59 void lock()
60 {
61 #ifdef __PX4_NUTTX
62  flags = px4_enter_critical_section();
63 #endif
64 }
65 
66 void unlock()
67 {
68 #ifdef __PX4_NUTTX
69  px4_leave_critical_section(flags);
70 #endif
71 }
72 
73 #define PERF(name, op, count) do { \
74  px4_usleep(1000); \
75  reset(); \
76  perf_counter_t p = perf_alloc(PC_ELAPSED, name); \
77  for (int i = 0; i < count; i++) { \
78  lock(); \
79  perf_begin(p); \
80  op; \
81  perf_end(p); \
82  unlock(); \
83  reset(); \
84  } \
85  perf_print_counter(p); \
86  perf_free(p); \
87  } while (0)
88 
89 class MicroBenchMath : public UnitTest
90 {
91 public:
92  virtual bool run_tests();
93 
94 private:
95  bool time_single_precision_float();
96  bool time_single_precision_float_trig();
97 
98  bool time_double_precision_float();
99  bool time_double_precision_float_trig();
100 
101  bool time_8bit_integers();
102  bool time_16bit_integers();
103  bool time_32bit_integers();
104  bool time_64bit_integers();
105 
106  void reset();
107 
108  float f32;
109  float f32_out;
110 
111  double f64;
112  double f64_out;
113 
114  uint8_t i_8;
115  uint8_t i_8_out;
116 
117  uint16_t i_16;
118  uint16_t i_16_out;
119 
120  uint32_t i_32;
121  uint32_t i_32_out;
122 
123  int64_t i_64;
124  int64_t i_64_out;
125 
126  uint64_t u_64;
127  uint64_t u_64_out;
128 };
129 
130 bool MicroBenchMath::run_tests()
131 {
132  ut_run_test(time_single_precision_float);
133  ut_run_test(time_single_precision_float_trig);
134  ut_run_test(time_double_precision_float);
135  ut_run_test(time_double_precision_float_trig);
136  ut_run_test(time_8bit_integers);
137  ut_run_test(time_16bit_integers);
138  ut_run_test(time_32bit_integers);
139  ut_run_test(time_64bit_integers);
140 
141  return (_tests_failed == 0);
142 }
143 
144 template<typename T>
145 T random(T min, T max)
146 {
147  const T scale = rand() / (T) RAND_MAX; /* [0, 1.0] */
148  return min + scale * (max - min); /* [min, max] */
149 }
150 
152 {
153  srand(time(nullptr));
154 
155  // initialize with random data
156  f32 = random(-2.0f * M_PI, 2.0f * M_PI); // somewhat representative range for angles in radians
157  f32_out = random(-2.0f * M_PI, 2.0f * M_PI);
158 
159  f64 = random(-2.0 * M_PI, 2.0 * M_PI);
160  f64_out = random(-2.0 * M_PI, 2.0 * M_PI);
161 
162  i_8 = rand();
163  i_8_out = rand();
164 
165  i_16 = rand();
166  i_16_out = rand();
167 
168  i_32 = rand();
169  i_32_out = rand();
170 
171  i_64 = rand();
172  i_64_out = rand();
173 
174  u_64 = rand();
175  u_64_out = rand();
176 }
177 
179 
180 bool MicroBenchMath::time_single_precision_float()
181 {
182  PERF("float add", f32_out += f32, 1000);
183  PERF("float sub", f32_out -= f32, 1000);
184  PERF("float mul", f32_out *= f32, 1000);
185  PERF("float div", f32_out /= f32, 1000);
186  PERF("float sqrt", f32_out = sqrtf(f32), 1000);
187 
188  return true;
189 }
190 
191 bool MicroBenchMath::time_single_precision_float_trig()
192 {
193  PERF("sinf()", f32_out = sinf(f32), 1000);
194  PERF("cosf()", f32_out = cosf(f32), 1000);
195  PERF("tanf()", f32_out = tanf(f32), 1000);
196 
197  PERF("acosf()", f32_out = acosf(f32), 1000);
198  PERF("asinf()", f32_out = asinf(f32), 1000);
199  PERF("atan2f()", f32_out = atan2f(f32, 2.0f * f32), 1000);
200 
201  return true;
202 }
203 
204 bool MicroBenchMath::time_double_precision_float()
205 {
206  PERF("double add", f64_out += f64, 1000);
207  PERF("double sub", f64_out -= f64, 1000);
208  PERF("double mul", f64_out *= f64, 1000);
209  PERF("double div", f64_out /= f64, 1000);
210  PERF("double sqrt", f64_out = sqrt(f64), 1000);
211 
212  return true;
213 }
214 
215 bool MicroBenchMath::time_double_precision_float_trig()
216 {
217  PERF("sin()", f64_out = sin(f64), 1000);
218  PERF("cos()", f64_out = cos(f64), 1000);
219  PERF("tan()", f64_out = tan(f64), 1000);
220 
221  PERF("acos()", f64_out = acos(f64 * 0.5), 1000);
222  PERF("asin()", f64_out = asin(f64 * 0.6), 1000);
223  PERF("atan2()", f64_out = atan2(f64 * 0.7, f64 * 0.8), 1000);
224 
225  PERF("sqrt()", f64_out = sqrt(f64), 1000);
226 
227  return true;
228 }
229 
230 
231 bool MicroBenchMath::time_8bit_integers()
232 {
233  PERF("int8 add", i_8_out += i_8, 1000);
234  PERF("int8 sub", i_8_out -= i_8, 1000);
235  PERF("int8 mul", i_8_out *= i_8, 1000);
236  PERF("int8 div", i_8_out /= i_8, 1000);
237 
238  return true;
239 }
240 
241 bool MicroBenchMath::time_16bit_integers()
242 {
243  PERF("int16 add", i_16_out += i_16, 1000);
244  PERF("int16 sub", i_16_out -= i_16, 1000);
245  PERF("int16 mul", i_16_out *= i_16, 1000);
246  PERF("int16 div", i_16_out /= i_16, 1000);
247 
248  return true;
249 }
250 
251 bool MicroBenchMath::time_32bit_integers()
252 {
253  PERF("int32 add", i_32_out += i_32, 1000);
254  PERF("int32 sub", i_32_out -= i_32, 1000);
255  PERF("int32 mul", i_32_out *= i_32, 1000);
256  PERF("int32 div", i_32_out /= i_32, 1000);
257 
258  return true;
259 }
260 
261 bool MicroBenchMath::time_64bit_integers()
262 {
263  PERF("int64 add", i_64_out += i_64, 1000);
264  PERF("int64 sub", i_64_out -= i_64, 1000);
265  PERF("int64 mul", i_64_out *= i_64, 1000);
266  PERF("int64 div", i_64_out /= i_64, 1000);
267 
268  return true;
269 }
270 
271 } // namespace MicroBenchMath
Dual< Scalar, N > acos(const Dual< Scalar, N > &a)
Definition: Dual.hpp:309
T random(T min, T max)
int test_microbench_math(int argc, char *argv[])
int reset(enum LPS22HB_BUS busid)
Reset the driver.
Dual< Scalar, N > asin(const Dual< Scalar, N > &a)
Definition: Dual.hpp:301
Base class to be used for unit tests.
Definition: unit_test.h:54
High-resolution timer with callouts and timekeeping.
ut_declare_test_c(test_microbench_math, MicroBenchMath) bool MicroBenchMath
Dual< Scalar, N > cos(const Dual< Scalar, N > &a)
Definition: Dual.hpp:286
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
#define PERF(name, op, count)
Dual< Scalar, N > tan(const Dual< Scalar, N > &a)
Definition: Dual.hpp:293
constexpr _Tp min(_Tp a, _Tp b)
Definition: Limits.hpp:54
constexpr _Tp max(_Tp a, _Tp b)
Definition: Limits.hpp:60
#define M_PI
Definition: gps_helper.cpp:38
#define ut_run_test(test)
Runs a single unit test.
Definition: unit_test.h:96
Dual< Scalar, N > sin(const Dual< Scalar, N > &a)
Definition: Dual.hpp:279
Dual< Scalar, N > sqrt(const Dual< Scalar, N > &a)
Definition: Dual.hpp:188
Dual< Scalar, N > atan2(const Dual< Scalar, N > &a, const Dual< Scalar, N > &b)
Definition: Dual.hpp:325
Performance measuring tools.