1#ifndef TMVA_SOFIE_ROPERATOR_GEMM
2#define TMVA_SOFIE_ROPERATOR_GEMM
17namespace Experimental{
58 static_assert(std::is_same_v<T, float>,
59 "TMVA::SOFIE - Unsupported type parsing a Gemm operator");
82 if (
input.size() > 3)
throw std::runtime_error(
"TMVA SOFIE Gemm Op Shape Inference only need 2 or 3 input tensor");
87 throw std::runtime_error(
"TMVA SOFIE Gemm Op Shape Inference only accept input tensor with >=2 dimensions");
92 if (
input.size() == 3){
114 for (
size_t i = 0; i <
input[0].size()-2; i++) {
118 if (
valueB.GetVal() ==
"1")
120 else if (
valueA.GetVal() ==
"1")
123 throw std::runtime_error(
"TMVA SOFIE Gemm Op - invalid input shapes " +
valueA.GetVal() +
" and "
138 throw std::runtime_error(
"TMVA SOFIE Gemm Op - invalid input shapes " +
valueA.GetVal() +
" and "
152 std::vector<std::vector<size_t>>
ret;
166 if ((model.CheckIfTensorAlreadyExist(
fNA) ==
false) || (model.CheckIfTensorAlreadyExist(
fNB) ==
false) ){
167 throw std::runtime_error(
"TMVA SOFIE Gemm Op Input Tensor " +
fNA +
" or " +
fNB +
" is not found in model");
170 if (model.CheckIfTensorAlreadyExist(
fNC) ==
false){
171 throw std::runtime_error(
"TMVA SOFIE Gemm Op Input Tensor " +
fNC +
" is not found in model");
174 if (model.IsDynamicTensor(
fNA) || model.IsDimInputTensor(
fNA) ) {
188 if (model.IsDynamicTensor(
fNB) || model.IsDimInputTensor(
fNB)) {
218 if (model.IsDynamicTensor(
fNC))
240 if ((
r.first & 2) == 2) {
242 }
else if (
r.first == 4) {
269 && model.IsInitializedTensor(
fNA)
270 && model.IsInitializedTensor(
fNB)
271 && (
fNC.empty() || model.IsInitializedTensor(
fNC))
285 auto dataA =
static_cast<T *
>(model.GetInitializedTensorData(
fNA).get());
286 auto dataB =
static_cast<T *
>(model.GetInitializedTensorData(
fNB).get());
289 std::vector<T>
dataY(
m *
n, T(0));
290 for (
size_t i = 0; i <
m; i++) {
291 for (
size_t j = 0;
j <
n;
j++) {
293 for (
size_t p = 0;
p < k;
p++) {
303 auto dataC =
static_cast<T *
>(model.GetInitializedTensorData(
fNC).get());
304 for (
size_t idx = 0; idx <
dataY.size(); idx++)
310 v = std::max(
v, T(0));
315 model.SetNotWritableInitializedTensor(
fNA);
316 model.SetNotWritableInitializedTensor(
fNB);
318 model.SetNotWritableInitializedTensor(
fNC);
321 if (model.Verbose()) {
322 std::cout <<
"Gemm (or MatMul) " <<
fNA <<
" , " <<
fNB;
324 std::cout <<
" , " <<
fNC;
331 model.AddIntermediateTensor(
fNY, model.GetTensorType(
fNA),
shapeY);
333 model.AddDynamicTensor(
fNY, model.GetTensorType(
fNA),
fShapeY);
335 if (model.Verbose()){
336 std::cout <<
"Gemm (or MatMul) " <<
" ---> " <<
fNY <<
" shape ";
343 model.AddNeededStdLib(
"algorithm");
346 if (
fType ==
"float")
347 model.AddNeededHelperFunction(
"Gemm_Call");
350 model.AddNeededHelperFunction(
"Copy");
351 model.AddNeededHelperFunction(
"Fill");
354 model.AddNeededHelperFunction(
"Relu");
366 std::stringstream out;
379 throw std::runtime_error(
"TMVA SOFIE Gemm(MatMul) has invalid shape for inputs or output");
389 for (int64_t i = 0; i <
dimY-2; i++) {
400 for (int64_t i = 0; i <
dimC-2; i++) {
405 }
else if (
dimC > 0) {
406 for (int64_t i = 0; i <
dimC; i++) {
427 throw std::runtime_error(
"TMVA SOFIE Gemm Op " +
opName +
" Bias tensor " +
fNC +
444 std::cout <<
"WARNING: TMVA SOFIE Gemm Op " +
opName +
" Bias tensor is not present but beta value in Gemm is not zero - force it to zero\n";
480 if (
sC[0].GetVal() !=
"1" &&
sC[1].GetVal() !=
sY[1].GetVal())
481 out <<
SP <<
"if (" <<
sC[0] <<
" == 1 && " <<
sC[1] <<
" == " <<
sY[1] <<
")\n";
482 else if (
sC[0].GetVal() ==
"1")
483 out <<
SP <<
"if (" <<
sC[1] <<
" == " <<
sY[1] <<
")\n";
484 else if (
sC[1].GetVal() ==
sY[1].GetVal())
485 out <<
SP <<
"if (" <<
sC[0] <<
" == 1)\n";
490 if (
sC[1].GetVal() !=
"1" &&
sC[0].GetVal() !=
sY[0].GetVal())
491 out <<
SP <<
"else if (" <<
sC[1] <<
" == 1 && " <<
sC[0] <<
" == " <<
sY[0] <<
")\n";
492 else if (
sC[1].GetVal() ==
"1")
493 out <<
SP <<
"else if (" <<
sC[0] <<
" == " <<
sY[0] <<
")\n";
494 else if (
sC[0].GetVal() ==
sY[0].GetVal())
495 out <<
SP <<
"else if (" <<
sC[1] <<
" == 1)\n";
500 if (
sC[0].GetVal() !=
"1" &&
sC[1].GetVal() !=
"1")
501 out <<
SP <<
"else if (" <<
sC[0] <<
" == 1 && " <<
sC[1] <<
" == 1 )\n";
502 else if (
sC[0].GetVal() ==
"1")
503 out <<
SP <<
"else if (" <<
sC[1] <<
" == 1)\n";
504 else if (
sC[1].GetVal() ==
"1")
505 out <<
SP <<
"else if (" <<
sC[0] <<
" == 1)\n";
507 out <<
SP <<
"else\n";
508 out <<
SP <<
SP <<
"throw std::runtime_error(\"TMVA SOFIE Gemm Op - bias tensor "
514 out <<
SP <<
"size_t " <<
opName <<
"_y_offset = 0;\n";
516 out <<
SP <<
"size_t " <<
opName <<
"_A_offset = 0;\n";
518 out <<
SP <<
"size_t " <<
opName <<
"_B_offset = 0;\n";
520 out <<
SP <<
"size_t " <<
opName <<
"_C_offset = 0;\n";
521 out <<
SP <<
"for (size_t i = 0; i < " <<
lengthExtra_Y <<
"; i++){\n";
531 out <<
SP2 <<
"for (size_t j = 0; j < " <<
sY[0] <<
"; j++) { \n";
532 out <<
SP2 <<
SP <<
"size_t y_index = ";
534 out <<
opName <<
"_y_offset + ";
535 if (
sY[1].GetVal() !=
"1")
536 out <<
sY[1] <<
" * j;\n";
540 std::string prefix =
SP2 +
SP;
542 if (
sC.size() != 2) {
544 }
if (
sC[0].GetVal() ==
"1" &&
sC[1].GetVal() ==
sY[1].GetVal()) {
545 out << prefix <<
"Copy(" <<
target <<
" + y_index, tensor_" <<
fNC <<
", " <<
sY[1] <<
");\n";
546 }
else if (
sC[1].GetVal() ==
"1" &&
sC[0].GetVal() ==
sY[0].GetVal()) {
547 out << prefix <<
"Fill(" <<
target <<
" + y_index, tensor_" <<
fNC <<
"[j], " <<
sY[1] <<
");\n";
548 }
else if (
sC[0].GetVal() ==
"1" &&
sC[1].GetVal() ==
"1") {
550 out << prefix <<
"Fill(" <<
target <<
" + y_index, tensor_" <<
fNC <<
"[0], " <<
sY[1] <<
");\n";
556 out <<
SP << prefix <<
"Copy(" <<
target <<
" + y_index, tensor_" <<
fNC <<
", " <<
sY[1] <<
");\n";
558 out <<
SP << prefix <<
"Fill(" <<
target <<
" + y_index, tensor_" <<
fNC <<
"[j], " <<
sY[1] <<
");\n";
559 out <<
SP2 <<
SP <<
"else \n";
560 out <<
SP << prefix <<
"Fill(" <<
target <<
" + y_index, tensor_" <<
fNC <<
"[0], " <<
sY[1] <<
");\n";
568 if (
fType ==
"float"){
570 out <<
SP2 <<
"Gemm_Call(" <<
"tensor_" <<
fNY;
575 <<
n <<
", " <<
m <<
", " << k <<
", ";
576 out << std::setprecision(std::numeric_limits<float>::max_digits10) <<
fAttrAlpha <<
", tensor_" <<
fNB;
578 out <<
", tensor_" <<
fNA;
580 out <<
", " << std::setprecision(std::numeric_limits<float>::max_digits10) <<
fAttrBeta <<
",";
583 out <<
"tensor_" <<
fNC;
585 out <<
" + " <<
opName <<
"_C_offset";
608 out <<
SP <<
"//--- applying RELU to output\n";
609 std::string
tnsr =
"tensor_" +
fNY;
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.
winID h TVirtualViewer3D TVirtualGLPainter p
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 Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t target
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 r
const_iterator begin() const
const_iterator end() const
const std::vector< std::string > & GetDimShapeNames() const
ROperator_Gemm(float alpha, float beta, int_t transA, int_t transB, std::string nameA, std::string nameB, std::string nameC, std::string nameY, EActivationType activation=EActivationType::UNDEFINED)
std::vector< Dim > DynamicShapeInference(const std::vector< std::vector< Dim > > &input)
std::vector< Dim > fShapeY
std::vector< ETensorType > TypeInference(std::vector< ETensorType > input) override
ROperator_Gemm(float alpha, float beta, int_t transA, int_t transB, std::string nameA, std::string nameB, std::string nameY, EActivationType activation=EActivationType::UNDEFINED)
std::vector< std::vector< size_t > > ShapeInference(std::vector< std::vector< size_t > > input) override
std::vector< U > DoShapeInference(const std::vector< std::vector< U > > &input)
std::vector< Dim > fShapeA
std::vector< Dim > fShapeB
std::vector< size_t > fShapeC
std::string Generate(std::string opName) override
void Initialize(RModel &model) override
std::vector< Dim > fDimShapeC
bool fBiasBroadcastAssumed
bool fCheckBiasShapeAtRuntime
EActivationType fActivation
std::vector< std::string > GetBlasRoutines() override
std::vector< std::string_view > fInputTensorNames
bool fIsOutputConstant
flag to identify if operator has a constant output (no need to generate code)
const std::string SP
space used to correctly indent the generated C++ code
std::vector< std::string_view > fOutputTensorNames
std::vector< size_t > MultidirectionalBroadcastShape(std::vector< std::vector< size_t > >)
std::string ConvertDimShapeToString(const std::vector< Dim > &shape)
std::vector< Dim > ConvertShapeToDim(const std::vector< size_t > &shape)
Convert shape from integer format to dynamic one (based on Dim)
std::vector< size_t > ConvertShapeToInt(const std::vector< Dim > &shape)
Convert shape based on Dim to integer format.
std::string ConvertDimShapeToLength(const std::vector< Dim > &shape)
std::string ConvertShapeToString(const std::vector< size_t > &shape)
create variable transformations
static uint64_t sum(uint64_t i)