Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RVariation.hxx
Go to the documentation of this file.
1// Author: Enrico Guiraud, CERN 10/2021
2
3/*************************************************************************
4 * Copyright (C) 1995-2021, 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_RDF_RVARIATION
12#define ROOT_RDF_RVARIATION
13
14#include "Utils.hxx" // IsRVec
15#include "ColumnReaderUtils.hxx"
16#include "RColumnReaderBase.hxx"
17#include "RLoopManager.hxx"
18#include "RVariationBase.hxx"
19
20#include <ROOT/RStringView.hxx>
21#include <ROOT/TypeTraits.hxx>
22#include <Rtypes.h> // R__CLING_PTRCHECK, Long64_t
23
24#include <array>
25#include <deque>
26#include <map>
27#include <string>
28#include <type_traits> // std::is_same, std::conditional_t
29#include <utility> // std::index_sequence
30#include <vector>
31
32class TTreeReader;
33
34namespace ROOT {
35
36namespace RDF {
37class RDataSource;
38}
39
40namespace Internal {
41namespace RDF {
42
43using namespace ROOT::TypeTraits;
44
45template <typename T>
46bool ResultsSizeEq(const RVec<RVec<T>> &results, std::size_t expected, std::size_t nColumns)
47{
48 if (nColumns == 1)
49 return results.size() == expected;
50
51 return std::all_of(results.begin(), results.end(), [&expected](const RVec<T> &v) { return v.size() == expected; });
52}
53
54template <typename T>
55bool ResultsSizeEq(const RVec<T> &results, std::size_t expected, std::size_t nColumns)
56{
57 assert(nColumns == 1);
58 (void)nColumns;
59
60 return results.size() == expected;
61}
62
63template <typename T>
64std::size_t GetNVariations(const RVec<RVec<T>> &results)
65{
66 assert(!results.empty());
67 return results[0].size();
68}
69
70template <typename T>
71std::size_t GetNVariations(const RVec<T> &results)
72{
73 return results.size();
74}
75
76template <typename RVec_t, typename Value_t = typename RVec_t::value_type>
77std::enable_if_t<!IsRVec<Value_t>::value, const std::type_info &> GetInnerValueType(std::size_t)
78{
79 return typeid(Value_t);
80}
81
82template <typename RVec_t, typename Value_t = typename RVec_t::value_type>
83std::enable_if_t<IsRVec<Value_t>::value, const std::type_info &> GetInnerValueType(std::size_t nCols)
84{
85 if (nCols == 1) // we are varying one column that is an RVec
86 return typeid(Value_t);
87 else // we are varying multiple columns whose type is the inner type of this RVec
88 return typeid(typename Value_t::value_type);
89}
90
91// This overload is for the case of a single column and ret_type != RVec<RVec<...>>
92template <typename T>
93std::enable_if_t<!IsRVec<T>::value, void>
94ResizeResults(ROOT::RVec<T> &results, std::size_t /*nCols*/, std::size_t nVariations)
95{
96 results.resize(nVariations);
97}
98
99// This overload is for the case of ret_type == RVec<RVec<...>>
100template <typename T>
101std::enable_if_t<IsRVec<T>::value, void>
102ResizeResults(ROOT::RVec<T> &results, std::size_t nCols, std::size_t nVariations)
103{
104 if (nCols == 1) {
105 results.resize(nVariations);
106 } else {
107 results.resize(nCols);
108 for (auto &rvecOverVariations : results) {
109 rvecOverVariations.resize(nVariations);
110 }
111 }
112}
113
114// Assign into fLastResults[slot] without changing the addresses of its elements (we gave those addresses away in
115// GetValuePtr)
116// This overload is for the case of a single column and ret_type != RVec<RVec<...>>
117template <typename T>
118std::enable_if_t<!IsRVec<T>::value, void>
119AssignResults(ROOT::RVec<T> &resStorage, ROOT::RVec<T> &&tmpResults, std::size_t /*nCols*/)
120{
121 const auto nVariations = resStorage.size(); // we have already checked that tmpResults has the same size
122
123 for (auto i = 0u; i < nVariations; ++i)
124 resStorage[i] = std::move(tmpResults[i]);
125}
126
127// This overload is for the case of ret_type == RVec<RVec<...>>
128template <typename T>
129std::enable_if_t<IsRVec<T>::value, void>
130AssignResults(ROOT::RVec<T> &resStorage, ROOT::RVec<T> &&tmpResults, std::size_t nCols)
131{
132 // we have already checked that tmpResults has the same inner size
133 const auto nVariations = nCols == 1 ? resStorage.size() : resStorage[0].size();
134
135 if (nCols == 1) {
136 for (auto varIdx = 0u; varIdx < nVariations; ++varIdx)
137 resStorage[varIdx] = std::move(tmpResults[varIdx]);
138 } else {
139 for (auto colIdx = 0u; colIdx < nCols; ++colIdx)
140 for (auto varIdx = 0u; varIdx < nVariations; ++varIdx)
141 resStorage[colIdx][varIdx] = std::move(tmpResults[colIdx][varIdx]);
142 }
143}
144
145template <typename F>
146class R__CLING_PTRCHECK(off) RVariation final : public RVariationBase {
148 using TypeInd_t = std::make_index_sequence<ColumnTypes_t::list_size>;
150
152 std::vector<ret_type> fLastResults;
153
154 /// Column readers per slot and per input column
155 std::vector<std::array<std::unique_ptr<RColumnReaderBase>, ColumnTypes_t::list_size>> fValues;
156
157 template <typename... ColTypes, std::size_t... S>
158 void UpdateHelper(unsigned int slot, Long64_t entry, TypeList<ColTypes...>, std::index_sequence<S...>)
159 {
160 // fExpression must return an RVec<T>
161 auto &&results = fExpression(fValues[slot][S]->template Get<ColTypes>(entry)...);
162
163 if (!ResultsSizeEq(results, fVariationNames.size(), fColNames.size())) {
164 std::string variationName = fVariationNames[0].substr(0, fVariationNames[0].find_first_of(':'));
165 throw std::runtime_error("The evaluation of the expression for variation \"" + variationName +
166 "\" resulted in " + std::to_string(GetNVariations(results)) + " values, but " +
167 std::to_string(fVariationNames.size()) + " were expected.");
168 }
169
170 AssignResults(fLastResults[slot * CacheLineStep<ret_type>()], std::move(results), fColNames.size());
171
172 // silence "unused parameter" warnings in gcc
173 (void)slot;
174 (void)entry;
175 }
176
177 // This overload is for the case of a single column and ret_type != RVec<RVec<...>> -- the colIdx is ignored.
178 template <typename U = typename ret_type::value_type>
179 std::enable_if_t<!IsRVec<U>::value, void *>
180 GetValuePtr(unsigned int slot, std::size_t /*colIdx*/, std::size_t varIdx)
181 {
182 auto &value = fLastResults[slot * CacheLineStep<ret_type>()][varIdx];
183 return static_cast<void *>(&value);
184 }
185
186 // This overload is for the case of ret_type == RVec<RVec<...>>
187 template <typename U = typename ret_type::value_type>
188 std::enable_if_t<IsRVec<U>::value, void *> GetValuePtr(unsigned int slot, std::size_t colIdx, std::size_t varIdx)
189 {
190 if (fColNames.size() == 1) {
191 auto &value = fLastResults[slot * CacheLineStep<ret_type>()][varIdx];
192 return static_cast<void *>(&value);
193 }
194
195 auto &value = fLastResults[slot * CacheLineStep<ret_type>()][colIdx][varIdx];
196 return static_cast<void *>(&value);
197 }
198
199public:
200 RVariation(const std::vector<std::string> &colNames, std::string_view variationName, F expression,
201 const std::vector<std::string> &variationTags, std::string_view type, const RColumnRegister &defines,
202 RLoopManager &lm, const ColumnNames_t &inputColNames)
203 : RVariationBase(colNames, variationName, variationTags, type, defines, lm, inputColNames),
204 fExpression(std::move(expression)), fLastResults(lm.GetNSlots() * RDFInternal::CacheLineStep<ret_type>()),
205 fValues(lm.GetNSlots())
206 {
207 fLoopManager->Book(this);
208
209 for (auto i = 0u; i < lm.GetNSlots(); ++i)
210 ResizeResults(fLastResults[i * RDFInternal::CacheLineStep<ret_type>()], colNames.size(), variationTags.size());
211 }
212
213 RVariation(const RVariation &) = delete;
214 RVariation &operator=(const RVariation &) = delete;
215 ~RVariation() { fLoopManager->Deregister(this); }
216
217 void InitSlot(TTreeReader *r, unsigned int slot) final
218 {
219 for (auto &define : fColumnRegister.GetColumns())
220 define.second->InitSlot(r, slot);
221 RColumnReadersInfo info{fInputColumns, fColumnRegister, fIsDefine.data(), fLoopManager->GetDSValuePtrs(),
222 fLoopManager->GetDataSource()};
223 fValues[slot] = MakeColumnReaders(slot, r, ColumnTypes_t{}, info);
224 fLastCheckedEntry[slot * CacheLineStep<Long64_t>()] = -1;
225 }
226
227 /// Return the (type-erased) address of the value for the given processing slot.
228 void *GetValuePtr(unsigned int slot, const std::string &column, const std::string &variation) final
229 {
230 const auto colIt = std::find(fColNames.begin(), fColNames.end(), column);
231 assert(colIt != fColNames.end());
232 const auto colIdx = std::distance(fColNames.begin(), colIt);
233
234 const auto varIt = std::find(fVariationNames.begin(), fVariationNames.end(), variation);
235 assert(varIt != fVariationNames.end());
236 const auto varIdx = std::distance(fVariationNames.begin(), varIt);
237
238 return GetValuePtr(slot, colIdx, varIdx);
239 }
240
241 /// Update the value at the address returned by GetValuePtr with the content corresponding to the given entry
242 void Update(unsigned int slot, Long64_t entry) final
243 {
244 if (entry != fLastCheckedEntry[slot * CacheLineStep<Long64_t>()]) {
245 // evaluate this filter, cache the result
246 UpdateHelper(slot, entry, ColumnTypes_t{}, TypeInd_t{});
247 fLastCheckedEntry[slot * CacheLineStep<Long64_t>()] = entry;
248 }
249 }
250
251 const std::type_info &GetTypeId() const { return GetInnerValueType<ret_type>(fColNames.size()); }
252
253 /// Clean-up operations to be performed at the end of a task.
254 void FinalizeSlot(unsigned int slot) final
255 {
256 for (auto &v : fValues[slot])
257 v.reset();
258 }
259};
260
261} // namespace RDF
262} // namespace Internal
263} // namespace ROOT
264
265#endif // ROOT_RDF_RVARIATION
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
ROOT::R::TRInterface & r
Definition Object.C:4
long long Long64_t
Definition RtypesCore.h:80
int type
Definition TGX11.cxx:121
The head node of a RDF computation graph.
void resize(size_type N)
Definition RVec.hxx:560
A binder for user-defined columns and aliases.
This type includes all parts of RVariation that do not depend on the callable signature.
std::make_index_sequence< ColumnTypes_t::list_size > TypeInd_t
void InitSlot(TTreeReader *r, unsigned int slot) final
typename CallableTraits< F >::ret_type ret_type
void FinalizeSlot(unsigned int slot) final
Clean-up operations to be performed at the end of a task.
std::enable_if_t< IsRVec< U >::value, void * > GetValuePtr(unsigned int slot, std::size_t colIdx, std::size_t varIdx)
RVariation(const std::vector< std::string > &colNames, std::string_view variationName, F expression, const std::vector< std::string > &variationTags, std::string_view type, const RColumnRegister &defines, RLoopManager &lm, const ColumnNames_t &inputColNames)
void * GetValuePtr(unsigned int slot, const std::string &column, const std::string &variation) final
Return the (type-erased) address of the value for the given processing slot.
std::enable_if_t<!IsRVec< U >::value, void * > GetValuePtr(unsigned int slot, std::size_t, std::size_t varIdx)
typename CallableTraits< F >::arg_types ColumnTypes_t
void UpdateHelper(unsigned int slot, Long64_t entry, TypeList< ColTypes... >, std::index_sequence< S... >)
std::vector< ret_type > fLastResults
void Update(unsigned int slot, Long64_t entry) final
Update the value at the address returned by GetValuePtr with the content corresponding to the given e...
RVariation(const RVariation &)=delete
RVariation & operator=(const RVariation &)=delete
const std::type_info & GetTypeId() const
std::vector< std::array< std::unique_ptr< RColumnReaderBase >, ColumnTypes_t::list_size > > fValues
Column readers per slot and per input column.
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1455
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition TTreeReader.h:44
#define F(x, y, z)
std::enable_if_t<!IsRVec< Value_t >::value, const std::type_info & > GetInnerValueType(std::size_t)
std::enable_if_t<!IsRVec< T >::value, void > ResizeResults(ROOT::RVec< T > &results, std::size_t, std::size_t nVariations)
unsigned int GetNSlots()
Definition RDFUtils.cxx:285
std::enable_if_t<!IsRVec< T >::value, void > AssignResults(ROOT::RVec< T > &resStorage, ROOT::RVec< T > &&tmpResults, std::size_t)
std::size_t GetNVariations(const RVec< RVec< T > > &results)
constexpr std::size_t CacheLineStep()
Stepping through CacheLineStep<T> values in a vector<T> brings you to a new cache line.
Definition Utils.hxx:220
std::array< std::unique_ptr< RDFDetail::RColumnReaderBase >, sizeof...(ColTypes)> MakeColumnReaders(unsigned int slot, TTreeReader *r, TypeList< ColTypes... >, const RColumnReadersInfo &colInfo, const std::string &variationName="nominal")
Create a group of column readers, one per type in the parameter pack.
bool ResultsSizeEq(const RVec< RVec< T > > &results, std::size_t expected, std::size_t nColumns)
std::vector< std::string > ColumnNames_t
Definition Utils.hxx:35
ROOT type_traits extensions.
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Extract types from the signature of a callable object. See CallableTraits.
This type aggregates some of the arguments passed to MakeColumnReaders.
Lightweight storage for a collection of types.