1#ifndef TMVA_SOFIE_ROPERATOR_CONV
2#define TMVA_SOFIE_ROPERATOR_CONV
16namespace Experimental {
51 size_t group, std::vector<size_t> kernelShape, std::vector<size_t> pads,
52 std::vector<size_t> strides, std::string nameX, std::string nameW,
53 std::string nameB, std::string nameY):
56 fNX(UTILITY::Clean_name(nameX)),
fNW(UTILITY::Clean_name(nameW)),
57 fNB(UTILITY::Clean_name(nameB)),
fNY(UTILITY::Clean_name(nameY))
59 if(std::is_same<T, float>::value) {
63 std::runtime_error(
"TMVA SOFIE Encountered unsupported type parsing a Conv operator");
68 size_t group, std::vector<size_t> kernelShape, std::vector<size_t> pads,
69 std::vector<size_t> strides, std::string nameX, std::string nameW,
73 fNX(UTILITY::Clean_name(nameX)),
fNW(UTILITY::Clean_name(nameW)),
fNY(UTILITY::Clean_name(nameY))
75 if(std::is_same<T, float>::value) {
79 std::runtime_error(
"TMVA SOFIE Encountered unsupported type parsing a Conv operator");
93 if (
input.size() > 3 ) {
95 std::runtime_error(
"TMVA SOFIE Conv Op Shape inference need 2 or 3 input tensors");
97 for(
size_t i = 0; i <
input.size(); i++) {
100 std::runtime_error(
"TMVA SOFIE Conv Op Shape inference - invalid inputs ");
114 size_t i1 = (
fDim > 1) ? ((
fDim > 2) ? 3 : 2) : 1;
115 size_t i2 = (
fDim > 2) ? 4 : 3;
155 std::runtime_error(
"TMVA SOFIE Conv Op invalid fAutopad");
167 size_t input1 =
input[0][2];
168 size_t input2 = (
fDim > 1) ?
input[0][3] : 1;
169 size_t input3 = (
fDim > 2) ?
input[0][4] : 1;
174 size_t batch_size =
input[0][0];
175 size_t output_channels =
input[1][0];
177 std::vector<std::vector<size_t>> ret({{ batch_size, output_channels, output1 }});
185 ret[0].push_back(output2);
193 ret[0].push_back(output3);
201 std::runtime_error(
"TMVA SOFIE Conv op Input Tensor " +
fNX +
" is not found in model");
207 std::runtime_error(
"TMVA SOFIE Conv Op input data tensor" +
fNX +
" is not of 3,4 or 5 dimensions");
212 std::runtime_error(
"TMVA SOFIE Conv op Input weight Tensor " +
fNW +
" is not found in model");
217 throw std::runtime_error(
"TMVA SOFIE Conv Op input weight tensor" +
fNW +
" is not of 3,4 or 5 dimensions");
224 std::runtime_error(
"TMVA SOFIE Conv op Input Tensor " +
fNB +
" is not found in model");
227 std::vector<size_t> targetShape(
fShapeY.begin() + 1,
fShapeY.end());
229 if (broadcast_needed) {
233 throw std::runtime_error(
"TMVA SOFIE Conv op: Bias Tensor has empty shape");
237 throw std::runtime_error(
"TMVA SOFIE Conv op: Bias Tensor has wrong shape: " +
239 if (
fType !=
"float")
240 throw std::runtime_error(
"TMVA SOFIE Conv op: Broadcasting for non-float type tensors is not supported");
243 std::vector<size_t> shape(
fDim + 1, 1);
245 std::shared_ptr<void> new_data_ptr(
246 UTILITY::UnidirectionalBroadcast<float>(
static_cast<float *
>(original_data.get()), shape, targetShape),
247 std::default_delete<
float[]>());
263 std::stringstream out;
267 std::vector<size_t> shape(
fDim + 1, 1);
269 std::vector<size_t> targetShape(
fShapeY.begin() + 1,
fShapeY.end());
271 out <<
SP <<
SP <<
"float * data = TMVA::Experimental::SOFIE::UTILITY::UnidirectionalBroadcast<float>(tensor_"
274 out <<
SP <<
SP <<
"delete[] data;\n";
283 size_t outputChannelSize =
fShapeY[2];
285 for (
size_t i = 1; i <
fDim; i++) {
286 outputChannelSize *=
fShapeY[2 + i];
290 opName =
"op_" + opName;
291 std::stringstream out;
293 out <<
"std::vector<" <<
fType <<
"> fVec_" << opName <<
"_f = std::vector<" <<
fType <<
">("
296 out <<
"std::vector<" <<
fType <<
"> fVec_" << opName <<
"_xcol = std::vector<" <<
fType <<
">("
297 <<
fShapeW[1] * kernelSize * outputChannelSize <<
");\n";
304 OpName =
"op_" + OpName;
308 std::runtime_error(
"TMVA SOFIE Conv Op called to Generate without being initialized first");
311 std::stringstream out;
323 out <<
"\n//---- operator Conv " << OpName <<
"\n";
327 out <<
SP <<
fType <<
" * " << OpName <<
"_f = fVec_" << OpName <<
"_f.data();\n";
335 size_t id = (
fDim > 2) ?
fDim-3 : 2;
336 size_t ih = (
fDim > 1) ?
fDim-2 : 1;
340 size_t hstride = kWidth;
342 size_t dstride = kHeight * kWidth;
344 size_t icstride = kHeight * kWidth * kDepth;
346 size_t ocstride =
fShapeW[1] * icstride;
347 size_t ocstrideDil =
fShapeW[1] * icstrideDil;
349 out <<
SP <<
"for (std::size_t oc = 0; oc < " <<
fShapeW[0] <<
"; oc++) {\n";
350 out <<
SP <<
SP <<
"for (std::size_t ic = 0; ic < " <<
fShapeW[1] <<
"; ic++) {\n";
352 out <<
SP <<
SP <<
SP <<
"for (std::size_t kd = 0; kd < " << kDepth <<
"; kd++) {\n";
354 out <<
SP <<
SP <<
SP <<
"for (std::size_t kh = 0; kh < " << kHeight <<
"; kh++) {\n";
355 out <<
SP <<
SP <<
SP <<
SP <<
"for (std::size_t kw = 0; kw < " << kWidth <<
"; kw++) {\n";
357 out <<
SP <<
SP <<
SP <<
SP <<
SP << OpName <<
"_f[oc * "
358 << ocstrideDil <<
" + ic * " << icstrideDil;
359 if (
fDim > 2) out <<
" + kd * " << dstrideDil;
360 if (
fDim > 1) out <<
" + kh * " << hstrideDil;
361 out <<
" + kw * " << wstrideDil <<
" ] = tensor_" <<
fNW <<
"[oc * " << ocstride <<
" + ic * " << icstride;
362 if (
fDim > 2) out <<
" + kd * " << dstride;
363 if (
fDim > 1) out <<
" + kh * " << hstride;
366 out <<
SP <<
SP <<
SP <<
SP <<
"}\n";
369 out <<
SP <<
SP <<
"}\n";
373 out <<
SP <<
"char " << OpName <<
"_transA = 'N';\n";
374 out <<
SP <<
"char " << OpName <<
"_transB = 'N';\n";
375 out <<
SP <<
"int " << OpName <<
"_m = " << oHeight * oWidth * oDepth <<
";\n";
378 out <<
SP <<
"int " << OpName <<
"_n = " <<
fShapeW[0] <<
";\n";
380 out <<
SP <<
"float " << OpName <<
"_alpha = 1.0;\n";
381 out <<
SP <<
"float " << OpName <<
"_beta = 0.0;\n";
384 out <<
SP <<
fType <<
" * " << OpName <<
"_xcol = fVec_" << OpName <<
"_xcol.data();\n";
387 out <<
SP <<
fType <<
" " << OpName <<
"_xcol["
393 out <<
SP <<
"for (size_t n = 0; n < " << bsize <<
"; n++) {\n";
404 std::cout <<
"TMVA SOFIE Operator Conv: asymmetric padding not supported. Assume an average padding "
413 std::cout <<
"TMVA SOFIE Operator Conv: asymmetric padding not supported. Assume an average padding " << std::endl;
420 std::cout <<
"TMVA SOFIE Operator Conv: asymmetric padding not supported. Assume an average padding " << std::endl;
426 out <<
SP <<
SP <<
"size_t out_offset = n * " <<
fShapeY[1] * oDepth * oHeight * oWidth <<
";\n";
429 out <<
SP <<
SP <<
"size_t x_offset = n * " <<
fShapeX[1] * iHeight * iWidth <<
";\n";
433 out <<
SP <<
SP <<
"TMVA::Experimental::SOFIE::UTILITY::Im2col<float>(tensor_" <<
fNX
438 <<
fShapeW[1] <<
"," << iHeight <<
"," << iWidth <<
",";
446 out <<
"," << OpName <<
"_xcol);\n\n ";
449 out <<
SP <<
SP <<
"TMVA::Experimental::SOFIE::UTILITY::Im2col_3d<float>(tensor_" <<
fNX
454 <<
fShapeW[1] <<
"," << iDepth <<
"," << iHeight <<
"," << iWidth <<
","
459 << OpName <<
"_xcol);\n\n ";
462 out <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transA, &" << OpName <<
"_transB, &" << OpName <<
"_m, &"
463 << OpName <<
"_n, &" << OpName <<
"_k, &" << OpName <<
"_alpha, " << OpName <<
"_xcol, &" << OpName
465 out <<
SP <<
SP <<
SP << OpName <<
"_f, &" << OpName <<
"_k, &" << OpName <<
"_beta, tensor_" <<
fNY
466 <<
" + out_offset, &" << OpName <<
"_m);\n";
472 out <<
SP <<
SP <<
"for (size_t g = 0; g < " <<
fAttrGroup <<
"; g++) {\n";
473 out <<
SP <<
SP <<
"size_t x_offset = n * " <<
fShapeX[1] * iDepth * iHeight * iWidth <<
" + g * "
474 <<
fShapeW[1] * iDepth * iHeight * iWidth <<
";\n ";
475 out <<
SP <<
SP <<
"size_t out_offset = n * " <<
fShapeY[1] * oDepth * oHeight * oWidth <<
" + g * "
479 out <<
SP <<
SP <<
"TMVA::Experimental::SOFIE::UTILITY::Im2col<float>(tensor_" <<
fNX
484 <<
fShapeW[1] <<
"," << iHeight <<
"," << iWidth <<
",";
492 out <<
"," << OpName <<
"_xcol);\n\n ";
495 out <<
SP <<
SP <<
"TMVA::Experimental::SOFIE::UTILITY::Im2col_3d<float>(tensor_" <<
fNX
511 out <<
SP <<
SP <<
SP <<
"size_t offset_f = g * "
514 out <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transA, &" << OpName <<
"_transB, &" << OpName <<
"_m, &"
515 << OpName <<
"_n, &" << OpName <<
"_k, &" << OpName <<
"_alpha, " << OpName <<
"_xcol, &" << OpName
517 out <<
SP <<
SP <<
SP << OpName <<
"_f + offset_f, &" << OpName <<
"_k, &" << OpName <<
"_beta, tensor_" <<
fNY
519 <<
", &" << OpName <<
"_m);\n";
521 out <<
SP <<
SP <<
"}\n";
525 out <<
SP <<
"int " << OpName <<
"_size = " <<
fShapeY[1] * oDepth * oHeight * oWidth <<
";\n";
526 out <<
SP <<
"float " << OpName <<
"_gamma = 1.0;\n";
527 out <<
SP <<
"int " << OpName <<
"_incx = 1;\n";
528 out <<
SP <<
"int " << OpName <<
"_incy = 1;\n";
530 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_size, &" << OpName <<
"_gamma, tensor_" <<
fNB2 <<
", &"
531 << OpName <<
"_incx, tensor_" <<
fNY <<
" + out_offset, &" << OpName <<
"_incy);\n";
541 std::vector<std::string>
GetBlasRoutines() {
return { std::string(
"Gemm"), std::string(
"Axpy") }; }
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 id
const ETensorType & GetTensorType(std::string name)
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< Dim > dim_shape)
bool CheckIfTensorAlreadyExist(std::string tensor_name)
const std::vector< size_t > & GetTensorShape(std::string name)
std::shared_ptr< void > GetInitializedTensorData(std::string tensor_name)
void UpdateInitializedTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
std::vector< size_t > fAttrDilations
virtual std::string GenerateSessionMembersCode(std::string opName)
void Initialize(RModel &model)
std::vector< size_t > fShapeY
std::string Generate(std::string OpName)
std::string GenerateInitCode()
std::vector< size_t > fShapeW
ROperator_Conv(std::string autopad, std::vector< size_t > dilations, size_t group, std::vector< size_t > kernelShape, std::vector< size_t > pads, std::vector< size_t > strides, std::string nameX, std::string nameW, std::string nameB, std::string nameY)
std::vector< size_t > fShapeX
std::vector< size_t > fAttrStrides
std::vector< size_t > fShapeB
std::vector< size_t > fAttrPads
ROperator_Conv(std::string autopad, std::vector< size_t > dilations, size_t group, std::vector< size_t > kernelShape, std::vector< size_t > pads, std::vector< size_t > strides, std::string nameX, std::string nameW, std::string nameY)
std::vector< std::string > GetBlasRoutines()
Returns the blas routines needed to compile the generated code.
std::vector< size_t > fAttrKernelShape
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
bool fUseSession
flag to identify if using the session class
bool AreSameShape(const std::vector< size_t > &, const std::vector< size_t > &)
std::string ConvertShapeToString(std::vector< size_t > shape)
std::size_t ConvertShapeToLength(std::vector< size_t > shape)
create variable transformations