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");
83 std::vector<ETensorType>
TypeInference(std::vector<ETensorType> input) {
89 std::vector<std::vector<size_t>>
ShapeInference(std::vector<std::vector<size_t>> input) {
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");
228 if (broadcast_needed) {
232 throw std::runtime_error(
"TMVA SOFIE Conv op: Bias Tensor has empty shape");
236 throw std::runtime_error(
"TMVA SOFIE Conv op: Bias Tensor has wrong shape: " +
238 if (
fType !=
"float")
239 throw std::runtime_error(
"TMVA SOFIE Conv op: Broadcasting for non-float type tensors is not supported");
246 std::shared_ptr<void> new_data_ptr(
247 UTILITY::Unidirectional_broadcast<float>(
static_cast<float *
>(original_data.get()),
fShapeB,
fShapeY),
248 std::default_delete<
float[]>());
269 std::stringstream out;
275 out <<
" std::vector<size_t> newShape = { " <<
fShapeY[1] <<
", ";
276 if (
fDim > 2) out << oDepth <<
", ";
277 if (
fDim > 1) out << oHeight <<
", ";
278 out << oWidth <<
"};\n";
279 out <<
" oldShape.resize(newShape.size(), 1.);\n";
280 std::string original_bias_tensor =
"tensor_" +
fNB;
281 std::string new_bias_tensor =
"tensor_" +
fNB2;
282 out <<
" float * newData_ptr = TMVA::Experimental::SOFIE::UTILITY::Unidirectional_broadcast<float>("
283 << original_bias_tensor <<
", oldShape, newShape);\n";
285 int length =
fShapeY[1]*oDepth*oHeight*oWidth;
286 out <<
" for (int i = 0; i < " <<
fShapeY[0] <<
" ; i++)\n";
287 out <<
" std::copy(newData_ptr, newData_ptr + " << length <<
", "
288 << new_bias_tensor <<
" + i * " << length <<
");\n";
289 out <<
" delete [] newData_ptr;\n";
298 size_t outputChannelSize =
fShapeY[2];
300 for (
size_t i = 1; i <
fDim; i++) {
301 outputChannelSize *=
fShapeY[2 + i];
305 opName =
"op_" + opName;
306 std::stringstream out;
308 out <<
"std::vector<" <<
fType <<
"> fVec_" << opName <<
"_f = std::vector<" <<
fType <<
">("
311 out <<
"std::vector<" <<
fType <<
"> fVec_" << opName <<
"_xcol = std::vector<" <<
fType <<
">("
312 <<
fShapeW[1] * kernelSize * outputChannelSize <<
");\n";
319 OpName =
"op_" + OpName;
323 std::runtime_error(
"TMVA SOFIE Conv Op called to Generate without being initialized first");
326 std::stringstream out;
338 out <<
"\n//---- operator Conv " << OpName <<
"\n";
342 out <<
SP <<
fType <<
" * " << OpName <<
"_f = fVec_" << OpName <<
"_f.data();\n";
350 size_t id = (
fDim > 2) ?
fDim-3 : 2;
351 size_t ih = (
fDim > 1) ?
fDim-2 : 1;
355 size_t hstride = kWidth;
357 size_t dstride = kHeight * kWidth;
359 size_t icstride = kHeight * kWidth * kDepth;
361 size_t ocstride =
fShapeW[1] * icstride;
362 size_t ocstrideDil =
fShapeW[1] * icstrideDil;
364 out <<
SP <<
"for (std::size_t oc = 0; oc < " <<
fShapeW[0] <<
"; oc++) {\n";
365 out <<
SP <<
SP <<
"for (std::size_t ic = 0; ic < " <<
fShapeW[1] <<
"; ic++) {\n";
367 out <<
SP <<
SP <<
SP <<
"for (std::size_t kd = 0; kd < " << kDepth <<
"; kd++) {\n";
369 out <<
SP <<
SP <<
SP <<
"for (std::size_t kh = 0; kh < " << kHeight <<
"; kh++) {\n";
370 out <<
SP <<
SP <<
SP <<
SP <<
"for (std::size_t kw = 0; kw < " << kWidth <<
"; kw++) {\n";
372 out <<
SP <<
SP <<
SP <<
SP <<
SP << OpName <<
"_f[oc * "
373 << ocstrideDil <<
" + ic * " << icstrideDil;
374 if (
fDim > 2) out <<
" + kd * " << dstrideDil;
375 if (
fDim > 1) out <<
" + kh * " << hstrideDil;
376 out <<
" + kw * " << wstrideDil <<
" ] = tensor_" <<
fNW <<
"[oc * " << ocstride <<
" + ic * " << icstride;
377 if (
fDim > 2) out <<
" + kd * " << dstride;
378 if (
fDim > 1) out <<
" + kh * " << hstride;
381 out <<
SP <<
SP <<
SP <<
SP <<
"}\n";
384 out <<
SP <<
SP <<
"}\n";
388 out <<
SP <<
"char " << OpName <<
"_transA = 'N';\n";
389 out <<
SP <<
"char " << OpName <<
"_transB = 'N';\n";
390 out <<
SP <<
"int " << OpName <<
"_m = " << oHeight * oWidth * oDepth <<
";\n";
393 out <<
SP <<
"int " << OpName <<
"_n = " <<
fShapeW[0] <<
";\n";
395 out <<
SP <<
"float " << OpName <<
"_alpha = 1.0;\n";
396 out <<
SP <<
"float " << OpName <<
"_beta = 0.0;\n";
399 out <<
SP <<
fType <<
" * " << OpName <<
"_xcol = fVec_" << OpName <<
"_xcol.data();\n";
402 out <<
SP <<
fType <<
" " << OpName <<
"_xcol["
408 out <<
SP <<
"for (size_t n = 0; n < " << bsize <<
"; n++) {\n";
419 std::cout <<
"TMVA SOFIE Operator Conv: asymmetric padding not supported. Assume an average padding "
428 std::cout <<
"TMVA SOFIE Operator Conv: asymmetric padding not supported. Assume an average padding " << std::endl;
435 std::cout <<
"TMVA SOFIE Operator Conv: asymmetric padding not supported. Assume an average padding " << std::endl;
442 out <<
SP <<
SP <<
"size_t x_offset = n * " <<
fShapeX[1] * iHeight * iWidth <<
";\n";
443 out <<
SP <<
SP <<
"size_t out_offset = n * " <<
fShapeY[1] * oHeight * oWidth <<
";\n";
447 out <<
SP <<
SP <<
"TMVA::Experimental::SOFIE::UTILITY::Im2col<float>(tensor_" <<
fNX
452 <<
fShapeW[1] <<
"," << iHeight <<
"," << iWidth <<
",";
460 out <<
"," << OpName <<
"_xcol);\n\n ";
463 out <<
SP <<
SP <<
"TMVA::Experimental::SOFIE::UTILITY::Im2col_3d<float>(tensor_" <<
fNX
468 <<
fShapeW[1] <<
"," << iDepth <<
"," << iHeight <<
"," << iWidth <<
","
473 << OpName <<
"_xcol);\n\n ";
476 out <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transA, &" << OpName <<
"_transB, &" << OpName <<
"_m, &"
477 << OpName <<
"_n, &" << OpName <<
"_k, &" << OpName <<
"_alpha, " << OpName <<
"_xcol, &" << OpName
479 out <<
SP <<
SP <<
SP << OpName <<
"_f, &" << OpName <<
"_k, &" << OpName <<
"_beta, tensor_" <<
fNY
480 <<
" + out_offset, &" << OpName <<
"_m);\n";
485 out <<
SP <<
SP <<
"size_t out_offset = n * " <<
fShapeY[1] * oDepth * oHeight * oWidth <<
";\n";
486 out <<
SP <<
SP <<
"for (size_t g = 0; g < " <<
fAttrGroup <<
"; g++) {\n";
487 out <<
SP <<
SP <<
"size_t x_offset = n * " <<
fShapeX[1] * iDepth * iHeight * iWidth <<
" + g * "
488 <<
fShapeW[1] * iDepth * iHeight * iWidth <<
";\n ";
489 out <<
SP <<
SP <<
"size_t out_offset = n * " <<
fShapeY[1] * oDepth * oHeight * oWidth <<
" + g * "
493 out <<
SP <<
SP <<
"TMVA::Experimental::SOFIE::UTILITY::Im2col<float>(tensor_" <<
fNX
498 <<
fShapeW[1] <<
"," << iHeight <<
"," << iWidth <<
",";
506 out <<
"," << OpName <<
"_xcol);\n\n ";
509 out <<
SP <<
SP <<
"TMVA::Experimental::SOFIE::UTILITY::Im2col_3d<float>(tensor_" <<
fNX
525 out <<
SP <<
SP <<
SP <<
"size_t offset_f = g * "
528 out <<
SP <<
SP <<
"BLAS::sgemm_(&" << OpName <<
"_transA, &" << OpName <<
"_transB, &" << OpName <<
"_m, &"
529 << OpName <<
"_n, &" << OpName <<
"_k, &" << OpName <<
"_alpha, " << OpName <<
"_xcol, &" << OpName
531 out <<
SP <<
SP <<
SP << OpName <<
"_f + offset_f, &" << OpName <<
"_k, &" << OpName <<
"_beta, tensor_" <<
fNY
533 <<
", &" << OpName <<
"_m);\n";
535 out <<
SP <<
SP <<
"}\n";
542 out <<
SP <<
"int " << OpName <<
"_size = " <<
fShapeY[0] *
fShapeY[1] * oDepth * oHeight * oWidth <<
";\n";
543 out <<
SP <<
"float " << OpName <<
"_gamma = 1.0;\n";
544 out <<
SP <<
"int " << OpName <<
"_incx = 1;\n";
545 out <<
SP <<
"int " << OpName <<
"_incy = 1;\n";
547 out <<
SP <<
"BLAS::saxpy_(&" << OpName <<
"_size, &" << OpName <<
"_gamma, tensor_" <<
fNB2 <<
", &"
548 << OpName <<
"_incx, tensor_" <<
fNY <<
", &" << OpName <<
"_incy);\n";
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
const ETensorType & GetTensorType(std::string name)
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > 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< 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
std::string ConvertShapeToString(std::vector< size_t > shape)
create variable transformations