Logo ROOT  
Reference Guide
df022_useKahan.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_dataframe
3/// \notebook
4/// This tutorial shows how to implement a Kahan summation custom action.
5///
6/// \macro_code
7/// \macro_output
8///
9/// \date July 2018
10/// \author Enrico Guiraud, Danilo Piparo, Massimo Tumolo
11
12template <typename T>
13class KahanSum final : public ROOT::Detail::RDF::RActionImpl<class KahanSum<T>> {
14public:
15 /// This type is a requirement for every helper.
16 using Result_t = T;
17
18private:
19 std::vector<T> fPartialSums;
20 std::vector<T> fCompensations;
21 int fNSlots;
22
23 std::shared_ptr<T> fResultSum;
24
25 void KahanAlgorithm(const T &x, T &sum, T &compensation){
26 T y = x - compensation;
27 T t = sum + y;
28 compensation = (t - sum) - y;
29 sum = t;
30 }
31
32public:
33 KahanSum(KahanSum &&) = default;
34 KahanSum(const KahanSum &) = delete;
35
36 KahanSum(const std::shared_ptr<T> &r) : fResultSum(r)
37 {
38 static_assert(std::is_floating_point<T>::value, "Kahan sum makes sense only on floating point numbers");
39
41 fPartialSums.resize(fNSlots, 0.);
42 fCompensations.resize(fNSlots, 0.);
43 }
44
45 std::shared_ptr<Result_t> GetResultPtr() const { return fResultSum; }
46
47 void Initialize() {}
48 void InitTask(TTreeReader *, unsigned int) {}
49
50 void Exec(unsigned int slot, T x)
51 {
52 KahanAlgorithm(x, fPartialSums[slot], fCompensations[slot]);
53 }
54
55 template <typename V=T, typename std::enable_if<ROOT::TypeTraits::IsContainer<V>::value, int>::type = 0>
56 void Exec(unsigned int slot, const T &vs)
57 {
58 for (auto &&v : vs) {
59 Exec(slot, v);
60 }
61 }
62
63 void Finalize()
64 {
65 T sum(0) ;
66 T compensation(0);
67 for (int i = 0; i < fNSlots; ++i) {
68 KahanAlgorithm(fPartialSums[i], sum, compensation);
69 }
70 *fResultSum = sum;
71 }
72
73 std::string GetActionName(){
74 return "THnHelper";
75 }
76
77};
78
79void df022_useKahan()
80{
81 // We enable implicit parallelism
83
85 auto dd = d.Define("x", "(rdfentry_ %2 == 0) ? 0.00000001 : 100000000.");
86
87 auto ptr = std::make_shared<double>();
88 KahanSum<double> helper(ptr);
89
90 auto kahanResult = dd.Book<double>(std::move(helper), {"x"});
91 auto plainResult = dd.Sum<double>({"x"});
92
93 std::cout << std::setprecision(24) << "Kahan: " << *kahanResult << " Classical: " << *plainResult << std::endl;
94 // Outputs: Kahan: 1000000000.00000011920929 Classical: 1000000000
95}
ROOT::R::TRInterface & r
Definition: Object.C:4
#define d(i)
Definition: RSha256.hxx:102
int type
Definition: TGX11.cxx:120
ROOT's RDataFrame offers a high level interface for analyses of data stored in TTrees,...
Definition: RDataFrame.hxx:42
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition: TTreeReader.h:43
Double_t y[n]
Definition: legend1.C:17
Double_t x[n]
Definition: legend1.C:17
double T(double x)
Definition: ChebyshevPol.h:34
void EnableImplicitMT(UInt_t numthreads=0)
Enable ROOT's implicit multi-threading for all objects and methods that provide an internal paralleli...
Definition: TROOT.cxx:580
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition: TROOT.cxx:611
UInt_t GetImplicitMTPoolSize()
Returns the size of the pool used for implicit multi-threading.
Definition: TROOT.cxx:618
void Initialize(Bool_t useTMVAStyle=kTRUE)
Definition: tmvaglob.cxx:176
static long int sum(long int i)
Definition: Factory.cxx:2276