Project
Loading...
Searching...
No Matches
benchmark_ASoA.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#include "Framework/ASoA.h"
15#include <benchmark/benchmark.h>
16#include <random>
17#include <vector>
18
19using namespace o2::framework;
20using namespace arrow;
21using namespace o2::soa;
22using namespace o2::aod;
23
24namespace o2::aod
25{
26namespace test
27{
28DECLARE_SOA_COLUMN_FULL(X, x, float, "x");
29DECLARE_SOA_COLUMN_FULL(Y, y, float, "y");
30DECLARE_SOA_COLUMN_FULL(Z, z, float, "z");
31DECLARE_SOA_DYNAMIC_COLUMN(Sum, sum, [](float x, float y) { return x + y; });
32DECLARE_SOA_DYNAMIC_COLUMN(SumFreeArgs, sumFreeArgs, [](float x, float y, float freeArg) { return x + y + freeArg; });
33} // namespace test
34
35DECLARE_SOA_TABLE(TestTable, "AOD", "TESTTBL", test::X, test::Y, test::Z, test::Sum<test::X, test::Y>);
36} // namespace o2::aod
37
38#ifdef __APPLE__
39constexpr unsigned int maxrange = 10;
40#else
41constexpr unsigned int maxrange = 15;
42#endif
43
44static void BM_SimpleForLoop(benchmark::State& state)
45{
46 struct XYZ {
47 float x;
48 float y;
49 float z;
50 };
51 std::vector<XYZ> foo;
52 foo.resize(state.range(0));
53
54 // Seed with a real random value, if available
55 std::default_random_engine e1(1234567891);
56 std::uniform_real_distribution<float> uniform_dist(0, 1);
57
58 for (auto i = 0; i < state.range(0); ++i) {
60 }
61
62 for (auto _ : state) {
63 float sum = 0;
64 for (auto& _ : foo) {
65 benchmark::DoNotOptimize(sum++);
66 }
67 }
68 state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
69}
70
71BENCHMARK(BM_SimpleForLoop)->Range(8, 8 << maxrange);
72
73static void BM_TrackForLoop(benchmark::State& state)
74{
75 struct TestTrack {
76 float a;
77 float b;
78 float c;
79 float d;
80 float e;
81 float f;
82 };
83 std::vector<TestTrack> foo;
84 foo.resize(state.range(0));
85
86 // Seed with a real random value, if available
87 std::default_random_engine e1(1234567891);
88 std::uniform_real_distribution<float> uniform_dist(0, 1);
89
90 for (auto i = 0; i < state.range(0); ++i) {
91 foo[i] = TestTrack{
94 }
95
96 for (auto _ : state) {
97 float sum = 0;
98 for (auto& xyz : foo) {
99 sum += xyz.a + xyz.d;
100 }
101 benchmark::DoNotOptimize(sum);
102 }
103 state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
104}
105
106BENCHMARK(BM_TrackForLoop)->Range(8, 8 << maxrange);
107
108static void BM_WholeTrackForLoop(benchmark::State& state)
109{
110 struct TestTrack {
111 float a;
112 float b;
113 float c;
114 float d;
115 float e;
116 float f;
117 };
118 std::vector<TestTrack> foo;
119 foo.resize(state.range(0));
120
121 // Seed with a real random value, if available
122 std::default_random_engine e1(1234567891);
123 std::uniform_real_distribution<float> uniform_dist(0, 1);
124
125 for (auto i = 0; i < state.range(0); ++i) {
126 foo[i] = TestTrack{
129 }
130
131 for (auto _ : state) {
132 float sum = 0;
133 for (auto& xyz : foo) {
134 sum += xyz.a + xyz.b + xyz.c + xyz.d + xyz.e + xyz.f;
135 }
136 benchmark::DoNotOptimize(sum);
137 }
138 state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 6);
139}
140
141BENCHMARK(BM_WholeTrackForLoop)->Range(8, 8 << maxrange);
142
143static void BM_TrackForPhi(benchmark::State& state)
144{
145 struct TestTrack {
146 float a;
147 float b;
148 float c;
149 float d;
150 float e;
151 float f;
152 };
153 std::vector<TestTrack> foo;
154 foo.resize(state.range(0));
155
156 // Seed with a real random value, if available
157 std::default_random_engine e1(1234567891);
158 std::uniform_real_distribution<float> uniform_dist(0, 1);
159
160 for (auto i = 0; i < state.range(0); ++i) {
161 foo[i] = TestTrack{
164 }
165
166 for (auto _ : state) {
167 size_t i = 0;
168 std::vector<float> result;
169 result.resize(state.range(0));
170 for (auto& track : foo) {
171 result[i++] = asin(track.a) + track.d + M_PI;
172 }
173 benchmark::DoNotOptimize(result);
174 }
175 state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
176}
177
178BENCHMARK(BM_TrackForPhi)->Range(8, 8 << maxrange);
179
180static void BM_SimpleForLoopWithOp(benchmark::State& state)
181{
182 struct XYZ {
183 float x;
184 float y;
185 float z;
186 };
187 std::vector<XYZ> foo;
188 foo.resize(state.range(0));
189
190 // Seed with a real random value, if available
191 std::default_random_engine e1(1234567891);
192 std::uniform_real_distribution<float> uniform_dist(0, 1);
193
194 for (auto i = 0; i < state.range(0); ++i) {
195 foo[i] = XYZ{uniform_dist(e1), uniform_dist(e1), uniform_dist(e1)};
196 }
197
198 for (auto _ : state) {
199 float sum = 0;
200 for (auto& xyz : foo) {
201 sum += xyz.x + xyz.y;
202 }
203 benchmark::DoNotOptimize(sum);
204 }
205 state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
206}
207
208BENCHMARK(BM_SimpleForLoopWithOp)->Range(8, 8 << maxrange);
209
210static void BM_ASoASimpleForLoop(benchmark::State& state)
211{
212 // Seed with a real random value, if available
213 std::default_random_engine e1(1234567891);
214 std::uniform_real_distribution<float> uniform_dist(0, 1);
215
216 TableBuilder builder;
217 auto rowWriter = builder.persist<float, float, float>({"x", "y", "z"});
218 for (auto i = 0; i < state.range(0); ++i) {
219 rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1));
220 }
221 auto table = builder.finalize();
222
223 using Test = o2::soa::InPlaceTable<"A/0"_h, test::X>;
224
225 for (auto _ : state) {
226 float sum = 0;
227 Test tests{table};
228 for (auto& _ : tests) {
229 sum++;
230 }
231 benchmark::DoNotOptimize(sum++);
232 }
233 state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
234}
235
236BENCHMARK(BM_ASoASimpleForLoop)->Range(8, 8 << maxrange);
237
238static void BM_ASoASimpleForLoopWithOp(benchmark::State& state)
239{
240 // Seed with a real random value, if available
241 std::default_random_engine e1(1234567891);
242 std::uniform_real_distribution<float> uniform_dist(0, 1);
243
244 TableBuilder builder;
245 auto rowWriter = builder.persist<float, float, float>({"x", "y", "z"});
246 for (auto i = 0; i < state.range(0); ++i) {
247 rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1));
248 }
249 auto table = builder.finalize();
250
251 using Test = o2::soa::InPlaceTable<"A/0"_h, test::X, test::Y>;
252
253 for (auto _ : state) {
254 Test tests{table};
255 float sum = 0;
256 for (auto& test : tests) {
257 sum += test.x() + test.y();
258 }
259 benchmark::DoNotOptimize(sum);
260 }
261 state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
262}
263
264BENCHMARK(BM_ASoASimpleForLoopWithOp)->Range(8, 8 << maxrange);
265
266static void BM_ASoADynamicColumnPresent(benchmark::State& state)
267{
268 // Seed with a real random value, if available
269 std::default_random_engine e1(1234567891);
270 std::uniform_real_distribution<float> uniform_dist(0, 1);
271
272 TableBuilder builder;
273 auto rowWriter = builder.persist<float, float, float>({"x", "y", "z"});
274 for (auto i = 0; i < state.range(0); ++i) {
275 rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1));
276 }
277 auto table = builder.finalize();
278
279 using Test = o2::soa::InPlaceTable<"A/0"_h, test::X, test::Y, test::Z, test::Sum<test::X, test::Y>>;
280
281 for (auto _ : state) {
282 Test tests{table};
283 float sum = 0;
284 for (auto& test : tests) {
285 sum += test.x() + test.y();
286 }
287 benchmark::DoNotOptimize(sum);
288 }
289 state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
290}
291
292BENCHMARK(BM_ASoADynamicColumnPresent)->Range(8, 8 << maxrange);
293
294static void BM_ASoADynamicColumnPresentGetGetterByLabel(benchmark::State& state)
295{
296 // Seed with a real random value, if available
297 std::default_random_engine e1(1234567891);
298 std::uniform_real_distribution<float> uniform_dist(0, 1);
299
300 TableBuilder builder;
301 auto rowWriter = builder.persist<float, float, float>({"x", "y", "z"});
302 for (auto i = 0; i < state.range(0); ++i) {
303 rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1));
304 }
305 auto table = builder.finalize();
306
307 using Test = o2::soa::InPlaceTable<"A/0"_h, test::X, test::Y, test::Z, test::Sum<test::X, test::Y>>;
308
309 for (auto _ : state) {
310 Test tests{table};
311 float sum = 0;
312 auto xGetter = o2::soa::row_helpers::getColumnGetterByLabel<float, Test>("x");
313 auto yGetter = o2::soa::row_helpers::getColumnGetterByLabel<float, Test>("y");
314 for (auto& test : tests) {
315 sum += xGetter(test) + yGetter(test);
316 }
317 benchmark::DoNotOptimize(sum);
318 }
319 state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
320}
321
322BENCHMARK(BM_ASoADynamicColumnPresentGetGetterByLabel)->Range(8, 8 << maxrange);
323
324static void BM_ASoADynamicColumnCall(benchmark::State& state)
325{
326 // Seed with a real random value, if available
327 std::default_random_engine e1(1234567891);
328 std::uniform_real_distribution<float> uniform_dist(0, 1);
329
330 TableBuilder builder;
331 auto rowWriter = builder.persist<float, float, float>({"x", "y", "z"});
332 for (auto i = 0; i < state.range(0); ++i) {
333 rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1));
334 }
335 auto table = builder.finalize();
336
337 using Test = o2::soa::InPlaceTable<"A/0"_h, test::X, test::Y, test::Sum<test::X, test::Y>>;
338
339 Test tests{table};
340 for (auto _ : state) {
341 float sum = 0;
342 for (auto& test : tests) {
343 sum += test.sum();
344 }
345 benchmark::DoNotOptimize(sum);
346 }
347 state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
348}
349BENCHMARK(BM_ASoADynamicColumnCall)->Range(8, 8 << maxrange);
350
351static void BM_ASoADynamicColumnCallGetGetterByLabel(benchmark::State& state)
352{
353 // Seed with a real random value, if available
354 std::default_random_engine e1(1234567891);
355 std::uniform_real_distribution<float> uniform_dist(0, 1);
356
357 TableBuilder builder;
358 auto rowWriter = builder.persist<float, float, float>({"x", "y", "z"});
359 for (auto i = 0; i < state.range(0); ++i) {
360 rowWriter(0, uniform_dist(e1), uniform_dist(e1), uniform_dist(e1));
361 }
362 auto table = builder.finalize();
363
364 // SumFreeArgs presence checks if dynamic columns get() is handled correctly during compilation
365 using Test = o2::soa::InPlaceTable<"A/0"_h, test::X, test::Y, test::Sum<test::X, test::Y>, test::SumFreeArgs<test::X, test::Y>>;
366
367 Test tests{table};
368 for (auto _ : state) {
369 float sum = 0;
370 auto sumGetter = o2::soa::row_helpers::getColumnGetterByLabel<float, Test>("Sum");
371 for (auto& test : tests) {
372 sum += sumGetter(test);
373 }
374 benchmark::DoNotOptimize(sum);
375 }
376 state.SetBytesProcessed(state.iterations() * state.range(0) * sizeof(float) * 2);
377}
378BENCHMARK(BM_ASoADynamicColumnCallGetGetterByLabel)->Range(8, 8 << maxrange);
379
#define DECLARE_SOA_DYNAMIC_COLUMN(_Name_, _Getter_,...)
Definition ASoA.h:2967
#define DECLARE_SOA_TABLE(_Name_, _Origin_, _Desc_,...)
Definition ASoA.h:3052
#define DECLARE_SOA_COLUMN_FULL(_Name_, _Getter_, _Type_, _Label_)
Definition ASoA.h:2285
benchmark::State & state
uniform_int_distribution< long long > uniform_dist(32, 126)
int32_t i
Test
Definition Utils.h:55
uint32_t c
Definition RawData.h:2
BENCHMARK(BM_SimpleForLoop) -> Range(8, 8<< maxrange)
BENCHMARK_MAIN()
constexpr unsigned int maxrange
auto persist(std::array< char const *, sizeof...(ARGS)+1 > const &columnNames)
std::shared_ptr< arrow::Table > finalize()
float sum(float s, o2::dcs::DataPointValue v)
Definition dcs-ccdb.cxx:39
GLint GLenum GLint x
Definition glcorearb.h:403
GLuint64EXT * result
Definition glcorearb.h:5662
GLdouble f
Definition glcorearb.h:310
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint y
Definition glcorearb.h:270
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
Defining PrimaryVertex explicitly as messageable.
Definition TFIDInfo.h:20
FIXME: do not use data model tables.
HistogramRegistry foo()