Logo ROOT  
Reference Guide
RAction.hxx
Go to the documentation of this file.
1// Author: Enrico Guiraud, Danilo Piparo CERN 09/2018
2
3/*************************************************************************
4 * Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. *
5 * All rights reserved. *
6 * *
7 * For the licensing terms see $ROOTSYS/LICENSE. *
8 * For the list of contributors see $ROOTSYS/README/CREDITS. *
9 *************************************************************************/
10
11#ifndef ROOT_RACTION
12#define ROOT_RACTION
13
16#include "ROOT/RDF/NodesUtils.hxx" // InitRDFValues
17#include "ROOT/RDF/Utils.hxx" // ColumnNames_t
20
21#include <cstddef> // std::size_t
22#include <memory>
23#include <string>
24#include <vector>
25
26namespace ROOT {
27namespace Internal {
28namespace RDF {
29
32
33// fwd declarations for RActionCRTP
34namespace GraphDrawing {
35std::shared_ptr<GraphNode> CreateDefineNode(const std::string &colName, const RDFDetail::RCustomColumnBase *columnPtr);
36bool CheckIfDefaultOrDSColumn(const std::string &name, const std::shared_ptr<RDFDetail::RCustomColumnBase> &column);
37} // ns GraphDrawing
38
39/// Unused, not instantiatable. Only the partial specialization RActionCRTP<RAction<...>> can be used.
40template <typename Dummy>
42 static_assert(sizeof(Dummy) < 0, "The unspecialized version of RActionCRTP should never be instantiated");
43};
44
45/// A type-erasing wrapper around RColumnValue.
46/// Used to reduce compile time by avoiding instantiation of very large tuples and/or (std::get<N>...) fold expressions.
48 std::shared_ptr<void> fPtr; // shared_ptr correctly deletes the type-erased object
49
50public:
51 template <typename T>
52 RTypeErasedColumnValue(std::unique_ptr<RColumnValue<T>> v) : fPtr(std::move(v))
53 {
54 }
55
56 template <typename T>
58 {
59 return std::static_pointer_cast<RColumnValue<T>>(fPtr)->Get(e);
60 }
61
62 template <typename T>
64 {
65 return static_cast<RColumnValue<T> *>(fPtr.get());
66 }
67};
68
69/// This overload is specialized to act on RTypeErasedColumnValues instead of RColumnValues.
70template <std::size_t... S, typename... ColTypes>
71void InitRDFValues(unsigned int slot, std::vector<RTypeErasedColumnValue> &values, TTreeReader *r,
72 const ColumnNames_t &bn, const RBookedCustomColumns &customCols, std::index_sequence<S...>,
73 ROOT::TypeTraits::TypeList<ColTypes...>, const std::array<bool, sizeof...(S)> &isTmpColumn)
74{
75 using expander = int[];
76 (void)slot; // avoid bogus 'unused parameter' warning
77 (void)r; // avoid bogus 'unused parameter' warning
78 (void)expander{(values.emplace_back(std::make_unique<RColumnValue<ColTypes>>()), 0)..., 0};
79 (void)expander{(isTmpColumn[S]
80 ? values[S].Cast<ColTypes>()->SetTmpColumn(slot, customCols.GetColumns().at(bn.at(S)).get())
81 : values[S].Cast<ColTypes>()->MakeProxy(r, bn.at(S)),
82 0)...,
83 0};
84}
85
86/// This overload is specialized to act on RTypeErasedColumnValues instead of RColumnValues.
87template <std::size_t... S, typename... ColTypes>
88void ResetRDFValueTuple(std::vector<RTypeErasedColumnValue> &values, std::index_sequence<S...>,
90{
91 using expander = int[];
92 (void)expander{(values[S].Cast<ColTypes>()->Reset(), 0)...};
93}
94
95// fwd decl for RActionCRTP
96template <typename Helper, typename PrevDataFrame, typename ColumnTypes_t>
97class RAction;
98
99/// A common template base class for all RActions. Avoids code repetition for specializations of RActions
100/// for different helpers, implementing all of the common logic.
101template <typename Helper, typename PrevDataFrame, typename ColumnTypes_t>
102class RActionCRTP<RAction<Helper, PrevDataFrame, ColumnTypes_t>> : public RActionBase {
104
105 Helper fHelper;
106 const std::shared_ptr<PrevDataFrame> fPrevDataPtr;
107 PrevDataFrame &fPrevData;
108
109protected:
110 /// The nth flag signals whether the nth input column is a custom column or not.
111 std::array<bool, ColumnTypes_t::list_size> fIsCustomColumn;
112
113public:
114 using TypeInd_t = std::make_index_sequence<ColumnTypes_t::list_size>;
115
116 RActionCRTP(Helper &&h, const ColumnNames_t &columns, std::shared_ptr<PrevDataFrame> pd,
117 RBookedCustomColumns &&customColumns)
118 : RActionBase(pd->GetLoopManagerUnchecked(), columns, std::move(customColumns)), fHelper(std::forward<Helper>(h)),
119 fPrevDataPtr(std::move(pd)), fPrevData(*fPrevDataPtr), fIsCustomColumn()
120 {
121 const auto nColumns = columns.size();
122 const auto &customCols = GetCustomColumns();
123 for (auto i = 0u; i < nColumns; ++i)
124 fIsCustomColumn[i] = customCols.HasName(columns[i]);
125 }
126
127 RActionCRTP(const RActionCRTP &) = delete;
129 // must call Deregister here, before fPrevDataFrame is destroyed,
130 // otherwise if fPrevDataFrame is fLoopManager we get a use after delete
131 ~RActionCRTP() { fLoopManager->Deregister(this); }
132
133 Helper &GetHelper() { return fHelper; }
134
135 void Initialize() final { fHelper.Initialize(); }
136
137 void InitSlot(TTreeReader *r, unsigned int slot) final
138 {
139 for (auto &bookedBranch : GetCustomColumns().GetColumns())
140 bookedBranch.second->InitSlot(r, slot);
141 static_cast<Action_t *>(this)->InitColumnValues(r, slot);
142 fHelper.InitTask(r, slot);
143 }
144
145 void Run(unsigned int slot, Long64_t entry) final
146 {
147 // check if entry passes all filters
148 if (fPrevData.CheckFilters(slot, entry))
149 static_cast<Action_t *>(this)->Exec(slot, entry, TypeInd_t());
150 }
151
152 void TriggerChildrenCount() final { fPrevData.IncrChildrenCount(); }
153
154 void FinalizeSlot(unsigned int slot) final
155 {
156 ClearValueReaders(slot);
157 for (auto &column : GetCustomColumns().GetColumns()) {
158 column.second->ClearValueReaders(slot);
159 }
160 fHelper.CallFinalizeTask(slot);
161 }
162
163 void ClearValueReaders(unsigned int slot) { static_cast<Action_t *>(this)->ResetColumnValues(slot, TypeInd_t()); }
164
165 void Finalize() final
166 {
167 fHelper.Finalize();
168 SetHasRun();
169 }
170
171 std::shared_ptr<RDFGraphDrawing::GraphNode> GetGraph()
172 {
173 auto prevNode = fPrevData.GetGraph();
174 auto prevColumns = prevNode->GetDefinedColumns();
175
176 // Action nodes do not need to ask an helper to create the graph nodes. They are never common nodes between
177 // multiple branches
178 auto thisNode = std::make_shared<RDFGraphDrawing::GraphNode>(fHelper.GetActionName());
179 auto evaluatedNode = thisNode;
180 for (auto &column : GetCustomColumns().GetColumns()) {
181 /* Each column that this node has but the previous hadn't has been defined in between,
182 * so it has to be built and appended. */
183 if (RDFGraphDrawing::CheckIfDefaultOrDSColumn(column.first, column.second))
184 continue;
185 if (std::find(prevColumns.begin(), prevColumns.end(), column.first) == prevColumns.end()) {
186 auto defineNode = RDFGraphDrawing::CreateDefineNode(column.first, column.second.get());
187 evaluatedNode->SetPrevNode(defineNode);
188 evaluatedNode = defineNode;
189 }
190 }
191
192 thisNode->AddDefinedColumns(GetCustomColumns().GetNames());
193 thisNode->SetAction(HasRun());
194 evaluatedNode->SetPrevNode(prevNode);
195 return thisNode;
196 }
197
198 /// This method is invoked to update a partial result during the event loop, right before passing the result to a
199 /// user-defined callback registered via RResultPtr::RegisterCallback
200 void *PartialUpdate(unsigned int slot) final { return PartialUpdateImpl(slot); }
201
202private:
203 // this overload is SFINAE'd out if Helper does not implement `PartialUpdate`
204 // the template parameter is required to defer instantiation of the method to SFINAE time
205 template <typename H = Helper>
206 auto PartialUpdateImpl(unsigned int slot) -> decltype(std::declval<H>().PartialUpdate(slot), (void *)(nullptr))
207 {
208 return &fHelper.PartialUpdate(slot);
209 }
210
211 // this one is always available but has lower precedence thanks to `...`
212 void *PartialUpdateImpl(...) { throw std::runtime_error("This action does not support callbacks!"); }
213};
214
215/// An action node in a RDF computation graph.
216template <typename Helper, typename PrevDataFrame, typename ColumnTypes_t = typename Helper::ColumnTypes_t>
217class RAction final : public RActionCRTP<RAction<Helper, PrevDataFrame, ColumnTypes_t>> {
218 std::vector<RDFValueTuple_t<ColumnTypes_t>> fValues;
219
220public:
222
223 RAction(Helper &&h, const ColumnNames_t &bl, std::shared_ptr<PrevDataFrame> pd,
224 RBookedCustomColumns &&customColumns)
225 : ActionCRTP_t(std::forward<Helper>(h), bl, std::move(pd), std::move(customColumns)), fValues(GetNSlots()) { }
226
227 void InitColumnValues(TTreeReader *r, unsigned int slot)
228 {
231 }
232
233 template <std::size_t... S>
234 void Exec(unsigned int slot, Long64_t entry, std::index_sequence<S...>)
235 {
236 (void)entry; // avoid bogus 'unused parameter' warning in gcc4.9
237 ActionCRTP_t::GetHelper().Exec(slot, std::get<S>(fValues[slot]).Get(entry)...);
238 }
239
240 template <std::size_t... S>
241 void ResetColumnValues(unsigned int slot, std::index_sequence<S...> s)
242 {
244 }
245};
246
247// These specializations let RAction<SnapshotHelper[MT]> type-erase their column values, for (presumably) a small hit in
248// performance (which hopefully be completely swallowed by the cost of I/O during the event loop) and a large,
249// measurable gain in compile time and therefore jitting time.
250// Snapshot is the action that most suffers from long compilation times because it happens to be called with dozens
251// if not with a few hundred template parameters, which pretty much never happens for other actions.
252
253// fwd decl
254template <typename... BranchTypes>
256
257template <typename... BranchTypes>
259
260template <typename PrevDataFrame, typename... ColTypes>
261class RAction<SnapshotHelper<ColTypes...>, PrevDataFrame, ROOT::TypeTraits::TypeList<ColTypes...>> final
262 : public RActionCRTP<RAction<SnapshotHelper<ColTypes...>, PrevDataFrame, ROOT::TypeTraits::TypeList<ColTypes...>>> {
263
265 RActionCRTP<RAction<SnapshotHelper<ColTypes...>, PrevDataFrame, ROOT::TypeTraits::TypeList<ColTypes...>>>;
266 using ColumnTypes_t = typename SnapshotHelper<ColTypes...>::ColumnTypes_t;
267
268 std::vector<std::vector<RTypeErasedColumnValue>> fValues;
269
270public:
271 RAction(SnapshotHelper<ColTypes...> &&h, const ColumnNames_t &bl, std::shared_ptr<PrevDataFrame> pd,
272 RBookedCustomColumns &&customColumns)
273 : ActionCRTP_t(std::forward<SnapshotHelper<ColTypes...>>(h), bl, std::move(pd), std::move(customColumns)),
275 {
276 }
277
278 void InitColumnValues(TTreeReader *r, unsigned int slot)
279 {
282 }
283
284 template <std::size_t... S>
285 void Exec(unsigned int slot, Long64_t entry, std::index_sequence<S...>)
286 {
287 (void)entry; // avoid bogus 'unused parameter' warning in gcc4.9
288 ActionCRTP_t::GetHelper().Exec(slot, fValues[slot][S].template Get<ColTypes>(entry)...);
289 }
290
291 template <std::size_t... S>
292 void ResetColumnValues(unsigned int slot, std::index_sequence<S...> s)
293 {
295 }
296};
297
298// Same exact code as above, but for SnapshotHelperMT. I don't know how to avoid repeating this code
299template <typename PrevDataFrame, typename... ColTypes>
300class RAction<SnapshotHelperMT<ColTypes...>, PrevDataFrame, ROOT::TypeTraits::TypeList<ColTypes...>> final
301 : public RActionCRTP<
302 RAction<SnapshotHelperMT<ColTypes...>, PrevDataFrame, ROOT::TypeTraits::TypeList<ColTypes...>>> {
303
305 RActionCRTP<RAction<SnapshotHelperMT<ColTypes...>, PrevDataFrame, ROOT::TypeTraits::TypeList<ColTypes...>>>;
306 using ColumnTypes_t = typename SnapshotHelperMT<ColTypes...>::ColumnTypes_t;
307
308 std::vector<std::vector<RTypeErasedColumnValue>> fValues;
309
310public:
311 RAction(SnapshotHelperMT<ColTypes...> &&h, const ColumnNames_t &bl, std::shared_ptr<PrevDataFrame> pd,
312 RBookedCustomColumns &&customColumns)
313 : ActionCRTP_t(std::forward<SnapshotHelperMT<ColTypes...>>(h), bl, std::move(pd), std::move(customColumns)),
315 {
316 }
317
318 void InitColumnValues(TTreeReader *r, unsigned int slot)
319 {
322 }
323
324 template <std::size_t... S>
325 void Exec(unsigned int slot, Long64_t entry, std::index_sequence<S...>)
326 {
327 (void)entry; // avoid bogus 'unused parameter' warning in gcc4.9
328 ActionCRTP_t::GetHelper().Exec(slot, fValues[slot][S].template Get<ColTypes>(entry)...);
329 }
330
331 template <std::size_t... S>
332 void ResetColumnValues(unsigned int slot, std::index_sequence<S...> s)
333 {
335 }
336};
337
338} // ns RDF
339} // ns Internal
340} // ns ROOT
341
342#endif // ROOT_RACTION
ROOT::R::TRInterface & r
Definition: Object.C:4
#define h(i)
Definition: RSha256.hxx:106
#define e(i)
Definition: RSha256.hxx:103
long long Long64_t
Definition: RtypesCore.h:69
unsigned long long ULong64_t
Definition: RtypesCore.h:70
char name[80]
Definition: TGX11.cxx:109
typedef void((*Func_t)())
const ColumnNames_t & GetColumnNames() const
Definition: RActionBase.hxx:63
RBookedCustomColumns & GetCustomColumns()
Definition: RActionBase.hxx:64
std::array< bool, ColumnTypes_t::list_size > fIsCustomColumn
The nth flag signals whether the nth input column is a custom column or not.
Definition: RAction.hxx:111
std::make_index_sequence< ColumnTypes_t::list_size > TypeInd_t
Definition: RAction.hxx:114
void * PartialUpdate(unsigned int slot) final
This method is invoked to update a partial result during the event loop, right before passing the res...
Definition: RAction.hxx:200
RActionCRTP(Helper &&h, const ColumnNames_t &columns, std::shared_ptr< PrevDataFrame > pd, RBookedCustomColumns &&customColumns)
Definition: RAction.hxx:116
auto PartialUpdateImpl(unsigned int slot) -> decltype(std::declval< H >().PartialUpdate(slot),(void *)(nullptr))
Definition: RAction.hxx:206
Unused, not instantiatable. Only the partial specialization RActionCRTP<RAction<.....
Definition: RAction.hxx:41
RAction(SnapshotHelperMT< ColTypes... > &&h, const ColumnNames_t &bl, std::shared_ptr< PrevDataFrame > pd, RBookedCustomColumns &&customColumns)
Definition: RAction.hxx:311
RAction(SnapshotHelper< ColTypes... > &&h, const ColumnNames_t &bl, std::shared_ptr< PrevDataFrame > pd, RBookedCustomColumns &&customColumns)
Definition: RAction.hxx:271
An action node in a RDF computation graph.
Definition: RAction.hxx:217
void InitColumnValues(TTreeReader *r, unsigned int slot)
Definition: RAction.hxx:227
void ResetColumnValues(unsigned int slot, std::index_sequence< S... > s)
Definition: RAction.hxx:241
void Exec(unsigned int slot, Long64_t entry, std::index_sequence< S... >)
Definition: RAction.hxx:234
std::vector< RDFValueTuple_t< ColumnTypes_t > > fValues
Definition: RAction.hxx:218
RAction(Helper &&h, const ColumnNames_t &bl, std::shared_ptr< PrevDataFrame > pd, RBookedCustomColumns &&customColumns)
Definition: RAction.hxx:223
Encapsulates the columns defined by the user.
bool HasName(std::string_view name) const
Check if the provided name is tracked in the names list.
const RCustomColumnBasePtrMap_t & GetColumns() const
Returns the list of the pointers to the defined columns.
Helper class that updates and returns TTree branches as well as RDataFrame temporary columns.
A type-erasing wrapper around RColumnValue.
Definition: RAction.hxx:47
RTypeErasedColumnValue(std::unique_ptr< RColumnValue< T > > v)
Definition: RAction.hxx:52
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition: TTreeReader.h:43
bool CheckIfDefaultOrDSColumn(const std::string &name, const std::shared_ptr< ROOT::Detail::RDF::RCustomColumnBase > &column)
std::shared_ptr< GraphNode > CreateDefineNode(const std::string &columnName, const ROOT::Detail::RDF::RCustomColumnBase *columnPtr)
void InitRDFValues(unsigned int slot, RDFValueTuple &valueTuple, TTreeReader *r, const ColumnNames_t &bn, const RBookedCustomColumns &customCols, std::index_sequence< S... >, const std::array< bool, sizeof...(S)> &isCustomColumn)
Initialize a tuple of RColumnValues.
Definition: NodesUtils.hxx:54
unsigned int GetNSlots()
Definition: RDFUtils.cxx:270
void ResetRDFValueTuple(std::vector< RTypeErasedColumnValue > &values, std::index_sequence< S... >, ROOT::TypeTraits::TypeList< ColTypes... >)
This overload is specialized to act on RTypeErasedColumnValues instead of RColumnValues.
Definition: RAction.hxx:88
double T(double x)
Definition: ChebyshevPol.h:34
VSD Structures.
Definition: StringConv.hxx:21
ROOT::Detail::RDF::ColumnNames_t ColumnNames_t
Definition: RDataFrame.cxx:788
RooArgSet S(const RooAbsArg &v1)
static constexpr double s
void forward(const LAYERDATA &prevLayerData, LAYERDATA &currLayerData)
apply the weights (and functions) in forward direction of the DNN
Definition: NeuralNet.icc:546
Lightweight storage for a collection of types.
Definition: TypeTraits.hxx:27