Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ROperator_Reduce.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_ROPERATOR_Reduce
2#define TMVA_SOFIE_ROPERATOR_Reduce
3
5#include "TMVA/ROperator.hxx"
6#include "TMVA/RModel.hxx"
7
8#include <memory>
9#include <sstream>
10#include <algorithm>
11#include <stdexcept>
12#include <vector>
13#include <cassert>
14
15namespace TMVA{
16namespace Experimental{
17namespace SOFIE{
18
20
21template <typename T, EReduceOpMode Op>
22class ROperator_Reduce final : public ROperator
23{
24private:
25 /* Attributes*/
26 int fkeepdims = 1; //default value
29 std::string fNX;
30 std::string fNY;
31 std::vector<size_t> fShapeX;
32 std::vector<size_t> fShapeY;
33
34
35public:
36
37 std::string Name() {
38 if (fReduceOpMode == ReduceMean) return "ReduceMean";
39 else if (fReduceOpMode == ReduceSumsquare ) return "ReduceSumsquare";
40 else if (fReduceOpMode == ReduceProd ) return "ReduceProd";
41 else if (fReduceOpMode == ReduceSum) return "ReduceSum";
42 return "Invalid";
43 }
44
46 ROperator_Reduce(int keepdims,int attrAxes,std::string nameX, std::string nameY):
47 fkeepdims(keepdims), fAttrAxes(attrAxes), fNX(UTILITY::Clean_name(nameX)), fNY(UTILITY::Clean_name(nameY)) {
48 fReduceOpMode = Op;
49 }
50
51 // type of output given input
52 std::vector<ETensorType> TypeInference(std::vector<ETensorType> input){
53 return input;
54 }
55
56 // shape of output tensors given input tensors
57 std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> input){
58 auto ret = input; //suggest copy to compiler
59 ret[0][fAttrAxes] = 1;
60 return ret;
61 }
62 void Initialize(RModel& model){
63
64 fUseSession = model.UseSession();
65
66 if (model.CheckIfTensorAlreadyExist(fNX) == false){ //input must be a graph input, or already initialized intermediate tensor
67 throw std::runtime_error("TMVA SOFIE Reduce Op Input Tensor " + fNX + " is not found in model");
68 }
69 fShapeX = model.GetTensorShape(fNX);
70 // find shape of Y and add it in the list of intermediate tensors
73
74 }
75
76 std::string Generate(std::string OpName){
77 OpName = "op_" + OpName;
78 if (fShapeX.empty() || fShapeY.empty()) {
79 throw std::runtime_error("TMVA SOFIE Reduce Op called to Generate without being initialized first");
80 }
81
83
86
87 // write here according to size of shape
88 // in generation code can be done automatically
89 // i0 = i / s0 ; i1 = (i % s0) / s1 ; i2 = ( (i % s0) % s1 ) / s2 and so on
90 // and we have for the inverse
91 // i = i0 * s0 + i1 * s1 + i2 * s2 + i3 * s3 ....
92
93 // don't need to divide by last stride s[n-1] since it is 1 by definition
94
95 std::stringstream out;
96 out << "\n//---- operator " << Name() << " " << OpName << "\n";
97 out << SP << "for (size_t i = 0; i < " << outputLength << "; i++) {\n";
98
99 size_t dim = fShapeX.size(); // this is the input dimension (e.g. 2, 3 or 4 or more)
100
101 // here we find output indices
102 out << SP << SP << "size_t idx_0 = i / " << outputStrides[0] << ";\n" ;
103 out << SP << SP << "size_t itmp = i;\n";
104 for (size_t k = 1; k < dim; k++) {
105 out << SP << SP << "itmp = itmp % " << outputStrides[k-1] << ";\n" ;
106 if (k < dim-1)
107 out << SP << SP << "size_t idx_" << k << " = itmp / " << outputStrides[k] << ";\n" ;
108 else
109 // to avoid division by 1 which is outputStrides[dim-1]
110 out << SP << SP << "size_t idx_" << k << " = itmp;\n";
111 }
112
113 // compute reduction
114
116 out << SP << SP << "float sum = 1;\n";
117 else
118 out << SP << SP << "float sum = 0;\n";
119
120 out << SP << SP << "for (size_t k = 0; k < " << fShapeX[fAttrAxes] <<"; k++) { \n";
121 out << SP << SP << SP << "idx_" << fAttrAxes << " = k;\n";
122 // compute input index j
123 out << SP << SP << SP << "size_t l = ";
124 for(int n = dim-1; n >=0; n--) {
125 if (n == int(dim-1))
126 out << "idx_" << n;
127 else
128 out << " + " << "idx_" << n << " * " << inputStrides[n];
129 }
130 out << ";\n";
131
133 out << SP << SP << SP << "sum += tensor_" << fNX << "[l];\n";
134 out << SP << SP << "}\n";
135 out << SP << SP << "float reduceResult = sum/static_cast<float>(" << fShapeX[fAttrAxes] << ");\n";
136 }
137 else if(fReduceOpMode == ReduceSum){
138 out << SP << SP << SP << "sum += tensor_" << fNX << "[l];\n";
139 out << SP << SP << "}\n";
140 out << SP << SP << "float reduceResult = sum;\n";
141 }
142 else if(fReduceOpMode == ReduceSumsquare){
143 out << SP << SP << SP << "sum += tensor_" << fNX << "[l] * tensor_" << fNX << "[l];\n";
144 out << SP << SP << "}\n";
145 out << SP << SP << "float reduceResult = sum;\n";
146 }
147 else if(fReduceOpMode == ReduceProd){
148 out << SP << SP << SP << "sum *= tensor_" << fNX << "[l];\n";
149 out << SP << SP << "}\n";
150 out << SP << SP << "float reduceResult = sum;\n";
151 }
152
153 out << SP << SP << "tensor_" << fNY << "[i] = reduceResult;\n";
154 out << SP << "}\n";
155 return out.str();
156 }
157
158};
159
160}//SOFIE
161}//Experimental
162}//TMVA
163
164
165#endif //TMVA_SOFIE_ROPERATOR_Reduce
166
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void input
const ETensorType & GetTensorType(std::string name)
Definition RModel.cxx:91
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< Dim > dim_shape)
Definition RModel.cxx:187
bool CheckIfTensorAlreadyExist(std::string tensor_name)
Definition RModel.cxx:116
const std::vector< size_t > & GetTensorShape(std::string name)
Definition RModel.cxx:56
ROperator_Reduce(int keepdims, int attrAxes, std::string nameX, std::string nameY)
std::string Generate(std::string OpName)
std::vector< std::vector< size_t > > ShapeInference(std::vector< std::vector< size_t > > input)
std::vector< ETensorType > TypeInference(std::vector< ETensorType > input)
const std::string SP
space used to correctly indent the generated C++ code
Definition ROperator.hxx:41
bool fUseSession
flag to identify if using the session class
Definition ROperator.hxx:42
const Int_t n
Definition legend1.C:16
std::vector< size_t > ComputeStrideFromShape(const std::vector< size_t > &shape)
compute stride of a tensor given its shape (assume layout is row-major)
std::size_t ConvertShapeToLength(std::vector< size_t > shape)
create variable transformations