Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
histspeedtest.cxx
Go to the documentation of this file.
1/// \file histspeedtest.cxx
2///
3/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
4/// is welcome!
5/// \author Axel Naumann <axel@cern.ch>
6
7#include "TRandom3.h"
8#include <vector>
9#include <chrono>
10#include <iostream>
11
12#include "TH1.h"
13#include "TH2.h"
14#include "TH3.h"
15
16#include "ROOT/RHist.hxx"
18
19using namespace ROOT;
20using namespace std;
21
22constexpr unsigned short gRepeat = 2;
23
24/* DataTypes:
25
26 THistDataContent
27 THistDataUncertainty
28 THistDataMomentUncert
29 THistDataRuntime
30and
31 MyTHistDataNoStat
32 MyTHistDataContent
33 MyTHistDataMomentUncert
34
35 /opt/build/root_builds/rootcling.cmake/include/ROOT/THistBinIter.h:53:50: error: no member named 'GetUncertainty' in
36'ROOT::Experimental::THistDataContent<2, double, ROOT::Experimental::THistDataDefaultStorage>::TBinStat<double>' auto
37GetUncertainty() const { return GetStat().GetUncertainty(); }
38
39 new ones (STATCLASSES)
40
41 THistStatContent
42 THistStatUncertainty
43 THistStatTotalSumOfWeights
44 THistStatTotalSumOfSquaredWeights
45 THistDataMomentUncert
46
47
48 */
49
50#ifndef STATCLASSES
51#define STATCLASSES Experimental::RHistStatContent, Experimental::RHistStatUncertainty
52#endif
53
54struct Timer {
55 using TimePoint_t = decltype(std::chrono::high_resolution_clock::now());
56
57 const char *fTitle;
58 size_t fCount;
60
61 Timer(const char *title, size_t count)
62 : fTitle(title), fCount(count), fStart(std::chrono::high_resolution_clock::now())
63 {}
64
66 {
67 using namespace std::chrono;
68 auto end = high_resolution_clock::now();
69 duration<double> time_span = duration_cast<duration<double>>(end - fStart);
70 // std::cout << fCount << " * " << fTitle << ": " << time_span.count() << " seconds \n";
71 // std::cout << fCount << " * " << fTitle << ": " << fCount / (1e6) / time_span.count()
72 // << " millions per seconds\n";
73 std::cout << fCount << " * " << fTitle << ": " << time_span.count() << " seconds, \t";
74 std::cout << fCount / (1e6) / time_span.count() << " millions per seconds \n";
75 }
76};
77
78constexpr UInt_t gStride = 32; // TH1::GetDefaultBufferSize()
79
80struct BinEdges {
81 static constexpr size_t fNBinsX = 4;
82 static constexpr size_t fNBinsY = 5;
83 double fXBins[4];
84 double fYBins[5];
85
86 BinEdges(double minValue, double maxValue)
87 {
88 if (maxValue < minValue)
89 swap(minValue, maxValue);
90 double range = maxValue - minValue;
91
92 double x[fNBinsX] = {0., 0.1, 0.3, 1.};
93 double y[fNBinsY] = {0., 0.1, 0.2, 0.3, 1.};
94
95 for (size_t i = 0; i < fNBinsX; ++i)
96 fXBins[i] = minValue + range * x[i];
97 for (size_t i = 0; i < fNBinsY; ++i)
98 fYBins[i] = minValue + range * y[i];
99 }
100
102
103 AConf_t GetConfigX() const { return AConf_t(std::span<const double>(fXBins).to_vector()); }
104 AConf_t GetConfigY() const { return AConf_t(std::span<const double>(fYBins).to_vector()); }
105};
106
107template <typename T>
108void GenerateInput(std::vector<T> &numbers, double minVal, double maxVal, UInt_t seed)
109{
110 Timer t("GenerateInput", numbers.size());
111 if (minVal > maxVal) {
112 std::swap(minVal, maxVal);
113 }
114 T range = maxVal - minVal;
115 TRandom3 r(seed);
116 size_t len = numbers.size();
117 for (auto c = numbers.begin(); c != numbers.end(); ++c) {
118 *c = minVal + range * r.Rndm();
119 }
120}
121
122std::string
123MakeTitle(std::string_view version, std::string_view histname, std::string_view title, std::string_view axis)
124{
125 std::string result =
126 std::string(version) + " " + std::string(histname) + " " + std::string(title) + " [" + std::string(axis) + "]";
127 return result;
128}
129
130template <int dim, typename type>
131const char *GetHist();
132
133template <>
135{
136 return "2D";
137};
138template <>
139const char *GetHist<2, float>()
140{
141 return "2F";
142};
143
144template <>
146{
147 return "1D";
148};
149template <>
150const char *GetHist<1, float>()
151{
152 return "1F";
153};
154
155namespace R7 {
156const char *gVersion = "R7";
157
158template <typename T, unsigned short kNDim>
159struct Dim;
160
161template <typename T>
162struct Dim<T, 2> {
163
164 constexpr static unsigned short kNDim = 2;
166
167 using FillFunc_t = std::add_pointer_t<long(ExpTH2 &hist, std::vector<double> &input, std::string_view type)>;
168
169 struct EE {
170 static constexpr const char *const gType = "regular bin size ";
171
172 template <FillFunc_t filler>
173 static long Execute(std::vector<double> &input, double minVal, double maxVal)
174 {
175
176 ExpTH2 hist({100, minVal, maxVal}, {5, minVal, maxVal});
177 return filler(hist, input, gType);
178 }
179 };
180
181 struct II {
182 static constexpr const char *const gType = "irregular bin size";
183
184 template <FillFunc_t filler>
185 static long Execute(std::vector<double> &input, double minVal, double maxVal)
186 {
187
188 BinEdges edges(minVal, maxVal);
189 ExpTH2 hist(edges.GetConfigX(), edges.GetConfigY());
190 return filler(hist, input, gType);
191 }
192 };
193
194 inline static long fillN(ExpTH2 &hist, std::vector<double> &input, std::string_view gType)
195 {
196
198 array_t *values = (array_t *)(&input[0]);
199 constexpr size_t stride = gStride;
200
201 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills N (stride 32)", gType);
202 {
203 Timer t(title.c_str(), input.size() / 2);
204 for (size_t i = 0; i < (input.size() - (stride * 2 - 1)); i += (stride * 2), values += 32) {
205 std::span<array_t> coords(values, 32);
206 hist.FillN(coords);
207 }
208 }
209 return hist.GetNDim();
210 }
211
212 inline static long fillBuffered(ExpTH2 &hist, std::vector<double> &input, std::string_view gType)
213 {
215 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills (buffered) ", gType);
216 {
217 Timer t(title.c_str(), input.size() / 2);
218 for (size_t i = 0; i < input.size() - 1; i += 2)
219 filler.Fill({input[i], input[i + 1]});
220 }
221 return hist.GetNDim();
222 }
223
224 inline static long fill(ExpTH2 &hist, std::vector<double> &input, std::string_view gType)
225 {
226 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills ", gType);
227 {
228 Timer t(title.c_str(), input.size() / 2);
229 for (size_t i = 0; i < input.size() - 1; i += 2)
230 hist.Fill({input[i], input[i + 1]});
231 }
232 return hist.GetNDim();
233 }
234}; // DimD
235
236template <typename T>
237struct Dim<T, 1> {
238
239 constexpr static unsigned short kNDim = 1;
241
242 using FillFunc_t = std::add_pointer_t<long(ExpTH1 &hist, std::vector<double> &input, std::string_view type)>;
243
244 struct EE {
245 static constexpr const char *const gType = "regular bin size ";
246
247 template <FillFunc_t filler>
248 static long Execute(std::vector<double> &input, double minVal, double maxVal)
249 {
250 long result = 0;
251 for (unsigned short i = 0; i < gRepeat; ++i) {
252 ExpTH1 hist({100, minVal, maxVal});
253 result += filler(hist, input, gType);
254 }
255 return result;
256 }
257 };
258
259 struct II {
260 static constexpr const char *const gType = "irregular bin size";
261
262 template <FillFunc_t filler>
263 static long Execute(std::vector<double> &input, double minVal, double maxVal)
264 {
265
266 long result = 0;
267 BinEdges edges(minVal, maxVal);
268 for (unsigned short i = 0; i < gRepeat; ++i) {
269 ExpTH1 hist(edges.GetConfigX());
270 result += filler(hist, input, gType);
271 }
272 return result;
273 }
274 };
275
276 inline static long fillN(ExpTH1 &hist, std::vector<double> &input, std::string_view gType)
277 {
278
280 array_t *values = (array_t *)(&input[0]);
281 constexpr size_t stride = gStride;
282
283 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills N (stride 32)", gType);
284 {
285 Timer t(title.c_str(), input.size());
286 for (size_t i = 0; i < (input.size() - (stride - 1)); i += (stride), values += 32) {
287 std::span<array_t> coords(values, 32);
288 hist.FillN(coords);
289 }
290 }
291 return hist.GetNDim();
292 }
293
294 inline static long fillBuffered(ExpTH1 &hist, std::vector<double> &input, std::string_view gType)
295 {
297 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills (buffered) ", gType);
298 {
299 Timer t(title.c_str(), input.size());
300 for (size_t i = 0; i < input.size(); ++i)
301 filler.Fill({input[i]});
302 }
303 return hist.GetNDim();
304 }
305
306 inline static long fill(ExpTH1 &hist, std::vector<double> &input, std::string_view gType)
307 {
308 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills ", gType);
309 {
310 Timer t(title.c_str(), input.size());
311 for (size_t i = 0; i < input.size(); ++i)
312 hist.Fill({input[i]});
313 }
314 return hist.GetNDim();
315 }
316}; // Dim1
317
318} // namespace R7
319
320namespace R6 {
321const char *gVersion = "R6";
322
323template <int ndim, typename T>
324struct Redirect;
325template <>
326struct Redirect<2, float> {
328};
329template <>
330struct Redirect<2, double> {
332};
333template <>
334struct Redirect<1, float> {
336};
337template <>
338struct Redirect<1, double> {
340};
341
342template <typename T, int kNDim>
343struct Dim;
344
345template <typename T>
346struct Dim<T, 2> {
347
348 constexpr static unsigned short kNDim = 2;
350
351 using FillFunc_t = std::add_pointer_t<long(HistType_t &hist, std::vector<double> &input, std::string_view type)>;
352
353 struct EE {
354
355 static constexpr const char *const gType = "regular bin size ";
356
357 template <FillFunc_t filler>
358 static long Execute(std::vector<double> &input, double minVal, double maxVal)
359 {
360
361 long result = 0;
362 for (unsigned short i = 0; i < gRepeat; ++i) {
363 HistType_t hist("a", "a hist", 100, minVal, maxVal, 5, minVal, maxVal);
364 result += filler(hist, input, gType);
365 }
366 return result;
367 }
368 };
369
370 struct II {
371
372 static constexpr const char *const gType = "irregular bin size";
373
374 template <FillFunc_t filler>
375 static long Execute(std::vector<double> &input, double minVal, double maxVal)
376 {
377 long result = 0;
378 BinEdges edges(minVal, maxVal);
379 for (unsigned short i = 0; i < gRepeat; ++i) {
380 HistType_t hist("a", "a hist", edges.fNBinsX - 1, edges.fXBins, edges.fNBinsY - 1, edges.fYBins);
381 result += filler(hist, input, gType);
382 }
383 return result;
384 }
385 };
386
387 static long fillBuffered(HistType_t &hist, std::vector<double> &input, std::string_view gType)
388 {
389 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills (buffered) ", gType);
390 hist.SetBuffer(TH1::GetDefaultBufferSize());
391 {
392 // Timer t("R6 2D fills [regular bins size]",input.size()/2);
393 Timer t(title.c_str(), input.size() / 2);
394 for (size_t i = 0; i < input.size() - 1; i += 2)
395 hist.Fill(input[i], input[i + 1]);
396 }
397 return (long)hist.GetEntries();
398 }
399
400 static long fillN(HistType_t &hist, std::vector<double> &input, std::string_view gType)
401 {
402 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills N (stride 32)", gType);
403 constexpr size_t stride = gStride;
404 {
405 // Timer t("R6 2D fills [regular bins size]",input.size()/2);
406 Timer t(title.c_str(), input.size() / 2);
407 for (size_t i = 0; i < (input.size() - (stride * 2 - 1)); i += (stride * 2))
408 hist.FillN(gStride, &(input[i]), &(input[i + gStride]), nullptr);
409 }
410 return (long)hist.GetEntries();
411 }
412
413 static long fill(HistType_t &hist, std::vector<double> &input, std::string_view gType)
414 {
415 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills ", gType);
416 {
417 // Timer t("R6 2D fills [regular bins size]",input.size()/2);
418 Timer t(title.c_str(), input.size() / 2);
419 for (size_t i = 0; i < input.size() - 1; i += 2)
420 hist.Fill(input[i], input[i + 1]);
421 }
422 return (long)hist.GetEntries();
423 }
424}; // Dim
425
426template <typename T>
427struct Dim<T, 1> {
428
429 constexpr static unsigned short kNDim = 1;
431
432 using FillFunc_t = std::add_pointer_t<long(HistType_t &hist, std::vector<double> &input, std::string_view type)>;
433
434 struct EE {
435
436 static constexpr const char *const gType = "regular bin size ";
437
438 template <FillFunc_t filler>
439 static long Execute(std::vector<double> &input, double minVal, double maxVal)
440 {
441
442 long result = 0;
443 for (unsigned short i = 0; i < gRepeat; ++i) {
444 HistType_t hist("a", "a hist", 100, minVal, maxVal);
445 result += filler(hist, input, gType);
446 }
447 return result;
448 }
449 };
450
451 struct II {
452
453 static constexpr const char *const gType = "irregular bin size";
454
455 template <FillFunc_t filler>
456 static long Execute(std::vector<double> &input, double minVal, double maxVal)
457 {
458 long result = 0;
459 BinEdges edges(minVal, maxVal);
460 for (unsigned short i = 0; i < gRepeat; ++i) {
461 HistType_t hist("a", "a hist", edges.fNBinsX - 1, edges.fXBins);
462 result += filler(hist, input, gType);
463 }
464 return result;
465 }
466 };
467
468 static long fillBuffered(HistType_t &hist, std::vector<double> &input, std::string_view gType)
469 {
470 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills (buffered) ", gType);
471 hist.SetBuffer(TH1::GetDefaultBufferSize());
472 {
473 // Timer t("R6 2D fills [regular bins size]",input.size()/2);
474 Timer t(title.c_str(), input.size());
475 for (size_t i = 0; i < input.size() - 1; ++i)
476 hist.Fill(input[i]);
477 }
478 return (long)hist.GetEntries();
479 }
480
481 static long fillN(HistType_t &hist, std::vector<double> &input, std::string_view gType)
482 {
483 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills N (stride 32)", gType);
484 constexpr size_t stride = gStride;
485 {
486 // Timer t("R6 2D fills [regular bins size]",input.size()/2);
487 Timer t(title.c_str(), input.size());
488 for (size_t i = 0; i < (input.size() - (stride - 1)); i += (stride))
489 hist.FillN(gStride, &(input[i]), nullptr);
490 }
491 return (long)hist.GetEntries();
492 }
493
494 static long fill(HistType_t &hist, std::vector<double> &input, std::string_view gType)
495 {
496 std::string title = MakeTitle(gVersion, GetHist<kNDim, T>(), "fills ", gType);
497 {
498 // Timer t("R6 2D fills [regular bins size]",input.size()/2);
499 Timer t(title.c_str(), input.size());
500 for (size_t i = 0; i < input.size(); ++i)
501 hist.Fill(input[i]);
502 }
503 return (long)hist.GetEntries();
504 }
505}; // Dim1
506} // namespace R6
507
508template <typename T, unsigned short kNDim>
509void speedtest(size_t count = (size_t)(1e6));
510
511template <>
512void speedtest<double, 2>(size_t count)
513{
514 using DataType_t = double;
515 static constexpr unsigned short kNDim = 2;
516
518
519 std::vector<double> input; // (count);
520 input.resize(count);
521
522 double minVal = -5.0;
523 double maxVal = +5.0;
524 GenerateInput(input, minVal, maxVal, 0);
525
526 // Make sure we have some overflow.
527 minVal *= 0.9;
528 maxVal *= 0.9;
529
530 cout << '\n';
531
538
539 cout << '\n';
540
547
548 cout << '\n';
549
556
557 cout << '\n';
558
565
566 cout << '\n';
567}
568
569// these are copy/paste to work around failure to properly instantiate the template :(
570
571template <>
572void speedtest<float, 2>(size_t count)
573{
574 using DataType_t = float;
575 constexpr unsigned short kNDim = 2;
576
578
579 std::vector<double> input; // (count);
580 input.resize(count);
581
582 double minVal = -5.0;
583 double maxVal = +5.0;
584 GenerateInput(input, minVal, maxVal, 0);
585
586 // Make sure we have some overflow.
587 minVal *= 0.9;
588 maxVal *= 0.9;
589
590 cout << '\n';
591
598
599 cout << '\n';
600
607
608 cout << '\n';
609
616
617 cout << '\n';
618
625}
626
627template <>
628void speedtest<double, 1>(size_t count)
629{
630 using DataType_t = double;
631 static constexpr unsigned short kNDim = 1;
632
634
635 std::vector<double> input; // (count);
636 input.resize(count);
637
638 double minVal = -5.0;
639 double maxVal = +5.0;
640 GenerateInput(input, minVal, maxVal, 0);
641
642 // Make sure we have some overflow.
643 minVal *= 0.9;
644 maxVal *= 0.9;
645
646 cout << '\n';
647
654
655 cout << '\n';
656
663
664 cout << '\n';
665
672
673 cout << '\n';
674
681}
682
683template <>
684void speedtest<float, 1>(size_t count)
685{
686 using DataType_t = float;
687 static constexpr unsigned short kNDim = 1;
688
690
691 std::vector<double> input; // (count);
692 input.resize(count);
693
694 double minVal = -5.0;
695 double maxVal = +5.0;
696 GenerateInput(input, minVal, maxVal, 0);
697
698 // Make sure we have some overflow.
699 minVal *= 0.9;
700 maxVal *= 0.9;
701
702 cout << '\n';
703
710
711 cout << '\n';
712
719
720 cout << '\n';
721
728
729 cout << '\n';
730
737}
738
739void histspeedtest(size_t iter = 1e6, int what = 255)
740{
741 if (what & 1)
743 if (what & 2)
745 if (what & 4)
747 if (what & 8)
749}
750
751int main(int argc, char **argv)
752{
753
754 size_t iter = 1e7;
755 int what = 1 | 2 | 4 | 8;
756 if (argc > 1)
757 iter = atof(argv[1]);
758 if (argc > 2)
759 what = atoi(argv[2]);
760
761 histspeedtest(iter, what);
762}
double
long
ROOT::R::TRInterface & r
Definition Object.C:4
int main()
Definition Prototype.cxx:12
#define c(i)
Definition RSha256.hxx:101
const Bool_t kFALSE
Definition RtypesCore.h:101
int type
Definition TGX11.cxx:121
void Fill(const CoordArray_t &x, Weight_t weight=1.)
Objects used to configure the different axis types.
Histogram class for histograms with DIMENSIONS dimensions, where each bin count is stored by a value ...
Definition RHist.hxx:53
1-D histogram with a double per channel (see TH1 documentation)}
Definition TH1.h:618
1-D histogram with a float per channel (see TH1 documentation)}
Definition TH1.h:575
static Int_t GetDefaultBufferSize()
Static function return the default buffer size for automatic histograms the parameter fgBufferSize ma...
Definition TH1.cxx:4370
static void AddDirectory(Bool_t add=kTRUE)
Sets the flag controlling the automatic add of histograms in memory.
Definition TH1.cxx:1283
2-D histogram with a double per channel (see TH1 documentation)}
Definition TH2.h:292
2-D histogram with a float per channel (see TH1 documentation)}
Definition TH2.h:251
Random number generator class based on M.
Definition TRandom3.h:27
const char * GetHist< 1, double >()
constexpr UInt_t gStride
void speedtest(size_t count=(size_t)(1e6))
const char * GetHist< 2, double >()
void speedtest< double, 1 >(size_t count)
constexpr unsigned short gRepeat
void speedtest< float, 1 >(size_t count)
const char * GetHist< 2, float >()
const char * GetHist< 1, float >()
void histspeedtest(size_t iter=1e6, int what=255)
void GenerateInput(std::vector< T > &numbers, double minVal, double maxVal, UInt_t seed)
const char * GetHist()
std::string MakeTitle(std::string_view version, std::string_view histname, std::string_view title, std::string_view axis)
void speedtest< double, 2 >(size_t count)
void speedtest< float, 2 >(size_t count)
Double_t y[n]
Definition legend1.C:17
Double_t x[n]
Definition legend1.C:17
const char * gVersion
const char * gVersion
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
static int gType
static const char * what
Definition stlLoader.cc:6
double fXBins[4]
static constexpr size_t fNBinsY
double fYBins[5]
Experimental::RAxisConfig AConf_t
BinEdges(double minValue, double maxValue)
static constexpr size_t fNBinsX
AConf_t GetConfigY() const
AConf_t GetConfigX() const
static long Execute(std::vector< double > &input, double minVal, double maxVal)
static long Execute(std::vector< double > &input, double minVal, double maxVal)
static long fill(HistType_t &hist, std::vector< double > &input, std::string_view gType)
typename Redirect< kNDim, T >::HistType_t HistType_t
static long fillN(HistType_t &hist, std::vector< double > &input, std::string_view gType)
std::add_pointer_t< long(HistType_t &hist, std::vector< double > &input, std::string_view type)> FillFunc_t
static long fillBuffered(HistType_t &hist, std::vector< double > &input, std::string_view gType)
static long Execute(std::vector< double > &input, double minVal, double maxVal)
static long Execute(std::vector< double > &input, double minVal, double maxVal)
std::add_pointer_t< long(HistType_t &hist, std::vector< double > &input, std::string_view type)> FillFunc_t
static long fillBuffered(HistType_t &hist, std::vector< double > &input, std::string_view gType)
typename Redirect< kNDim, T >::HistType_t HistType_t
static long fillN(HistType_t &hist, std::vector< double > &input, std::string_view gType)
static long fill(HistType_t &hist, std::vector< double > &input, std::string_view gType)
static long Execute(std::vector< double > &input, double minVal, double maxVal)
static long Execute(std::vector< double > &input, double minVal, double maxVal)
static long fillN(ExpTH1 &hist, std::vector< double > &input, std::string_view gType)
Experimental::RHist< kNDim, T, STATCLASSES > ExpTH1
static long fillBuffered(ExpTH1 &hist, std::vector< double > &input, std::string_view gType)
static long fill(ExpTH1 &hist, std::vector< double > &input, std::string_view gType)
std::add_pointer_t< long(ExpTH1 &hist, std::vector< double > &input, std::string_view type)> FillFunc_t
static long Execute(std::vector< double > &input, double minVal, double maxVal)
static long Execute(std::vector< double > &input, double minVal, double maxVal)
std::add_pointer_t< long(ExpTH2 &hist, std::vector< double > &input, std::string_view type)> FillFunc_t
static long fillBuffered(ExpTH2 &hist, std::vector< double > &input, std::string_view gType)
Experimental::RHist< kNDim, T, STATCLASSES > ExpTH2
static long fillN(ExpTH2 &hist, std::vector< double > &input, std::string_view gType)
static long fill(ExpTH2 &hist, std::vector< double > &input, std::string_view gType)
Timer(const char *title, size_t count)
size_t fCount
decltype(std::chrono::high_resolution_clock::now()) TimePoint_t
TimePoint_t fStart
const char * fTitle