Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ROperator_BasicBinary.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_ROperator_BasicBinary
2#define TMVA_SOFIE_ROperator_BasicBinary
3
5#include "TMVA/ROperator.hxx"
6#include "TMVA/RModel.hxx"
7
8#include <sstream>
9
10namespace TMVA{
11namespace Experimental{
12namespace SOFIE{
13
15
16template <typename T, EBasicBinaryOperator Op1>
18
19template <typename T>
21 static const std::string Name() { return "Add"; }
22 static std::string Op(const std::string & t1, const std::string t2) { return t1 + " + " + t2; }
23 static T Func(T t1, T t2) {return t1 + t2;}
24};
25
26template <typename T>
28 static const std::string Name() { return "Sub"; }
29 static std::string Op(const std::string & t1, const std::string t2) { return t1 + " - " + t2; }
30 static T Func (T t1, T t2) { return t1 - t2;}
31};
32
33template <typename T>
35 static const std::string Name() { return "Mul"; }
36 static std::string Op(const std::string & t1, const std::string t2) { return t1 + " * " + t2; }
37 static T Func (T t1, T t2) { return t1 * t2;}
38};
39
40template <typename T>
42 static const std::string Name() { return "Div"; }
43 static std::string Op(const std::string & t1, const std::string t2) { return t1 + " / " + t2; }
44 static T Func (T t1, T t2) { return t1/t2;}
45};
46
47template <typename T>
49 static const std::string Name() { return "Pow"; }
50 static std::string Op(const std::string & t1, const std::string t2) { return "std::pow(" + t1 + "," + t2 + ")"; }
51 static T Func (T t1, T t2) { return std::pow(t1,t2);}
52};
53
54template <typename T>
55struct TensorType {};
56template<>
57struct TensorType<float> {
58 static const std::string Name() { return "float"; }
59};
60template<>
62 static const std::string Name() { return "double"; }
63};
64template<>
65struct TensorType<int64_t> {
66 static const std::string Name() { return "int64_t"; }
67};
68template<>
69struct TensorType<int32_t> {
70 static const std::string Name() { return "int32_t"; }
71};
72template<>
73struct TensorType<uint32_t> {
74 static const std::string Name() { return "uint32_t"; }
75};
76template<>
77struct TensorType<uint64_t> {
78 static const std::string Name() { return "uint64_t"; }
79};
80
81template<typename T, EBasicBinaryOperator Op>
82class ROperator_BasicBinary final : public ROperator{
83private:
84
85 std::string fNA;
86 std::string fNB;
87 std::string fNBroadcastedA;
88 std::string fNBroadcastedB;
89 std::string fNY;
90
91 std::vector<size_t> fShapeA;
92 std::vector<size_t> fShapeB;
93 std::vector<size_t> fShapeY;
94
95public:
97 ROperator_BasicBinary(std::string nameA, std::string nameB, std::string nameY):
98 fNA(UTILITY::Clean_name(nameA)), fNB(UTILITY::Clean_name(nameB)), fNY(UTILITY::Clean_name(nameY)){}
99
100 // type of output given input
101 std::vector<ETensorType> TypeInference(std::vector<ETensorType> input) override {
102 return input;
103 }
104
105 // shape of output tensors given input tensors
106 std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> input) override {
107 // assume now inputs have same shape (no broadcasting)
108 auto ret = std::vector<std::vector<size_t>>(1, input[0]); // return vector size 1 with first input
109 return ret;
110 }
111
112 void Initialize(RModel& model) override {
113 // input must be a graph input, or already initialized intermediate tensor
114 if (!model.CheckIfTensorAlreadyExist(fNA)){
115 throw std::runtime_error(std::string("TMVA SOFIE Binary Op Input Tensor ") + fNA + "is not found in model");
116 }
117 if (!model.CheckIfTensorAlreadyExist(fNB)) {
118 throw std::runtime_error(std::string("TMVA SOFIE Binary Op Input Tensor ") + fNB + "is not found in model");
119 }
120 fShapeA = model.GetTensorShape(fNA);
121 fShapeB = model.GetTensorShape(fNB);
122 bool broadcast = !UTILITY::AreSameShape(fShapeA, fShapeB);
123 if (broadcast) {
124 // Y is the common shape of A and B
126 bool broadcastA = !UTILITY::AreSameShape(fShapeA, fShapeY);
127 bool broadcastB = !UTILITY::AreSameShape(fShapeB, fShapeY);
128 // Broadcast A to Y
129 if (broadcastA) {
130 fNBroadcastedA = "Broadcasted" + fNA + "to" + fNY;
131 if (model.IsInitializedTensor(fNA)) {
132 auto data = model.GetInitializedTensorData(fNA);
133 std::shared_ptr<void> broadcastedData(
134 UTILITY::UnidirectionalBroadcast<T>(static_cast<T *>(data.get()), fShapeA, fShapeY),
135 std::default_delete<T[]>());
136 // Update the data and the shape of A
137 model.AddConstantTensor(fNBroadcastedA, model.GetTensorType(fNA), fShapeY, broadcastedData);
139 } else {
140 // Add an intermediate tensor for broadcasting A
142 }
143 }
144 // Broadcast B to Y
145 if (broadcastB) {
146 fNBroadcastedB = "Broadcasted" + fNB + "to" + fNY;
147 if (model.IsInitializedTensor(fNB)) {
148 auto data = model.GetInitializedTensorData(fNB);
149 std::shared_ptr<void> broadcastedData(
150 UTILITY::UnidirectionalBroadcast<T>(static_cast<T *>(data.get()), fShapeB, fShapeY),
151 std::default_delete<T[]>());
152 // do not update tensor B but add broadcasted one (since it can be input to some other operators)
153 model.AddConstantTensor(fNBroadcastedB, model.GetTensorType(fNB), fShapeY, broadcastedData);
155 } else {
156 // Add an intermediate tensor for broadcasting B
158 }
159 }
160 } else {
162 }
163 // check case of constant output (if all inputs are defined)
164 if (model.IsInitializedTensor(fNA) && model.IsInitializedTensor(fNB)) {
165 auto dataA = static_cast<T *>(model.GetInitializedTensorData(fNA).get());
166 auto dataB = static_cast<T *>(model.GetInitializedTensorData(fNB).get());
167 std::vector<T> dataY(ConvertShapeToLength(fShapeY));
168 for (size_t i = 0; i < dataY.size(); i++)
169 dataY[i] = BinaryOperatorTrait<T,Op>::Func(dataA[i], dataB[i]);
170 model.AddConstantTensor<T>(fNY, fShapeY, dataY.data());
171 // flag tensors to not be written in a fil
174 fIsOutputConstant = true;
175 if (model.Verbose())
176 std::cout << "Binary op ---> " << fNY << " " << ConvertShapeToString(fShapeY) << " : "
177 << ConvertValuesToString(dataY) << std::endl;
178 }
179 else {
181 }
182 }
183
184 std::string GenerateInitCode() override {
185 std::stringstream out;
186 return out.str();
187 }
188
189 std::string Generate(std::string OpName) override {
190
191 if (fIsOutputConstant) return "";
192
193 OpName = "op_" + OpName;
194
195 if (fShapeY.empty()) {
196 throw std::runtime_error("TMVA SOFIE Binary Op called to Generate without being initialized first");
197 }
198 std::stringstream out;
199 out << SP << "\n//------ " << BinaryOperatorTrait<T,Op>::Name() << "\n";
201 std::string typeName = TensorType<T>::Name();
202 // Broadcast A if it's uninitialized
203 if (fShapeA != fShapeY) {
204 out << SP << "// Broadcasting uninitialized tensor " << fNA << "\n";
205 out << SP << "{\n";
206 out << SP << SP << typeName << "* data = TMVA::Experimental::SOFIE::UTILITY::UnidirectionalBroadcast<" << typeName << ">(tensor_" << fNA << ", " << ConvertShapeToString(fShapeA) << ", " << ConvertShapeToString(fShapeY) << ");\n";
207 out << SP << SP << "std::copy(data, data + " << length << ", tensor_" << fNBroadcastedA << ");\n";
208 out << SP << SP << "delete[] data;\n";
209 out << SP << "}\n";
210 }
211 // Broadcast B if it's uninitialized
212 if (fShapeB != fShapeY) {
213 out << SP << "// Broadcasting uninitialized tensor " << fNB << "\n";
214 out << SP << "{\n";
215 out << SP << SP << typeName << "* data = TMVA::Experimental::SOFIE::UTILITY::UnidirectionalBroadcast<" << typeName << ">(tensor_" << fNB << ", " << ConvertShapeToString(fShapeB) << ", " << ConvertShapeToString(fShapeY) << ");\n";
216 out << SP << SP << "std::copy(data, data + " << length << ", tensor_" << fNBroadcastedB << ");\n";
217 out << SP << SP << "delete[] data;\n";
218 out << SP << "}\n";
219 }
220 const std::string& nameA = fNBroadcastedA.empty()? fNA : fNBroadcastedA;
221 const std::string& nameB = fNBroadcastedB.empty()? fNB : fNBroadcastedB;
222 out << SP << "for (size_t id = 0; id < " << length << " ; id++){\n";
223 out << SP << SP << "tensor_" << fNY << "[id] = " << BinaryOperatorTrait<T,Op>::Op( "tensor_" + nameA + "[id]" , "tensor_" + nameB + "[id]") << " ;\n";
224 out << SP << "}\n";
225 return out.str();
226 }
227
228 std::vector<std::string> GetStdLibs() override {
229 if (Op == EBasicBinaryOperator::Pow) {
230 return { std::string("cmath") };
231 } else {
232 return {};
233 }
234 }
235};
236
237}//SOFIE
238}//Experimental
239}//TMVA
240
241
242#endif //TMVA_SOFIE_ROperator_BasicBinary
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void input
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h length
const ETensorType & GetTensorType(std::string name)
Definition RModel.cxx:94
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< Dim > dim_shape)
Definition RModel.cxx:203
bool CheckIfTensorAlreadyExist(std::string tensor_name)
Definition RModel.cxx:122
void AddConstantTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
Definition RModel.cxx:178
bool IsInitializedTensor(const std::string &name) const
Definition RModel.cxx:188
const std::vector< size_t > & GetTensorShape(std::string name)
Definition RModel.cxx:56
std::shared_ptr< void > GetInitializedTensorData(std::string tensor_name)
Definition RModel.cxx:264
void SetNotWritableInitializedTensor(const std::string &tensor_name)
Definition RModel.cxx:273
std::vector< ETensorType > TypeInference(std::vector< ETensorType > input) override
std::vector< std::vector< size_t > > ShapeInference(std::vector< std::vector< size_t > > input) override
std::string Generate(std::string OpName) override
ROperator_BasicBinary(std::string nameA, std::string nameB, std::string nameY)
bool fIsOutputConstant
flag to identify if operator has a constant output (no need to generate code)
Definition ROperator.hxx:43
const std::string SP
space used to correctly indent the generated C++ code
Definition ROperator.hxx:41
bool AreSameShape(const std::vector< size_t > &, const std::vector< size_t > &)
std::vector< size_t > UnidirectionalBroadcastShape(std::vector< size_t >, std::vector< size_t >)
std::string ConvertValuesToString(size_t n, const T *data)
std::string ConvertShapeToString(std::vector< size_t > shape)
std::size_t ConvertShapeToLength(std::vector< size_t > shape)
create variable transformations
static std::string Op(const std::string &t1, const std::string t2)
static std::string Op(const std::string &t1, const std::string t2)
static std::string Op(const std::string &t1, const std::string t2)
static std::string Op(const std::string &t1, const std::string t2)
static std::string Op(const std::string &t1, const std::string t2)
auto * t1
Definition textangle.C:20