Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ROperator_TopK.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_ROPERATOR_TOPK
2#define TMVA_SOFIE_ROPERATOR_TOPK
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>
16
17private:
21
23 std::string fNK;
24 std::string fNX;
25 std::string fNVal;
26 std::string fNInd;
27 std::vector<Dim> fShapeX;
28 std::vector<Dim> fShapeY;
29 std::string fType;
30
31public:
33 ROperator_TopK(int attr_axis, int attr_largest, int attr_sorted, std::string nameK, std::string nameX, std::string nameVal, std::string nameInd)
37 fNK(UTILITY::Clean_name(nameK)),
38 fNX(UTILITY::Clean_name(nameX)),
39 fNVal(UTILITY::Clean_name(nameVal)),
40 fNInd(UTILITY::Clean_name(nameInd)){
43 }
44
45 std::vector<ETensorType> TypeInference(std::vector<ETensorType> input) override {
47 return {ret, ret};
48 }
49
50 void Initialize(RModel& model) override {
51 if (model.CheckIfTensorAlreadyExist(fNX) == false) {
52 // input must be a graph input, or already initialized intermediate tensor
53 throw std::runtime_error("TMVA SOFIE TopK Op Input Tensor is not found in model");
54 }
55 if (model.CheckIfTensorAlreadyExist(fNK) == false) {
56 // input must be a graph input, or already initialized intermediate tensor
57 throw std::runtime_error("TMVA SOFIE TopK Op Input Tensor i.e. K is not found in model");
58 }
59
61 auto fShapeK = model.GetTensorShape(fNK);
62 auto kptr = static_cast<int64_t *>(model.GetInitializedTensorData(fNK).get());
63 size_t kval = *kptr;
66 if(static_cast<size_t>(fAttrAxis) >= fShapeX.size()){
67 throw
68 std::runtime_error("TMVA::SOFIE ONNX TopK op axis = "+ std::to_string(fAttrAxis) +" value exeeds size of tensor " +fNX+" of size "+fShapeX.size()+" .");
69 }
70 // fK cannot be larger that axis dimension
71 if (fShapeX[fAttrAxis].isParam)
72 fK = Dim{std::string("std::min(size_t(" + std::to_string(kval) + "), " + fShapeX[fAttrAxis].GetVal() + ")" ), static_cast<size_t>(-1) };
73 else
74 fK = Dim { std::min(kval, fShapeX[fAttrAxis].dim) };
75
76 // output shape is equal to input shape apart for value in fAttrAxis
79
81
82 // output indices should be an int64 tensor
85
86 if (model.Verbose()) {
87 std::cout << "TopK " << fNX << " " << ConvertShapeToString(fShapeX)
88 << "---> " << fNVal << " " << ConvertShapeToString(fShapeY) << std::endl;
89 }
90 }
91
92 std::string Generate(std::string OpName) override {
93 OpName = "op_" + OpName;
94 if (fShapeX.empty()) {
95 throw std::runtime_error("TMVA SOFIE Operator TopK called to Generate without being initialized first");
96 }
97 std::stringstream out;
98 size_t size = fShapeX.size();
99 size_t axis = fAttrAxis < 0 ? size + fAttrAxis : fAttrAxis;
100 out << "\n" << SP << "//------ TopK\n";
101
105 // we perform loop on dimension before sorted axis and after sorted axis
106 std::vector<Dim> shape_before(fShapeX.begin(), fShapeX.begin() + axis); // input shape before axis
107 std::string n_before = (axis>0) ? ConvertDimShapeToLength(shape_before) : "1";
108 std::string n_after = strideX[axis].GetVal();
109 std::string n_elements = fShapeX[axis].GetVal(); // number of elements to be sorted
110
111 // }
112 out << SP << "{\n"; // to define a separate scope for the operator code
113 out << SP << "std::vector<std::pair<float,int64_t>> elements(" << n_elements << ");\n";
114 // loop on elements before
115 if (n_before != "1") {
116 out << SP << "for (size_t i = 0; i < " << n_before << "; i++) {\n";
117 out << SP << SP << "size_t xoffset = i*" << strideX[axis-1] << ";\n";
118 out << SP << SP << "size_t yoffset = i*" << strideY[axis-1] << ";\n";
119 out << SP;
120 } else {
121 out << SP << "size_t xoffset = 0;\n";
122 out << SP << "size_t yoffset = 0;\n";
123 }
124 if (n_after != "1")
125 out << SP << "for (size_t j = 0; j < " << n_after << "; j++) {\n";
126 else
127 out << SP << "const size_t j = 0;\n";
128
129 // copy elements to be sorted in vector of pair
130 out << SP << SP << "for (size_t l = 0; l < " << n_elements << "; l++) {\n";
131 out << SP << SP << SP << "elements[l] = std::make_pair(tensor_" << fNX << "[xoffset + " << strideX[axis] << "*l + j], l);\n";
132 out << SP << SP << "}\n";
133
134 if (fAttrSorted) {
135 if (fAttrLargest) {
136 out<<SP<<SP << "std::partial_sort(elements.begin(),elements.begin()+" << fK << ",elements.end()," <<
137 "[](std::pair<float,int64_t>a,std::pair<float,int64_t>b){return (a.first!=b.first) ? (a.first>b.first) : a.second < b.second;});\n";
138
139 } else
140 out<<SP<<SP << "std::partial_sort(elements.begin(),elements.begin()+" << fK << ",elements.end()," <<
141 "[](std::pair<float,int64_t>a,std::pair<float,int64_t>b){return (a.first!=b.first) ? (a.first<b.first) : a.second < b.second;});\n";
142 } else
143 // in this case we don;t need to return sorted elements, so we keep same order as before
144 out<<SP<<SP << "std::partial_sort(elements.begin(),elements.begin()+" << fK << ",elements.end());\n";
145
146 // copy the selected elements in the output
147 out << SP << SP << "for (size_t l = 0; l < " << fK << "; l++) {\n";
148 out << SP << SP << SP << "tensor_" << fNVal << "[yoffset + " << strideY[axis] << "*l + j] = elements[l].first;\n";
149 out << SP << SP << SP << "tensor_" << fNInd << "[yoffset + " << strideY[axis] << "*l + j] = elements[l].second;\n";
150 out << SP << SP << "}\n";
151 if (n_after != "1") out << SP << SP << "}\n";
152 if (n_before != "1") out << SP << "}\n";
153 out << SP << "}\n"; // end operator scope
154 return out.str();
155 }
156};
157
158} // namespace SOFIE
159} // namespace Experimental
160} // namespace TMVA
161
162#endif // TMVA_SOFIE_ROPERATOR_TOPK
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
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
std::vector< size_t > GetTensorShape(const std::string &name) const
Definition RModel.cxx:29
std::vector< Dim > GetDimTensorShape(const std::string &name) const
Definition RModel.cxx:65
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< Dim > dim_shape)
Definition RModel.cxx:262
bool CheckIfTensorAlreadyExist(std::string tensor_name)
Definition RModel.cxx:122
std::shared_ptr< void > GetInitializedTensorData(std::string tensor_name)
Definition RModel.cxx:327
void SetNotWritableInitializedTensor(const std::string &tensor_name)
Definition RModel.cxx:336
ETensorType GetTensorType(std::string name) const
Definition RModel.cxx:90
std::string Generate(std::string OpName) override
std::vector< ETensorType > TypeInference(std::vector< ETensorType > input) override
ROperator_TopK(int attr_axis, int attr_largest, int attr_sorted, std::string nameK, std::string nameX, std::string nameVal, std::string nameInd)
void Initialize(RModel &model) override
std::vector< std::string_view > fInputTensorNames
Definition ROperator.hxx:47
const std::string SP
space used to correctly indent the generated C++ code
Definition ROperator.hxx:42
std::vector< std::string_view > fOutputTensorNames
Definition ROperator.hxx:48
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 ConvertTypeToString(ETensorType type)
std::string ConvertDimShapeToLength(const std::vector< Dim > &shape)
std::string ConvertShapeToString(const std::vector< size_t > &shape)
create variable transformations