Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ROperator_Tile.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_ROPERATOR_Tile
2#define TMVA_SOFIE_ROPERATOR_Tile
3
5#include "TMVA/ROperator.hxx"
6#include "TMVA/RModel.hxx"
7
8#include <sstream>
9
10namespace TMVA{
11namespace Experimental{
12namespace SOFIE{
13
14template <typename T>
15class ROperator_Tile final : public ROperator
16{
17
18private:
19
20 std::string fNRepeats;
21 std::string fNInput;
22 std::string fNY;
23 std::vector<size_t>fShapeInput;
24 std::vector<size_t> fShapeY;
25
26public:
28 ROperator_Tile(std::string nameRepeat, std::string nameInput, std::string nameY):
29 fNRepeats(UTILITY::Clean_name(nameRepeat)),fNInput(UTILITY::Clean_name(nameInput)), fNY(UTILITY::Clean_name(nameY)){}
30
31 std::vector<ETensorType> TypeInference(std::vector<ETensorType> input){
32 return input;
33 }
34
35 std::vector<std::vector<size_t>> ShapeInference(std::vector<std::vector<size_t>> input){
36 std::vector<size_t> ret = input[0];
37
38 for(size_t i=0; i < input[1].size(); i++) {
39 ret[i]=ret[i]*input[1][i];
40 }
41 return {ret};
42 }
43
44 void Initialize(RModel& model){
45 //input must be a graph input, or already initialized intermediate tensor
46 if (model.CheckIfTensorAlreadyExist(fNInput) == false){
47 throw std::runtime_error("TMVA SOFIE Tile Op Input Tensor is not found in model");
48 }
49 if (model.CheckIfTensorAlreadyExist(fNRepeats) == false){
50 throw std::runtime_error("TMVA SOFIE Tile Op Input Tensor is not found in model");
51 }
53
54 // Retrieve the data pointer for the repeats tensor
55 auto repptr = model.GetInitializedTensorData(fNRepeats);
56 // Cast the raw pointer to the appropriate type (size_t*)
57 auto repeat_shape = static_cast<size_t*>(repptr.get());
58
59 if (repeat_shape == nullptr) {
60 throw std::runtime_error("Failed to retrieve the data for the repeats tensor.");
61 }
62 // Get the shape of the repeats tensor to determine the number of elements
63 auto repeats_shape = model.GetTensorShape(fNRepeats);
64 // Ensure the repeats tensor is 1D and get the number of elements
65 if (repeats_shape.size() != 1) {
66 throw std::runtime_error("Repeats tensor is not 1D.");
67 }
68 size_t num_elements = repeats_shape[0];
69 // Convert the data to a vector
70 std::vector<size_t> repeats_vector(repeat_shape, repeat_shape + num_elements);
71
72 fShapeY = ShapeInference({fShapeInput,repeats_vector})[0];
73
75 }
76
77 std::string Generate(std::string OpName){
78 OpName = "op_" + OpName;
79 if (fShapeInput.empty() || fShapeY.empty()) {
80 throw std::runtime_error("TMVA SOFIE Tile Op called to Generate without being initialized first");
81 }
82
83 //size_t input_length = ConvertShapeToLength(fShapeInput);
84 //size_t output_length = ConvertShapeToLength(fShapeY);
85
86
87 std::stringstream out;
88 std::string input = "tensor_" + fNInput;
89 std::string output = "tensor_" + fNY;
90 out << "///-------- Tile operator\n";
91 out << "{\n"; // add scope to re-use same names
92 out << "std::vector<int> input_shape = " << ConvertShapeToString(fShapeInput) << ";\n";
93 std::vector<size_t> repeats = fShapeY;
94 for (size_t i = 0; i < repeats.size(); i++)
95 repeats[i] /= fShapeInput[i];
96
97 out << "std::vector<int> repeats = " << ConvertShapeToString(repeats) << ";\n";
98 out << "int inputLength = " << ConvertShapeToLength(fShapeInput) << ";\n";
99 out << "int s = 1;\n";
100 // loop from inverse dim order
101 out << "for (int i = " << fShapeInput.size()-1 << "; i >=0; i--) {\n";
102 out << SP << "int r = repeats[i];\n";
103 // we cannot exclude case where repeats=1 since we need offset
104 //out << SP << "if (r == 1 && i < " << fShapeInput.size()-1 << ") continue;\n";
105 out << SP << "int i_offset = 0, o_offset = 0;\n";
106 out << SP << "s = s * input_shape[i];\n";
107 // case we have first copy
108 out << SP << "if (i == " << fShapeInput.size()-1 << ") {\n";
109 out << SP << SP << "for (int j = 0; j < inputLength/s ; j++) {\n";
110 out << SP << SP << SP << "for (int k = 0; k < r ; k++) {\n";
111 out << SP << SP << SP << SP << "std::copy(" << input << "+ i_offset, "
112 << input << "+ i_offset + s, " << output << "+ o_offset);\n";
113 out << SP << SP << SP << SP << "o_offset += s;\n";
114 out << SP << SP << SP << "}\n"; // end k loop
115 out << SP << SP << SP << "i_offset += s;\n";
116 out << SP << SP << "}\n"; // end j loop
117 out << SP << "} else {\n"; // second copy we do from output to output
118 // and we need to loop on j from reverse order to avoir re-writing in output tensor
119 out << SP << SP << "for (int j = inputLength/s - 1 ; j>=0; j--) {\n";
120 out << SP << SP << SP << "o_offset = j*s*r;\n";
121 out << SP << SP << SP << "i_offset = j*s;\n";
122 out << SP << SP << SP << "for (int k = 0; k < r ; k++) {\n";
123 out << SP << SP << SP << SP << "std::copy(" << output << "+ i_offset, "
124 << output << "+ i_offset + s, " << output << "+ o_offset);\n";
125 out << SP << SP << SP << SP << "o_offset += s;\n";
126 out << SP << SP << SP << "}\n"; // end k loop
127 out << SP << SP << "}\n"; // end j loop
128 out << SP << "}\n"; // end if
129 out << SP << "s *= r;\n";
130 out << SP << "inputLength *= r;\n";
131 out << "}\n"; // end i loop
132 out << "}\n"; // end of scope
133 return out.str();
134 }
135};
136
137}//SOFIE
138}//Experimental
139}//TMVA
140
141#endif //TMVA_SOFIE_ROPERATOR_Tile
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: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
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
std::vector< std::vector< size_t > > ShapeInference(std::vector< std::vector< size_t > > input)
ROperator_Tile(std::string nameRepeat, std::string nameInput, std::string nameY)
std::vector< ETensorType > TypeInference(std::vector< ETensorType > input)
std::string Generate(std::string OpName)
const std::string SP
space used to correctly indent the generated C++ code
Definition ROperator.hxx:41
std::string ConvertShapeToString(std::vector< size_t > shape)
std::size_t ConvertShapeToLength(std::vector< size_t > shape)
create variable transformations
static void output()