Project
Loading...
Searching...
No Matches
benchmark_Types.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#include <TObjArray.h>
12#include <TH1.h>
13#include <TH2.h>
14#include <TH3.h>
15#include <TTree.h>
16#include <THnSparse.h>
17#include <TF1.h>
18#include <TF2.h>
19#include <TF3.h>
20#include <TRandom.h>
21#include <TRandomGen.h>
22
23#include <chrono>
24#include <ctime>
25#include <TMessage.h>
26
28
29#include <type_traits>
30
31#include <iostream>
32#include <fstream>
33
34#include <boost/archive/binary_iarchive.hpp>
35#include <boost/archive/binary_oarchive.hpp>
36#include <boost/histogram.hpp>
37#include <boost/histogram/serialization.hpp>
38#include <sstream>
39
40namespace bh = boost::histogram;
41
49
50struct Results {
51 size_t sizeBytes = 0;
54 double mergingSeconds = 0;
56};
57
58struct Parameters {
59 constexpr static Parameters forHistograms(size_t objectSize, size_t entries)
60 {
61 return {objectSize, 0, 0, entries};
62 }
63 constexpr static Parameters forSparse(size_t bins, size_t dimensions, size_t entries)
64 {
65 return {0, bins, dimensions, entries};
66 }
67 constexpr static Parameters forTrees(size_t branches, size_t branchSize, size_t entries)
68 {
69 return {0, 0, 0, entries, branches, branchSize};
70 }
71 size_t objectSize = 0;
72 size_t bins = 0;
73 size_t dimensions = 0;
74 size_t entries = 0;
75 size_t branches = 0;
76 size_t branchSize = 0;
77};
78
79auto measure = [](Measurement m, auto* o, auto* i) -> double {
80 switch (m) {
81 case Measurement::Size: {
82 const double scale = 1.0; //000000000.0;
83 if constexpr (std::is_base_of<TObject, typename std::remove_pointer<decltype(o)>::type>::value) {
84 if (o->InheritsFrom(TH1::Class())) {
85 // this includes TH1, TH2, TH3
86 // i don't see an easy way to find out the size of a cell, i assume that they are Int
87 return reinterpret_cast<TH1*>(o)->GetNcells() * sizeof(Int_t) / scale;
88 } else if (o->InheritsFrom(THnSparse::Class())) {
89 auto* sparse = reinterpret_cast<THnSparse*>(o);
90 // this is has to be multiplied with bin (entry) size, but we cannot get it from th einterface.
91 return sparse->GetNChunks() * sparse->GetChunkSize() / scale;
92 } else if (o->InheritsFrom(THnBase::Class())) {
93 // this includes THn and THnSparse
94 return reinterpret_cast<THnBase*>(o)->GetNbins() * sizeof(Int_t) / scale;
95 } else if (o->InheritsFrom(TTree::Class())) {
96 size_t totalSize = 0;
97 auto tree = reinterpret_cast<TTree*>(o);
98 auto branchList = tree->GetListOfBranches();
99 for (const auto* branch : *branchList) {
100 totalSize += dynamic_cast<const TBranch*>(branch)->GetTotalSize();
101 }
102 return totalSize / scale;
103 } else {
104 throw std::runtime_error("Object with type '" + std::string(o->ClassName()) + "' is not one of the mergeable types.");
105 }
106 } else {
107 // boost
108 return o->size() * sizeof(int);
109 }
110 }
112 auto end = std::chrono::high_resolution_clock::now();
113 auto start = std::chrono::high_resolution_clock::now();
114 if constexpr (std::is_base_of<TObject, typename std::remove_pointer<decltype(o)>::type>::value) {
115 if (o->InheritsFrom(TH1::Class())) {
116 // this includes TH1, TH2, TH3
117 start = std::chrono::high_resolution_clock::now();
118 reinterpret_cast<TH1*>(o)->Merge(i, "-NOCHECK");
119 } else if (o->InheritsFrom(THnBase::Class())) {
120 // this includes THn and THnSparse
121 start = std::chrono::high_resolution_clock::now();
122 reinterpret_cast<THnBase*>(o)->Merge(i);
123 } else if (o->InheritsFrom(TTree::Class())) {
124 start = std::chrono::high_resolution_clock::now();
125 reinterpret_cast<TTree*>(o)->Merge(i);
126 } else {
127 throw std::runtime_error("Object with type '" + std::string(o->ClassName()) + "' is not one of the mergeable types.");
128 }
129 end = std::chrono::high_resolution_clock::now();
130 } else {
131 // boost
132 *o += *i;
133 end = std::chrono::high_resolution_clock::now();
134 (void)*o;
135 }
136 auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
137 return elapsed_seconds.count();
138 }
140 auto end = std::chrono::high_resolution_clock::now();
141 auto start = std::chrono::high_resolution_clock::now();
142 if constexpr (std::is_base_of<TObject, typename std::remove_pointer<decltype(o)>::type>::value) {
143 TMessage* tm = new TMessage(kMESS_OBJECT);
144 tm->WriteObject(o);
145 end = std::chrono::high_resolution_clock::now();
146 (void)*tm;
147 delete tm;
148 } else {
149 // boost
150 std::ostringstream os;
151 std::string buf;
152 boost::archive::binary_oarchive oa(os);
153 oa << *o;
154 end = std::chrono::high_resolution_clock::now();
155 (void)os; // hopefully this will prevent from optimising this code out.
156 }
157 auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
158 return elapsed_seconds.count();
159 }
161 auto start = std::chrono::high_resolution_clock::now();
162 auto end = std::chrono::high_resolution_clock::now();
163 if constexpr (std::is_base_of<TObject, typename std::remove_pointer<decltype(o)>::type>::value) {
164 TMessage* tm = new TMessage(kMESS_OBJECT);
165 tm->WriteObject(o);
166 start = std::chrono::high_resolution_clock::now();
167
168 // Needed to take into account that FairInputTBuffer expects the first 8 bytes to be the
169 // allocator pointer, which is not present in the TMessage buffer.
170 o2::framework::FairInputTBuffer ftm(const_cast<char*>(tm->Buffer() - 8), tm->BufferSize() + 8);
171 ftm.InitMap();
172 auto* storedClass = ftm.ReadClass();
173 if (storedClass == nullptr) {
174 throw std::runtime_error("Unknown stored class");
175 }
176 ftm.SetBufferOffset(0);
177 ftm.ResetMap();
178 auto* tObjectClass = TClass::GetClass(typeid(TObject));
179
180 if (!storedClass->InheritsFrom(tObjectClass)) {
181 throw std::runtime_error("Class '" + std::string(storedClass->GetName()) + "'does not inherit from TObject");
182 }
183
184 auto* object = ftm.ReadObjectAny(storedClass);
185 if (object == nullptr) {
186 throw std::runtime_error("Failed to read object with name '" + std::string(storedClass->GetName()) + "' from message using ROOT serialization.");
187 }
188
189 auto tobject = static_cast<TObject*>(object);
190 end = std::chrono::high_resolution_clock::now();
191 (void)*tobject;
192 delete tm;
193 delete tobject;
194 } else {
195 std::ostringstream os;
196 std::string buf;
197 boost::archive::binary_oarchive oa(os);
198 oa << *o;
199 buf = os.str();
200
201 start = std::chrono::high_resolution_clock::now();
202 auto deserialisedHistogram = typename std::remove_pointer<decltype(o)>::type();
203 std::istringstream is(buf);
204 boost::archive::binary_iarchive ia(is);
205 ia >> deserialisedHistogram;
206 end = std::chrono::high_resolution_clock::now();
207 assert(deserialisedHistogram == *o);
208 }
209 auto elapsed_seconds = std::chrono::duration_cast<std::chrono::duration<double>>(end - start);
210 return elapsed_seconds.count();
211 }
213 const double scale = 1.0; //1000000000.0;
214 if constexpr (std::is_base_of<TObject, typename std::remove_pointer<decltype(o)>::type>::value) {
215 TMessage* tm = new TMessage(kMESS_OBJECT);
216 tm->WriteObject(o);
217 auto serialisedSize = tm->BufferSize();
218 delete tm;
219 return serialisedSize / scale;
220 } else {
221 std::ostringstream os;
222 std::string buf;
223 boost::archive::binary_oarchive oa(os);
224 oa << *i;
225 buf = os.str();
226 return buf.size() / scale;
227 }
228 }
229 }
230 throw;
231};
232
233static std::vector<Results> BM_TH1I(size_t repetitions, const Parameters p)
234{
235 const size_t objSize = p.objectSize;
236 const size_t entries = p.entries;
237 const size_t bins = objSize / sizeof(Int_t);
238
239 auto m = std::make_unique<TH1I>("merged", "merged", bins, 0, 1000000);
240 // avoid memory overcommitment by doing something with data.
241 for (size_t i = 0; i < bins; i++) {
242 m->SetBinContent(i, 1);
243 }
244
245 std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>();
246 collection->SetOwner(true);
247 auto uni = std::make_unique<TF1>("uni", "1", 0, 1000000);
248 TH1I* h = new TH1I("test", "test", bins, 0, 1000000);
249 collection->Add(h);
250
251 std::vector<Results> allResults;
252 for (size_t r = 0; r < repetitions; r++) {
253 h->Reset();
254 h->FillRandom("uni", entries);
255 Results iterationResults;
256 iterationResults.sizeBytes = measure(Measurement::Size, m.get(), collection.get());
257 iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, m.get(), collection.get());
258 iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, m.get(), collection.get());
259 iterationResults.serialisationSeconds = measure(Measurement::Serialisation, m.get(), collection.get());
260 iterationResults.mergingSeconds = measure(Measurement::Merging, m.get(), collection.get());
261 allResults.push_back(iterationResults);
262 }
263 return allResults;
264}
265
266static std::vector<Results> BM_TH2I(size_t repetitions, const Parameters p)
267{
268 const size_t objSize = p.objectSize;
269 const size_t entries = p.entries;
270 const size_t bins = std::sqrt(objSize / sizeof(Int_t));
271
272 auto m = std::make_unique<TH2I>("merged", "merged", bins, 0, 1000000, bins, 0, 1000000);
273 // avoid memory overcommitment by doing something with data.
274 for (size_t i = 0; i < bins * bins; i++) {
275 m->SetBinContent(i, 1);
276 }
277
278 std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>();
279 collection->SetOwner(true);
280 auto uni = std::make_unique<TF2>("uni", "1", 0, 1000000, 0, 1000000);
281 auto* h = new TH2I("test", "test", bins, 0, 1000000, bins, 0, 1000000);
282 collection->Add(h);
283
284 std::vector<Results> allResults;
285 for (size_t r = 0; r < repetitions; r++) {
286 h->Reset();
287 h->FillRandom("uni", entries);
288 Results iterationResults;
289 iterationResults.sizeBytes = measure(Measurement::Size, m.get(), collection.get());
290 iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, m.get(), collection.get());
291 iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, m.get(), collection.get());
292 iterationResults.serialisationSeconds = measure(Measurement::Serialisation, m.get(), collection.get());
293 iterationResults.mergingSeconds = measure(Measurement::Merging, m.get(), collection.get());
294 allResults.push_back(iterationResults);
295 }
296 return allResults;
297}
298
299static std::vector<Results> BM_TH3I(size_t repetitions, const Parameters p)
300{
301 const size_t objSize = p.objectSize;
302 const size_t entries = p.entries;
303 const size_t bins = std::pow(objSize / sizeof(Int_t), 1 / 3.0);
304
305 auto m = std::make_unique<TH3I>("merged", "merged", bins, 0, 1000000, bins, 0, 1000000, bins, 0, 1000000);
306 // avoid memory overcommitment by doing something with data.
307 for (size_t i = 0; i < bins * bins * bins; i++) {
308 m->SetBinContent(i, 1);
309 }
310
311 std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>();
312 collection->SetOwner(true);
313 auto uni = std::make_unique<TF3>("uni", "1", 0, 1000000, 0, 1000000, 0, 1000000);
314 auto* h = new TH3I("test", "test", bins, 0, 1000000, bins, 0, 1000000, bins, 0, 1000000);
315 collection->Add(h);
316
317 std::vector<Results> allResults;
318 for (size_t r = 0; r < repetitions; r++) {
319 h->Reset();
320 h->FillRandom("uni", entries);
321 Results iterationResults;
322 iterationResults.sizeBytes = measure(Measurement::Size, m.get(), collection.get());
323 iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, m.get(), collection.get());
324 iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, m.get(), collection.get());
325 iterationResults.serialisationSeconds = measure(Measurement::Serialisation, m.get(), collection.get());
326 iterationResults.mergingSeconds = measure(Measurement::Merging, m.get(), collection.get());
327 allResults.push_back(iterationResults);
328 }
329 return allResults;
330}
331
332template <typename storageT>
333static std::vector<Results> BM_BoostRegular1D(size_t repetitions, const Parameters p)
334{
335 const size_t entries = p.entries;
336 const size_t bins = p.objectSize / sizeof(int32_t);
337 const double min = 0.0;
338 const double max = 1000000.0;
339
340 auto merged = bh::make_histogram_with(storageT(), bh::axis::regular<>(bins, min, max, "x"));
341 merged += merged; // avoid memory overcommitment by doing something with data.
342 using HistoType = decltype(merged);
343
344 TRandomMixMax gen;
345 gen.SetSeed(std::random_device()());
346 Double_t randomArray[entries];
347
348 std::vector<Results> allResults;
349 for (size_t r = 0; r < repetitions; r++) {
350 auto h = bh::make_histogram_with(storageT(), bh::axis::regular<>(bins, min, max, "x"));
351 gen.RndmArray(entries, randomArray);
352 for (double rnd : randomArray) {
353 h(rnd * max);
354 }
355 Results iterationResults;
356 iterationResults.sizeBytes = measure(Measurement::Size, &merged, &h);
358 iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, &merged, &h);
359 iterationResults.serialisationSeconds = measure(Measurement::Serialisation, &merged, &h);
360 iterationResults.mergingSeconds = measure(Measurement::Merging, &merged, &h);
361 allResults.push_back(iterationResults);
362 }
363 return allResults;
364}
365
366template <typename storageT>
367static std::vector<Results> BM_BoostRegular2D(size_t repetitions, const Parameters p)
368{
369 const size_t entries = p.entries;
370 const size_t bins = std::sqrt(p.objectSize / sizeof(int32_t));
371 const double min = 0.0;
372 const double max = 1000000.0;
373
374 auto merged = bh::make_histogram_with(storageT(), bh::axis::regular<>(bins, min, max, "x"), bh::axis::regular<>(bins, min, max, "y"));
375 merged += merged; // avoid memory overcommitment by doing something with data.
376
377 TRandomMixMax gen;
378 gen.SetSeed(std::random_device()());
379 Double_t randomArrayX[entries];
380 Double_t randomArrayY[entries];
381
382 std::vector<Results> allResults;
383 for (size_t r = 0; r < repetitions; r++) {
384 auto h = bh::make_histogram_with(storageT(), bh::axis::regular<>(bins, min, max, "x"), bh::axis::regular<>(bins, min, max, "y"));
385 gen.RndmArray(entries, randomArrayX);
386 gen.RndmArray(entries, randomArrayY);
387 for (size_t rnd = 0; rnd < entries; rnd++) {
388 h(randomArrayX[rnd] * max, randomArrayY[rnd] * max);
389 }
390
391 Results iterationResults;
392 iterationResults.sizeBytes = measure(Measurement::Size, &merged, &h);
394 iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, &merged, &h);
395 iterationResults.serialisationSeconds = measure(Measurement::Serialisation, &merged, &h);
396 iterationResults.mergingSeconds = measure(Measurement::Merging, &merged, &h);
397 allResults.push_back(iterationResults);
398 }
399 return allResults;
400}
401
402static std::vector<Results> BM_THNSparseI(size_t repetitions, const Parameters p)
403{
404 const size_t bins = p.bins;
405 const size_t dim = p.dimensions;
406 const size_t entries = p.entries;
407
408 const Double_t min = 0.0;
409 const Double_t max = 1000000.0;
410 const std::vector<Int_t> binsDims(dim, bins);
411 const std::vector<Double_t> mins(dim, min);
412 const std::vector<Double_t> maxs(dim, max);
413
414 TRandomMixMax gen;
415 gen.SetSeed(std::random_device()());
416 Double_t randomArray[dim];
417
418 std::vector<Results> allResults;
419 for (size_t rep = 0; rep < repetitions; rep++) {
420 // histograms have to be created in each loop repetition, otherwise i get strange segfaults with large number of entries.
421 std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>();
422 collection->SetOwner(true);
423 auto* h = new THnSparseI("test", "test", dim, binsDims.data(), mins.data(), maxs.data());
424 collection->Add(h);
425
426 auto m = std::make_unique<THnSparseI>("merged", "merged", dim, binsDims.data(), mins.data(), maxs.data());
427
428 for (size_t entry = 0; entry < entries; entry++) {
429 gen.RndmArray(dim, randomArray);
430 for (double& r : randomArray) {
431 r *= max;
432 }
433 h->Fill(randomArray);
434 }
435
436 for (size_t entry = 0; entry < entries; entry++) {
437 gen.RndmArray(dim, randomArray);
438 for (double& r : randomArray) {
439 r *= max;
440 }
441 m->Fill(randomArray);
442 }
443
444 Results iterationResults;
445 iterationResults.sizeBytes = measure(Measurement::Size, m.get(), collection.get());
446 iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, m.get(), collection.get());
447 iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, m.get(), collection.get());
448 iterationResults.serialisationSeconds = measure(Measurement::Serialisation, m.get(), collection.get());
449 iterationResults.mergingSeconds = measure(Measurement::Merging, m.get(), collection.get());
450 allResults.push_back(iterationResults);
451 }
452 return allResults;
453}
454
455static std::vector<Results> BM_TTree(size_t repetitions, const Parameters p)
456{
457 const size_t branchSize = p.branchSize;
458 const size_t branches = p.branches;
459 const size_t entries = p.entries;
460
461 using branch_t = std::vector<uint64_t>;
462 std::vector<branch_t> branchCollection;
463 for (size_t i = 0; i < branches; i++) {
464 branchCollection.emplace_back(branchSize, 0);
465 }
466 auto createTree = [&](std::string name) -> TTree* {
467 TTree* tree = new TTree();
468 for (size_t i = 0; i < branchCollection.size(); i++) {
469 tree->Branch(("b" + std::to_string(i)).c_str(),
470 &branchCollection[i],
471 ("array" + std::to_string(i) + "[" + std::to_string(branchSize) + "]:l").c_str());
472 }
473 tree->SetName(name.c_str());
474 return tree;
475 };
476
477 auto fillTree = [&](TTree* t) {
478 TRandomMixMax gen;
479 gen.SetSeed(std::random_device()());
480 Float_t randomArray[branchSize];
481
482 for (size_t entry = 0; entry < entries; entry++) {
483 for (auto& branch : branchCollection) {
484 gen.RndmArray(branchSize, randomArray);
485 for (size_t i = 0; i < branchSize; i++) {
486 branch[i] = static_cast<uint64_t>(randomArray[i]);
487 }
488 }
489 t->Fill();
490 }
491 };
492
493 std::vector<Results> allResults;
494 for (size_t r = 0; r < repetitions; r++) {
495 std::unique_ptr<TCollection> collection = std::make_unique<TObjArray>();
496 collection->SetOwner(true);
497 TTree* t = createTree("input");
498 fillTree(t);
499 collection->Add(t);
500
501 TTree* m = createTree("merged");
502 fillTree(m);
503
504 Results iterationResults;
505 iterationResults.sizeBytes = measure(Measurement::Size, m, collection.get());
506 iterationResults.sizeSerialisedBytes = measure(Measurement::SizeAfterSerialisation, m, collection.get());
507 iterationResults.deserialisationSeconds = measure(Measurement::Deserialisation, m, collection.get());
508 iterationResults.serialisationSeconds = measure(Measurement::Serialisation, m, collection.get());
509 iterationResults.mergingSeconds = measure(Measurement::Merging, m, collection.get());
510 allResults.push_back(iterationResults);
511
512 delete m;
513 }
514 return allResults;
515}
516
517void printHeaderCSV(std::ostream& out)
518{
519 out << "name,"
520 "objectSize,bins,dimensions,entries,branches,branchSize,"
521 "sizeBytes,sizeSerialisedBytes,deserialisationSeconds,mergingSeconds,serialisationSeconds"
522 "\n";
523}
524
525void printResultsCSV(std::ostream& out, std::string name, const Parameters& p, const std::vector<Results>& results)
526{
527 for (const auto r : results) {
528 out << name << ","
529 << p.objectSize << "," << p.bins << "," << p.dimensions << "," << p.entries << "," << p.branches << "," << p.branchSize << ","
530 << r.sizeBytes << "," << r.sizeSerialisedBytes << "," << r.deserialisationSeconds << "," << r.mergingSeconds << "," << r.serialisationSeconds
531 << '\n';
532 }
533}
534
535int main(int argc, const char* argv[])
536{
537 if (argc < 2) {
538 throw std::runtime_error("Output file name expected");
539 }
540
541 std::ofstream file;
542 file.open(argv[1]);
544 printHeaderCSV(std::cout);
545
546 size_t repetitions = argc < 3 ? 1 : std::atoll(argv[2]);
547
548 {
549 // TH1I
550 std::vector<Parameters> parameters{
551 Parameters::forHistograms(8 << 0, 50000),
552 Parameters::forHistograms(8 << 3, 50000),
553 Parameters::forHistograms(8 << 6, 50000),
554 Parameters::forHistograms(8 << 9, 50000),
555 Parameters::forHistograms(8 << 12, 50000),
556 Parameters::forHistograms(8 << 15, 50000),
557 Parameters::forHistograms(8 << 18, 50000),
558 Parameters::forHistograms(8 << 21, 50000)};
559 for (const auto& p : parameters) {
560 auto results = BM_TH1I(repetitions, p);
561 printResultsCSV(file, "TH1I", p, results);
562 printResultsCSV(std::cout, "TH1I", p, results);
563 }
564 }
565
566 {
567 // TH2I
568 std::vector<Parameters> parameters{
569 Parameters::forHistograms(8 << 0, 50000),
570 Parameters::forHistograms(8 << 3, 50000),
571 Parameters::forHistograms(8 << 6, 50000),
572 Parameters::forHistograms(8 << 9, 50000),
573 Parameters::forHistograms(8 << 12, 50000),
574 Parameters::forHistograms(8 << 15, 50000),
575 Parameters::forHistograms(8 << 18, 50000),
576 Parameters::forHistograms(8 << 21, 50000)};
577 for (const auto& p : parameters) {
578 auto results = BM_TH2I(repetitions, p);
579 printResultsCSV(file, "TH2I", p, results);
580 printResultsCSV(std::cout, "TH2I", p, results);
581 }
582 }
583
584 {
585 // TH3I
586 std::vector<Parameters> parameters{
587 Parameters::forHistograms(8 << 0, 50000),
588 Parameters::forHistograms(8 << 3, 50000),
589 Parameters::forHistograms(8 << 6, 50000),
590 Parameters::forHistograms(8 << 9, 50000),
591 Parameters::forHistograms(8 << 12, 50000),
592 Parameters::forHistograms(8 << 15, 50000),
593 Parameters::forHistograms(8 << 18, 50000),
594 Parameters::forHistograms(8 << 21, 50000)};
595 for (const auto& p : parameters) {
596 auto results = BM_TH3I(repetitions, p);
597 printResultsCSV(file, "TH3I", p, results);
598 printResultsCSV(std::cout, "TH3I", p, results);
599 }
600 }
601
602 {
603 // THnSparseI
604 std::vector<Parameters> parameters{
605 Parameters::forSparse(8, 8, 512),
606 Parameters::forSparse(64, 8, 512),
607 Parameters::forSparse(512, 8, 512),
608 Parameters::forSparse(4096, 8, 512),
609 Parameters::forSparse(32768, 8, 512),
610 Parameters::forSparse(512, 2, 512),
611 Parameters::forSparse(512, 4, 512),
612 Parameters::forSparse(512, 8, 512),
613 Parameters::forSparse(512, 16, 512),
614 Parameters::forSparse(512, 32, 512),
615 Parameters::forSparse(512, 64, 512),
616 Parameters::forSparse(512, 8, 1),
617 Parameters::forSparse(512, 8, 8),
618 Parameters::forSparse(512, 8, 64),
619 Parameters::forSparse(512, 8, 512),
620 Parameters::forSparse(512, 8, 4096),
621 Parameters::forSparse(512, 8, 32768),
622 Parameters::forSparse(512, 8, 262144),
623 Parameters::forSparse(512, 8, 2097152),
624 // Parameters::forSparse(512, 8, 16777216),
625 Parameters::forSparse(32, 4, 1),
626 Parameters::forSparse(32, 4, 8),
627 Parameters::forSparse(32, 4, 64),
628 Parameters::forSparse(32, 4, 512),
629 Parameters::forSparse(32, 4, 4096),
630 Parameters::forSparse(32, 4, 32768),
631 Parameters::forSparse(32, 4, 262144),
632 Parameters::forSparse(32, 4, 2097152),
633 Parameters::forSparse(32, 4, 16777216)};
634 for (const auto& p : parameters) {
635 auto results = BM_THNSparseI(repetitions, p);
636 printResultsCSV(file, "THnSparseI", p, results);
637 printResultsCSV(std::cout, "THnSparseI", p, results);
638 }
639 }
640
641 {
642 // TTree
643 std::vector<Parameters> parameters{
644 Parameters::forTrees(8, 8, 8),
645 Parameters::forTrees(8, 8, 8 << 3),
646 Parameters::forTrees(8, 8, 8 << 6),
647 Parameters::forTrees(8, 8, 8 << 9),
648 Parameters::forTrees(8, 8, 8 << 12),
649 Parameters::forTrees(8, 8, 8 << 15),
650 Parameters::forTrees(8, 8, 8 << 18),
651 Parameters::forTrees(8, 1 << 0, 8 << 12),
652 Parameters::forTrees(8, 1 << 2, 8 << 12),
653 Parameters::forTrees(8, 1 << 4, 8 << 12),
654 Parameters::forTrees(8, 1 << 6, 8 << 12),
655 Parameters::forTrees(8, 1 << 8, 8 << 12),
656 Parameters::forTrees(1 << 0, 8, 8 << 12),
657 Parameters::forTrees(1 << 2, 8, 8 << 12),
658 Parameters::forTrees(1 << 4, 8, 8 << 12),
659 Parameters::forTrees(1 << 6, 8, 8 << 12),
660 Parameters::forTrees(1 << 8, 8, 8 << 12)};
661 for (const auto& p : parameters) {
662 auto results = BM_TTree(repetitions, p);
663 printResultsCSV(file, "TTree", p, results);
664 printResultsCSV(std::cout, "TTree", p, results);
665 }
666 }
667
668 {
669 // boost regular 1D. We use a combination of template and macro to be able to use static storage (std::array) with different parameters.
670#define BM_BOOST1DARRAY_FOR(objSize, entries) \
671 { \
672 constexpr auto p = Parameters::forHistograms(objSize, entries); \
673 auto results = BM_BoostRegular1D<std::array<int32_t, p.objectSize / sizeof(int32_t) + 2>>(repetitions, p); \
674 printResultsCSV(file, "BoostRegular1DArray", p, results); \
675 printResultsCSV(std::cout, "BoostRegular1DArray", p, results); \
676 }
677
678 BM_BOOST1DARRAY_FOR(8 << 0, 50000);
679 BM_BOOST1DARRAY_FOR(8 << 3, 50000);
680 BM_BOOST1DARRAY_FOR(8 << 6, 50000);
681 BM_BOOST1DARRAY_FOR(8 << 9, 50000);
682 BM_BOOST1DARRAY_FOR(8 << 12, 50000);
683 BM_BOOST1DARRAY_FOR(8 << 15, 50000);
684 }
685
686 {
687 // boost regular 1D.
688#define BM_BOOST1DVECTOR_FOR(objSize, entries) \
689 { \
690 constexpr auto p = Parameters::forHistograms(objSize, entries); \
691 auto results = BM_BoostRegular1D<std::vector<int32_t>>(repetitions, p); \
692 printResultsCSV(file, "BoostRegular1DVector", p, results); \
693 printResultsCSV(std::cout, "BoostRegular1DVector", p, results); \
694 }
695
696 BM_BOOST1DVECTOR_FOR(8 << 0, 50000);
697 BM_BOOST1DVECTOR_FOR(8 << 3, 50000);
698 BM_BOOST1DVECTOR_FOR(8 << 6, 50000);
699 BM_BOOST1DVECTOR_FOR(8 << 9, 50000);
700 BM_BOOST1DVECTOR_FOR(8 << 12, 50000);
701 BM_BOOST1DVECTOR_FOR(8 << 15, 50000);
702 BM_BOOST1DVECTOR_FOR(8 << 18, 50000);
703 BM_BOOST1DVECTOR_FOR(8 << 21, 50000);
704 }
705
706 {
707 // boost regular 2D. We use a combination of template and macro to be able to use static storage (std::array) with different parameters.
708#define BM_BOOST2DARRAY_FOR(objSize, arrSize, entries) \
709 { \
710 constexpr auto p = Parameters::forHistograms(objSize, entries); \
711 auto results = BM_BoostRegular2D<std::array<int32_t, arrSize>>(repetitions, p); \
712 printResultsCSV(file, "BoostRegular2DArray", p, results); \
713 printResultsCSV(std::cout, "BoostRegular2DArray", p, results); \
714 }
715
716 BM_BOOST2DARRAY_FOR(8 << 0, 10, 50000);
717 BM_BOOST2DARRAY_FOR(8 << 3, 36, 50000);
718 BM_BOOST2DARRAY_FOR(8 << 6, 178, 50000);
719 BM_BOOST2DARRAY_FOR(8 << 9, 1156, 50000);
720 BM_BOOST2DARRAY_FOR(8 << 12, 8558, 50000);
721 BM_BOOST2DARRAY_FOR(8 << 15, 66564, 50000);
722 }
723
724 {
725 // boost regular 2D.
726#define BM_BOOST2DVECTOR_FOR(objSize, entries) \
727 { \
728 constexpr auto p = Parameters::forHistograms(objSize, entries); \
729 auto results = BM_BoostRegular2D<std::vector<int32_t>>(repetitions, p); \
730 printResultsCSV(file, "BoostRegular2DVector", p, results); \
731 printResultsCSV(std::cout, "BoostRegular2DVector", p, results); \
732 }
733
734 BM_BOOST2DVECTOR_FOR(8 << 0, 50000);
735 BM_BOOST2DVECTOR_FOR(8 << 3, 50000);
736 BM_BOOST2DVECTOR_FOR(8 << 6, 50000);
737 BM_BOOST2DVECTOR_FOR(8 << 9, 50000);
738 BM_BOOST2DVECTOR_FOR(8 << 12, 50000);
739 BM_BOOST2DVECTOR_FOR(8 << 15, 50000);
740 BM_BOOST2DVECTOR_FOR(8 << 18, 50000);
741 BM_BOOST2DVECTOR_FOR(8 << 21, 50000);
742 }
743
744 file.close();
745 return 0;
746}
default_random_engine gen(dev())
const auto bins
Definition PID.cxx:49
int32_t i
bool o
#define BM_BOOST1DARRAY_FOR(objSize, entries)
void printResultsCSV(std::ostream &out, std::string name, const Parameters &p, const std::vector< Results > &results)
auto measure
#define BM_BOOST2DARRAY_FOR(objSize, arrSize, entries)
void printHeaderCSV(std::ostream &out)
Measurement
@ SizeAfterSerialisation
#define BM_BOOST1DVECTOR_FOR(objSize, entries)
#define BM_BOOST2DVECTOR_FOR(objSize, entries)
Class for time synchronization of RawReader instances.
const GLfloat * m
Definition glcorearb.h:4066
GLuint entry
Definition glcorearb.h:5735
GLuint GLuint end
Definition glcorearb.h:469
GLuint const GLchar * name
Definition glcorearb.h:781
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLuint object
Definition glcorearb.h:4041
GLboolean r
Definition glcorearb.h:1233
GLuint start
Definition glcorearb.h:469
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition glcorearb.h:2514
std::string to_string(gsl::span< T, Size > span)
Definition common.h:52
static constexpr Parameters forHistograms(size_t objectSize, size_t entries)
static constexpr Parameters forSparse(size_t bins, size_t dimensions, size_t entries)
static constexpr Parameters forTrees(size_t branches, size_t branchSize, size_t entries)
size_t sizeSerialisedBytes
double serialisationSeconds
double deserialisationSeconds
double mergingSeconds
size_t sizeBytes
constexpr size_t min
constexpr size_t max
#define main
std::unique_ptr< TTree > tree((TTree *) flIn.Get(std::string(o2::base::NameConf::CTFTREENAME).c_str()))