16#ifndef TMVA_RSOFIEREADER
17#define TMVA_RSOFIEREADER
34namespace Experimental {
55 void Load(
const std::string &path, std::vector<std::vector<size_t>>
inputShapes = {},
int verbose = 0)
58 auto pos2 = path.find(
".onnx");
59 if (
pos2 == std::string::npos) {
60 throw std::runtime_error(
"Input file is not an ONNX file");
62 auto pos1 = path.rfind(
"/");
63 if (
pos1 == std::string::npos)
69 if (verbose) std::cout <<
"Parsing SOFIE model " << modelName <<
" of type " <<
fileType << std::endl;
72 std::string
modelHeader = modelName +
"_fromRSofieR.hxx";
73 std::string
modelWeights = modelName +
"_fromRSofieR.dat";
81 throw std::runtime_error(
"RSofieReader: cannot use SOFIE with ONNX since libROOTTMVASofieParser is missing");
83 gInterpreter->Declare(
"#include \"TMVA/RModelParser_ONNX.hxx\"");
84 parserCode +=
"{\nTMVA::Experimental::SOFIE::RModelParser_ONNX parser ; \n";
86 parserCode +=
"TMVA::Experimental::SOFIE::RModel model = parser.Parse(\"" + path +
"\",true); \n";
88 parserCode +=
"TMVA::Experimental::SOFIE::RModel model = parser.Parse(\"" + path +
"\"); \n";
93 parserCode +=
"{ auto p = new TMVA::Experimental::SOFIE::ROperator_Custom<float>(\""
94 +
op.fOpName +
"\"," +
op.fInputNames +
"," +
op.fOutputNames +
"," +
op.fOutputShapes +
",\"" +
op.fFileName +
"\");\n";
95 parserCode +=
"std::unique_ptr<TMVA::Experimental::SOFIE::ROperator> op(p);\n";
96 parserCode +=
"model.AddOperator(std::move(op));\n}\n";
103 if (batchSize < 1) batchSize = 1;
105 if (verbose) std::cout <<
"generating the code with batch size = " << batchSize <<
" ...\n";
107 parserCode +=
"model.Generate(TMVA::Experimental::SOFIE::Options::kDefault,"
112 parserCode +=
"model.PrintRequiredInputTensors();\n";
113 parserCode +=
"model.PrintIntermediateTensors();\n";
114 parserCode +=
"model.PrintOutputTensors();\n";
120 parserCode +=
"int nInputs = model.GetInputTensorNames().size();\n";
127 std::cout <<
"...ParserCode being executed...:\n";
134 std::string
msg =
"RSofieReader: error processing the parser code: \n" +
parserCode;
135 throw std::runtime_error(
msg);
136 }
else if (verbose) {
137 std::cout <<
"Model Header file is generated!" << std::endl;
140 throw std::runtime_error(
"RSofieReader does not yet support model with > 3 inputs");
144 if (verbose) std::cout <<
"compile generated code from file " <<
modelHeader << std::endl;
146 std::string
msg =
"RSofieReader: input header file " +
modelHeader +
" is not existing";
147 throw std::runtime_error(
msg);
149 if (verbose) std::cout <<
"Creating Inference function for model " << modelName << std::endl;
151 declCode +=
"#pragma cling optimize(2)\n";
158 [](
char const&
c ) ->
bool { return !std::isalnum(c); } ),
uidName.
end());
163 if (verbose) std::cout <<
"//global session declaration\n" <<
declCode << std::endl;
168 throw std::runtime_error(
"Error loading libROOTTMVASofie library");
172 std::string
msg =
"RSofieReader: error compiling inference code and creating session class\n" +
declCode;
173 throw std::runtime_error(
msg);
180 std::string funcName =
"SofieInference_" +
uidName;
181 ifuncCode <<
"std::vector<float> " + funcName +
"( void * ptr";
187 for (
int i = 0; i <
fNInputs; i++) {
194 if (verbose) std::cout <<
"//Inference function code using global session instance\n"
199 std::string
msg =
"RSofieReader: error compiling inference function\n" +
ifuncCode.str();
200 throw std::runtime_error(
msg);
209 const std::string &
outputShapes,
const std::string & fileName) {
210 if (
fInitialized) std::cout <<
"WARNING: Model is already loaded and initialised. It must be done after adding the custom operators" << std::endl;
217 std::string
msg =
"Wrong number of inputs - model requires " + std::to_string(
fNInputs);
218 throw std::runtime_error(
msg);
220 auto fptr =
reinterpret_cast<std::vector<float> (*)(
void *,
const float *)
>(
fFuncPtr);
223 std::vector<float>
DoCompute(
const std::vector<float> &
x1,
const std::vector<float> &
x2) {
225 std::string
msg =
"Wrong number of inputs - model requires " + std::to_string(
fNInputs);
226 throw std::runtime_error(
msg);
228 auto fptr =
reinterpret_cast<std::vector<float> (*)(
void *,
const float *,
const float *)
>(
fFuncPtr);
231 std::vector<float>
DoCompute(
const std::vector<float> &
x1,
const std::vector<float> &
x2,
const std::vector<float> &
x3) {
233 std::string
msg =
"Wrong number of inputs - model requires " + std::to_string(
fNInputs);
234 throw std::runtime_error(
msg);
236 auto fptr =
reinterpret_cast<std::vector<float> (*)(
void *,
const float *,
const float *,
const float *)
>(
fFuncPtr);
241 template<
typename... T>
245 return std::vector<float>();
255 std::vector<float>
Compute(
const std::vector<float> &
x) {
257 return std::vector<float>();
275 const auto nrows =
x.GetShape()[0];
276 const auto rowsize =
x.GetStrides()[0];
277 auto fptr =
reinterpret_cast<std::vector<float> (*)(
void *,
const float *)
>(
fFuncPtr);
284 for (
size_t i = 1; i <
nrows; i++) {
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 char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t result
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
R__EXTERN TSystem * gSystem
#define R__WRITE_LOCKGUARD(mutex)
const_iterator begin() const
const_iterator end() const
TMVA::RSofieReader class for reading external Machine Learning models in ONNX files and performing th...
RSofieReader(const std::string &path, std::vector< std::vector< size_t > > inputShapes={}, int verbose=0)
Create TMVA model from ONNX file print level can be 0 (minimal) 1 with info , 2 with all ONNX parsing...
RTensor< float > Compute(RTensor< float > &x)
Compute model prediction on input RTensor The shape of the input tensor should be {nevents,...
std::vector< float > Compute(const std::vector< float > &x)
std::vector< float > Compute(T... x)
Compute model prediction on vector.
void Load(const std::string &path, std::vector< std::vector< size_t > > inputShapes={}, int verbose=0)
std::vector< float > DoCompute(const std::vector< float > &x1, const std::vector< float > &x2, const std::vector< float > &x3)
std::vector< CustomOperatorData > fCustomOperators
std::vector< float > DoCompute(const std::vector< float > &x1)
void AddCustomOperator(const std::string &opName, const std::string &inputNames, const std::string &outputNames, const std::string &outputShapes, const std::string &fileName)
std::vector< float > DoCompute(const std::vector< float > &x1, const std::vector< float > &x2)
RSofieReader()
Dummy constructor which needs model loading afterwards.
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
This class defines a UUID (Universally Unique IDentifier), also known as GUIDs (Globally Unique IDent...
const char * AsString() const
Return UUID as string. Copy string immediately since it will be reused.
std::string ToString(const T &val)
Utility function for conversion to strings.
R__EXTERN TVirtualRWMutex * gCoreMutex
modelName
Step 2 : Parse model and generate inference code with SOFIE.
create variable transformations
std::string fOutputShapes