Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ROperator_Concat.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_ROPERATOR_Concat
2 #define TMVA_SOFIE_ROPERATOR_Concat
3
4
5 #include "TMVA/SOFIE_common.hxx"
6 #include "TMVA/ROperator.hxx"
7 #include "TMVA/RModel.hxx"
8
9 #include <sstream>
10 #include <algorithm>
11 #include <iterator>
12 #include <iomanip>
13 #include <limits>
14
15 namespace TMVA{
16 namespace Experimental{
17 namespace SOFIE{
18
19 template <typename T>
20 class ROperator_Concat final : public ROperator
21 {
22 private:
23 int fAxis=0;
24 int fnewAxis=0;
25 std::vector<std::string> fInputs;
26 std::string fOutput;
27 std::vector<size_t>fOutputShape;
28 std::vector<std::vector<size_t>> fInputShapes;
29
30 public:
32 ROperator_Concat(std::vector<std::string> inputs, int axis, int newAxis, std::string output):
33 fAxis(axis), fnewAxis(newAxis), fOutput(UTILITY::Clean_name(output)) {
34 fInputs.reserve(inputs.size());
35 for (auto & name : inputs)
37 }
38
39 std::vector<ETensorType> TypeInference(std::vector<ETensorType> input){
40 return input;
41 }
42
43 // get shape of output given inputs. It is going to be called after initialized
44 std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> inputs){
45 std::vector<std::vector<size_t>> ret(1);
46 // treat negative axis case
47 if (fAxis<0) {
48 fAxis = inputs[0].size()+fAxis;
49 }
50 if (fAxis < 0 || fAxis >= (int) inputs[0].size())
51 throw std::runtime_error("TMVA SOFIE Concat Op - invalid axis value ");
52
53 int concat_dim=0;
54 if(fnewAxis == 0){
55 for(size_t i = 0; i < inputs.size(); i++) {
56 if (i > 0 && inputs[i].size() != inputs[i-1].size() )
57 throw std::runtime_error("TMVA SOFIE Concat Op - input tensors have different shapes " +
58 ConvertShapeToString(inputs[i]) + " and " + ConvertShapeToString(inputs[i-1]));
59 for (size_t iaxis = 0; iaxis < inputs[i].size(); iaxis++) {
60 if ((int) iaxis == fAxis)
61 concat_dim += inputs[i][iaxis];
62 else
63 if (i> 0 && inputs[i][iaxis] != inputs[i-1][iaxis])
64 throw std::runtime_error("TMVA SOFIE Concat Op - input tensors have wrong shapes " +
65 ConvertShapeToString(inputs[i]) + " and " + ConvertShapeToString(inputs[i-1]));
66 }
67 }
68
69 // output shape
70 ret[0] = inputs[0];
71 ret[0][fAxis] = concat_dim;
72 }
73 std::vector<int> stack;
74 if(fnewAxis == 1){
75 for(size_t i = 0; i < inputs.size(); i++) {
76 if (i > 0 && inputs[i].size() != inputs[i-1].size() )
77 throw std::runtime_error("TMVA SOFIE Concat Op - input tensors have different shapes " +
78 ConvertShapeToString(inputs[i]) + " and " + ConvertShapeToString(inputs[i-1]));
79 for (size_t iaxis = 0; iaxis < inputs[i].size(); iaxis++) {
80 if ((int) iaxis == fAxis)
81 stack.push_back(inputs[i][iaxis]);
82 else
83 if (i> 0 && inputs[i][iaxis] != inputs[i-1][iaxis])
84 throw std::runtime_error("TMVA SOFIE Concat Op - input tensors have wrong shapes " +
85 ConvertShapeToString(inputs[i]) + " and " + ConvertShapeToString(inputs[i-1]));
86 }
87
88 }
89 for(auto it:stack)
90 ret[0].push_back(it);
91 }
92
93 return ret;
94 }
95
96 void Initialize(RModel &model)
97 {
98 for (auto &it : fInputs) {
99 if (model.CheckIfTensorAlreadyExist(it) == false) {
100 throw std::runtime_error("TMVA SOFIE Concat Op Input Tensor " + it + " is not found in model");
101 }
102 fInputShapes.push_back(model.GetTensorShape(it));
103 }
106 }
107
108 std::string Generate(std::string OpName){
109 OpName = "op_"+OpName;
110 if(fOutputShape.empty()){
111 throw std::runtime_error("TMVA SOFIE Concat called to Generate without being initialized first");
112 }
113 std::stringstream out;
114 out<<"\n//--------- Concat\n";
115 // special case when memory is contigous
116 bool hasShapeOnes = true;
117 for(int i = 0; i<fAxis; ++i){
118 if(fInputShapes[0][i]!=1){
119 hasShapeOnes = false;
120 break;
121 }
122 }
123 if (fAxis == 0 || hasShapeOnes) {
124 size_t offset = 0;
125 for(size_t i=0; i<fInputs.size(); ++i){
126 out<<SP<<"std::copy(tensor_"<<fInputs[i]<<", tensor_"<<fInputs[i]<<"+"<<ConvertShapeToLength(fInputShapes[i])<<", tensor_"<<fOutput<<"+"<<offset<<");\n";
128 }
129 }
130 else {
131
132 std::vector<size_t> outStride = UTILITY::ComputeStrideFromShape(fOutputShape);
133 std::vector<std::vector<size_t>> inStrides(fInputs.size());
134 int idx = 0;
135 for ( auto &s : inStrides) {
137 idx++;
138 }
139 for (int i = 0; i < fAxis; ++i) {
140 // loop on dimensions
141 out << SP << "for (size_t i" << i << " = 0; i" << i << " < " << fOutputShape[i] << "; ++i" << i <<") {\n";
142 }
143
144 out << SP << SP << SP << "int idxOut =";
145 for (int k = 0; k < fAxis; k++)
146 out << " + " << outStride[k] << "*i" << k;
147 out << ";\n";
148
149 for (size_t j = 0; j < fInputs.size(); j++) {
150 if (j>0)
151 out << SP << SP << SP << "idxOut += " << fInputShapes[j-1][fAxis] << ";\n";
152 out << SP << SP << SP << "int idxIn" << j <<" =";
153 for (int k = 0; k < fAxis; k++)
154 out << " + " << inStrides[j][k] << "*i" << k;
155 out << ";\n";
156 out << SP << SP << SP << "for (size_t iC = 0; iC < " << fInputShapes[j][fAxis] << "; ++iC) {\n";
157 out << SP << SP << SP << SP << "tensor_" << fOutput << "[idxOut+iC] = tensor_" << fInputs[j] << "[idxIn" << j << "+iC];\n";
158 out << SP << SP << SP << "}\n";
159 // concatenate the axis values
160 }
161 for (int i = 0; i < fAxis; ++i) {
162 out << SP << "}\n";
163 }
164 }
165
166 return out.str();
167 }
168 };
169 }//SOFIE
170 }//Experimental
171 }//TMVA
172
173 #endif //TMVA_SOFIE_ROPERATOR_CONCAT
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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 offset
char name[80]
Definition TGX11.cxx:110
const ETensorType & GetTensorType(std::string name)
Definition RModel.cxx:80
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape)
Definition RModel.cxx:160
bool CheckIfTensorAlreadyExist(std::string tensor_name)
Definition RModel.cxx:101
const std::vector< size_t > & GetTensorShape(std::string name)
Definition RModel.cxx:59
std::vector< std::vector< size_t > > fInputShapes
std::vector< ETensorType > TypeInference(std::vector< ETensorType > input)
std::vector< std::vector< size_t > > ShapeInference(std::vector< std::vector< size_t > > inputs)
ROperator_Concat(std::vector< std::string > inputs, int axis, int newAxis, std::string output)
const std::string SP
space used to correctly indent the generated C++ code
Definition ROperator.hxx:41
std::string Clean_name(std::string input_tensor_name)
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::string ConvertShapeToString(std::vector< size_t > shape)
std::size_t ConvertShapeToLength(std::vector< size_t > shape)
create variable transformations
static void output()