1#ifndef TMVA_SOFIE_ROPERATOR_Reduce
2#define TMVA_SOFIE_ROPERATOR_Reduce
17namespace Experimental{
30template <EReduceOpMode Op>
53 return "ReduceSumSquare";
66 ROperator_Reduce(
int keepdims, std::vector<int64_t> attrAxes, std::string nameX, std::string nameAxes, std::string nameY):
67 fkeepdims(keepdims),
fAttrAxes(attrAxes),
fNX(UTILITY::Clean_name(nameX)),
fNAxes(UTILITY::Clean_name(nameAxes)),
fNY(UTILITY::Clean_name(nameY)) {
81 auto & outputShape = ret;
82 for (
size_t j = 0; j <
fAttrAxes.size(); j++) {
85 throw std::runtime_error(
"TMVA SOFIE Reduce Op - invalid axes values " + std::to_string(
fAttrAxes[j]));
93 std::sort(ax.begin(), ax.end());
94 for (
size_t j = 0; j < ax.size(); j++) {
96 if (outputShape.size() > 0) {
97 outputShape.erase(outputShape.begin() + ax[j]);
98 for (
size_t k = j+1; k < ax.size(); k++)
107 if (!model.CheckIfTensorAlreadyExist(
fNX)) {
109 throw std::runtime_error(
"TMVA SOFIE Reduce Op Input Tensor " +
fNX +
" is not found in model");
112 if (model.IsDynamicTensor(
fNX))
116 auto ax_shptr = model.GetInitializedTensorData(
fNAxes);
117 auto ax_ptr =
static_cast<int64_t *
>(ax_shptr.get());
118 auto ax_shape = model.GetTensorShape(
fNAxes);
120 fAttrAxes = std::vector<int64_t>(ax_ptr, ax_ptr+ax_length);
124 for (
size_t i = 0; i <
fAttrAxes.size(); i++)
129 model.AddIntermediateTensor(
fNY, model.GetTensorType(
fNX),
fShapeY);
130 if (model.Verbose()){
134 model.AddNeededStdLib(
"algorithm");
136 model.AddNeededStdLib(
"limits");
139 std::string
Generate(std::string opName)
override {
140 opName =
"op_" + opName;
156 std::stringstream out;
157 out <<
"\n//---- operator " <<
Name() <<
" " << opName <<
"\n";
159 enum EReduceDim {kFirst, kLast, kMiddle};
160 EReduceDim reduceDims = kLast;
162 for (
int k =
fShapeX.size()-1; k >= kmin; k--) {
165 reduceDims = kMiddle;
169 if (reduceDims == kMiddle) {
172 for (
size_t k = 0; k <
fAttrAxes.size(); k++) {
175 reduceDims = kMiddle;
181 std::string initValue =
"0";
185 initValue =
"std::numeric_limits<" +
fType +
">::lowest()";
187 initValue =
"std::numeric_limits<" +
fType +
">::max()";
189 std::string reducedLength;
191 reducedLength =
"reducedLength_" + opName;
192 out <<
SP <<
"size_t " << reducedLength <<
" = (" << inputLength <<
") / (" << outputLength <<
");\n";
194 int rLength = std::stoi(inputLength) / std::stoi(outputLength);
195 reducedLength = std::to_string(rLength);
197 if (reduceDims == kLast) {
204 out <<
SP <<
"for (size_t i = 0; i < " << outputLength <<
"; i++) {\n";
206 out <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[i] = " << initValue <<
";\n";
207 out <<
SP <<
SP <<
"for (size_t j = 0; j < " << reducedLength <<
"; j++) {\n";
210 out <<
SP <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[i] = std::max(tensor_" <<
fNY <<
"[i], tensor_" <<
fNX
211 <<
"[i * " << reducedLength <<
" + j]);\n";
213 out <<
SP <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[i] = std::min(tensor_" <<
fNY <<
"[i], tensor_" <<
fNX
214 <<
"[i * " << reducedLength <<
" + j]);\n";
216 out <<
SP <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[i] *= tensor_" <<
fNX <<
"[i * " << reducedLength <<
" + j];\n";
218 out <<
SP <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[i] += tensor_" <<
fNX <<
"[i * " << reducedLength <<
" + j];\n";
220 out <<
SP <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[i] += tensor_" <<
fNX <<
"[i * " << reducedLength <<
" + j] * tensor_"
221 <<
fNX <<
"[i * " << reducedLength <<
" + j];\n";
222 out <<
SP <<
SP <<
"}\n";
224 out <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[i] /= static_cast<float>(" << reducedLength <<
");\n";
227 }
else if (reduceDims == kFirst) {
231 out <<
SP <<
"std::fill(tensor_" <<
fNY <<
", tensor_" <<
fNY <<
" + " << outputLength <<
", " << initValue
234 out <<
SP <<
"for (size_t i = 0; i < " << reducedLength <<
"; i++) {\n";
235 out <<
SP <<
SP <<
"for (size_t j = 0; j < " << outputLength <<
"; j++) {\n";
238 out <<
SP <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[j] = std::max(tensor_" <<
fNY <<
"[j], tensor_" <<
fNX
239 <<
"[i * " << outputLength <<
" + j]);\n";
241 out <<
SP <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[j] = std::min(tensor_" <<
fNY <<
"[j], tensor_" <<
fNX
242 <<
"[i * " << outputLength <<
" + j]);\n";
244 out <<
SP <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[j] *= tensor_" <<
fNX <<
"[i * " << outputLength <<
" + j];\n";
246 out <<
SP <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[j] += tensor_" <<
fNX <<
"[i * " << outputLength <<
" + j];\n";
248 out <<
SP <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[j] += tensor_" <<
fNX <<
"[i * " << outputLength <<
" + j] * tensor_"
249 <<
fNX <<
"[i * " << outputLength <<
" + j];\n";
250 out <<
SP <<
SP <<
"}\n";
253 out <<
SP <<
"for (size_t j = 0; j < " << outputLength <<
"; j++) {\n";
254 out <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[j] /= static_cast<float>(" << reducedLength <<
");\n";
262 out <<
SP <<
"std::fill(tensor_" <<
fNY <<
", tensor_" <<
fNY <<
" + " << outputLength <<
", " << initValue
273 for (
size_t q = 0;
q <
n;
q++)
278 out <<
SP <<
SP <<
"size_t inputIndex = 0;\n";
279 std::string outputIndex =
"0";
280 for (
size_t k = 0; k < dim; k++) {
282 out <<
"for (size_t i_" << k <<
" = 0; i_" << k <<
" < (" <<
fShapeX[k] <<
"); i_" << k <<
"++) {\n";
285 std::string next =
"outputIndex_" + std::to_string(k);
287 out <<
"size_t " << next <<
" = " << outputIndex <<
" + i_" << k <<
" * (" << outputStrides[k] <<
");\n";
293 out <<
"// compute reduction....\n";
294 std::string
y =
"tensor_" +
fNY +
"[" + outputIndex +
"]";
295 std::string
x =
"tensor_" +
fNX +
"[inputIndex]";
298 out <<
y <<
" = std::max(" <<
y <<
", " <<
x <<
");\n";
300 out <<
y <<
" = std::min(" <<
y <<
", " <<
x <<
");\n";
302 out <<
y <<
" *= " <<
x <<
";\n";
304 out <<
y <<
" += " <<
x <<
";\n";
306 out <<
y <<
" += " <<
x <<
" * " <<
x <<
";\n";
308 out <<
"inputIndex++;\n";
309 for (
size_t k = dim; k > 0; k--) {
316 out <<
SP <<
"for (size_t i = 0; i < " << outputLength <<
"; i++) {\n";
317 out <<
SP <<
SP <<
"tensor_" <<
fNY <<
"[i] /= static_cast<float>(" << reducedLength <<
");\n";
static void indent(ostringstream &buf, int indent_level)
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void input
std::vector< Dim > fShapeY
std::string Generate(std::string opName) override
std::vector< int64_t > fAttrAxes
std::vector< Dim > fShapeYNotPruned
std::vector< Dim > fShapeX
EReduceOpMode fReduceOpMode
void Initialize(RModel &model) override
ROperator_Reduce(int keepdims, std::vector< int64_t > attrAxes, std::string nameX, std::string nameAxes, std::string nameY)
std::vector< Dim > DoShapeInference(const std::vector< Dim > &input)
std::vector< std::string_view > fInputTensorNames
const std::string SP
space used to correctly indent the generated C++ code
std::vector< std::string_view > fOutputTensorNames
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 ConvertDimShapeToString(const std::vector< Dim > &shape)
std::size_t ConvertShapeToLength(const std::vector< size_t > &shape)
std::string ConvertTypeToString(ETensorType type)
std::string ConvertDimShapeToLength(const std::vector< Dim > &shape)
create variable transformations