2#include "onnx_proto3.pb.h"
9#include <unordered_map>
14namespace Experimental {
152 std::vector<std::string> ops;
155 ops.emplace_back(it.first);
176std::unique_ptr<ROperator>
179 int idx = (nodes.size() > i) ? nodes[i] : (
int)i;
180 const auto &nodeproto = graphproto.node(idx);
181 const std::string op_type = nodeproto.op_type();
183 std::cout <<
"Parsing an operator " << op_type << std::endl;
186 if (op_type ==
"MatMul") {
188 int idx2 = (nodes.size() > i + 1) ? nodes[i + 1] : (
int)i + 1;
189 if (idx2 < graphproto.node_size() && graphproto.node(idx2).op_type() ==
"Add") {
192 else if(graphproto.node(idx2).op_type() !=
"Add"){
195 }
else if (nodeproto.op_type() ==
"Conv" || nodeproto.op_type() ==
"ConvTranspose") {
197 int j = (nodes.size() > i + 1) ? nodes[i + 1] : (
int)i + 1;
198 if (j < graphproto.node_size() && graphproto.node(j).op_type() ==
"Add") {
199 if (nodeproto.op_type() ==
"Conv") {
208 if (idx > 0 && op_type ==
"Add") {
209 int idx0 = (nodes.size() > i) ? nodes[i - 1] : (
int)i - 1;
210 if (graphproto.node(idx0).op_type() ==
"MatMul")
212 else if (graphproto.node(idx0).op_type() ==
"ConvTranspose")
218 throw std::runtime_error(
"TMVA::SOFIE Operator type " + op_type +
" is not yet supported");
221 std::cout <<
"\tCreating operator " << op_type << std::endl;
223 return it->second(*
this, nodeproto);
235 std::string filename_nodir =
filename;
236 if (isep != std::string::npos) {
240 std::time_t ttime = std::time(0);
241 std::tm *gmt_time = std::gmtime(&ttime);
242 std::string parsetime(std::asctime(gmt_time));
244 GOOGLE_PROTOBUF_VERIFY_VERSION;
246 onnx::ModelProto model;
247 RModel rmodel(filename_nodir, parsetime);
251 std::fstream
input(
filename, std::ios::in | std::ios::binary);
252 if (!model.ParseFromIstream(&
input)) {
253 throw std::runtime_error(
"TMVA::SOFIE - Failed to parse onnx file " +
filename);
256 const onnx::GraphProto &
graph = model.graph();
257 google::protobuf::ShutdownProtobufLibrary();
261 std::cout <<
"ONNX Version " << model.ir_version() << std::endl;
264 std::unordered_set<std::string> initializer_names;
265 for (
int i = 0; i <
graph.initializer_size(); i++) {
266 initializer_names.insert(
graph.initializer(i).name());
270 std::cout <<
"Parsing model inputs...." << std::endl;
272 for (
int i = 0; i <
graph.input_size(); i++) {
277 std::cout <<
"\tgraph input " << i <<
" name " <<
graph.input(i).name() <<
" type "
278 <<
graph.input(i).type().tensor_type().elem_type() << std::endl;
280 if (initializer_names.find(
graph.input(i).name()) != initializer_names.end())
284 const onnx::ValueInfoProto &valueinfoproto =
graph.input(i);
285 std::string input_name = valueinfoproto.name();
289 throw std::runtime_error(
"TMVA::SOFIE Data type in input tensor " + input_name +
" not supported!\n");
293 bool existParam =
false;
294 if (!valueinfoproto.type().tensor_type().has_shape())
295 throw std::runtime_error(
"TMVA::SOFIE datanode with no shape restrictions is not supported yet");
296 for (
int j = 0; j < valueinfoproto.type().tensor_type().shape().dim_size(); j++) {
298 if (valueinfoproto.type().tensor_type().shape().dim(j).value_case() ==
299 onnx::TensorShapeProto_Dimension::ValueCase::kDimValue) {
300 dim.
dim = valueinfoproto.type().tensor_type().shape().dim(j).dim_value();
301 }
else if (valueinfoproto.type().tensor_type().shape().dim(j).value_case() ==
302 onnx::TensorShapeProto_Dimension::ValueCase::kDimParam) {
305 dim.
param = valueinfoproto.type().tensor_type().shape().dim(j).dim_param();
307 throw std::runtime_error(
"TMVA::SOFIE ONNX file error: Valueinfoproto " + input_name +
308 " has neither dim_value nor dim_param! \n");
312 if (valueinfoproto.type().tensor_type().shape().dim_size() == 0) {
319 std::vector<size_t> fShape_sizet;
321 fShape_sizet.push_back(j.dim);
331 std::map<std::string, int> allInitializedTensors;
334 std::cout <<
"\nParsing graph initializer list and fill model initialized tensors" << std::endl;
336 for (
int i = 0; i <
graph.initializer_size(); i++) {
337 onnx::TensorProto *tensorproto =
const_cast<onnx::TensorProto *
>(&
graph.initializer(i));
338 std::vector<std::size_t> shape;
339 std::size_t fLength = 1;
340 for (
int j = 0; j < tensorproto->dims_size(); j++) {
341 shape.push_back(tensorproto->dims(j));
342 fLength *= tensorproto->dims(j);
346 std::string input_name =
graph.initializer(i).name();
349 std::cout <<
"\t initializer " << i <<
" name " << input_name <<
" type " <<
graph.initializer(i).data_type()
354 std::shared_ptr<void>
data(
malloc(fLength *
sizeof(
float)),
free);
356 if (tensorproto->raw_data().empty() ==
false) {
357 auto raw_data_ptr =
reinterpret_cast<float *
>(
const_cast<char *
>(tensorproto->raw_data().c_str()));
358 std::memcpy(
data.get(), raw_data_ptr, fLength *
sizeof(
float));
360 tensorproto->mutable_float_data()->ExtractSubrange(0, tensorproto->float_data_size(),
361 static_cast<float *
>(
data.get()));
364 if (verbose) std::cout <<
"add FLOAT initialized tensor " << input_name <<
" shape " <<
ConvertShapeToString(shape) << std::endl;
366 allInitializedTensors[input_name] = i;
370 std::shared_ptr<void>
data(
malloc(fLength *
sizeof(int64_t)),
free);
372 if (tensorproto->raw_data().empty() ==
false) {
373 auto raw_data_ptr =
reinterpret_cast<int64_t *
>(
const_cast<char *
>(tensorproto->raw_data().c_str()));
374 std::memcpy(
data.get(), raw_data_ptr, fLength *
sizeof(int64_t));
376 tensorproto->mutable_int64_data()->ExtractSubrange(0, tensorproto->int64_data_size(),
377 static_cast<int64_t *
>(
data.get()));
380 if (verbose) std::cout <<
"add INT64 initialized tensor " << input_name <<
" shape " <<
ConvertShapeToString(shape) << std::endl;
382 allInitializedTensors[input_name] = i;
386 throw std::runtime_error(
"Data type in weight tensor " +
graph.initializer(i).name() +
" not supported!\n");
392 std::cout <<
"\nGraph operator list (ONNX order)\n";
393 for (
int i = 0; i <
graph.node_size(); i++) {
394 std::cout <<
"\tOperator " << i <<
" : " <<
graph.node(i).op_type() <<
" , " <<
graph.node(i).input_size()
396 for (
int j = 0; j <
graph.node(i).input_size(); j++) {
397 std::cout <<
graph.node(i).input(j);
398 if (j <
graph.node(i).input_size() - 1)
401 std::cout <<
" }" << std::endl;
407 std::cout <<
"\nRe-Order graph operator list\n";
408 std::vector<size_t> nodesOrder;
409 nodesOrder.reserve(
graph.node_size());
410 std::vector<bool> foundNodes(
graph.node_size());
412 std::map<std::string, int> allInputs;
413 for (
int i = 0; i <
graph.input_size(); i++) {
414 allInputs[
graph.input(i).name()] = -1;
417 auto psize = nodesOrder.size();
418 for (
int i = 0; i <
graph.node_size(); i++) {
422 bool existInputs =
true;
423 int input_size =
graph.node(i).input_size();
425 for (
int j = 0; j < input_size; j++) {
426 std::string
name =
graph.node(i).input(j);
429 existInputs &= (allInputs.find(
name) != allInputs.end() ||
430 allInitializedTensors.find(
name) != allInitializedTensors.end());
432 std::cout <<
graph.node(i).op_type() <<
" input " <<
name <<
" "
433 <<
bool(allInputs.find(
name) != allInputs.end()) <<
" " <<
434 bool(allInitializedTensors.find(
name) != allInitializedTensors.end()) <<
435 existInputs << std::endl;
441 std::cout <<
"skip op " <<
graph.node(i).op_type() <<
" inputs are ";
442 for (
int j = 0; j < input_size; j++) {
443 std::cout <<
graph.node(i).input(j) <<
" ";
445 std::cout << std::endl;
450 std::cout <<
"\tadd node " <<
graph.node(i).op_type() <<
" order " << i << std::endl;
452 nodesOrder.push_back(i);
453 foundNodes[i] =
true;
455 for (
int j = 0; j <
graph.node(i).output_size(); j++) {
456 allInputs[
graph.node(i).output(j)] = i;
460 if (nodesOrder.size() == psize) {
461 throw std::runtime_error(
"TMVA::SOFIE - cannot find a new node ");
463 }
while ((
int)nodesOrder.size() <
graph.node_size());
467 std::cout <<
"\nGraph operator list (re-ordered)\n";
468 for (
int k = 0; k <
graph.node_size(); k++) {
469 int i = nodesOrder[k];
470 std::cout <<
"\tOperator " << i <<
" : " <<
graph.node(i).op_type() <<
" , " <<
graph.node(i).input_size()
472 for (
int j = 0; j <
graph.node(i).input_size(); j++) {
473 std::cout <<
graph.node(i).input(j);
474 if (j <
graph.node(i).input_size() - 1)
477 std::cout <<
" }" << std::endl;
483 std::cout <<
"Fill RModel with operators...\n";
485 for (
int i = 0; i <
graph.node_size(); i++) {
486 std::string op_type =
graph.node(nodesOrder[i]).op_type();
489 std::cout <<
"\t" << i <<
" " << nodesOrder[i] <<
" parsing operator " << op_type << std::endl;
495 std::cout <<
"\t\tskipping operator since it is fused with previous one" << std::endl;
503 std::vector<std::string> outputnames;
505 std::cout <<
"\nParsing Graph output list\n";
506 for (
int i = 0; i <
graph.output_size(); i++) {
508 std::cout <<
"\toutput " << i <<
" name " <<
graph.output(i).name() << std::endl;
509 outputnames.push_back(
graph.output(i).name());
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
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 filename
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 Atom_t Time_t type
void RegisterOperator(const std::string &name, ParserFuncSignature func)
bool IsRegisteredOperator(const std::string &name)
RModelParser_ONNX() noexcept
std::unordered_map< std::string, ETensorType > fTensorTypeMap
RModel Parse(std::string filename, bool verbose=false)
bool IsRegisteredTensorType(const std::string &)
std::unique_ptr< ROperator > ParseOperator(const size_t, const onnx::GraphProto &, const std::vector< size_t > &)
void RegisterTensorType(const std::string &, ETensorType)
ETensorType GetTensorType(const std::string &name)
std::vector< std::string > GetRegisteredOperators()
std::unique_ptr< OperatorsMapImpl > fOperatorsMapImpl
void AddOutputTensorNameList(std::vector< std::string > outputtensornames)
void AddInputTensorInfo(std::string input_name, ETensorType type, std::vector< Dim > shape)
void AddInitializedTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
void AddInputTensorName(std::string name)
void AddOperator(std::unique_ptr< ROperator > op, int order_execution=-1)
std::string Clean_name(std::string input_tensor_name)
std::function< std::unique_ptr< ROperator >(RModelParser_ONNX &, const onnx::NodeProto &, const onnx::NodeProto &)> ParserFuseFuncSignature
ParserFuncSignature ParseSqrt
ParserFuncSignature ParseBatchNormalization
ParserFuncSignature ParseReshape
ParserFuseFuncSignature ParseFuseConvTransposeAdd
ParserFuncSignature ParseReduceMean
ParserFuseFuncSignature ParseFuseMatMulAdd
ParserFuncSignature ParseGather
ParserFuncSignature ParseNeg
ParserFuncSignature ParseLog
ParserFuncSignature ParseLeakyRelu
ParserFuncSignature ParseExp
ParserFuncSignature ParsePool
ParserFuncSignature ParseDiv
ParserFuncSignature ParseLayerNormalization
ParserFuncSignature ParseConcat
ParserFuncSignature ParseMax
ParserFuncSignature ParseIdentity
ParserFuncSignature ParseConvTranspose
ParserFuncSignature ParseReduceProd
ParserFuncSignature ParseSlice
ParserFuncSignature ParseTranspose
ParserFuncSignature ParseShape
ParserFuncSignature ParseGRU
ParserFuncSignature ParseMatMul
ParserFuncSignature ParseErf
ParserFuncSignature ParseSub
ParserFuncSignature ParseReduceSumsquare
ParserFuncSignature ParseAdd
ParserFuncSignature ParseExpand
ParserFuncSignature ParseRNN
std::function< std::unique_ptr< ROperator >(RModelParser_ONNX &, const onnx::NodeProto &)> ParserFuncSignature
ParserFuncSignature ParseLSTM
ParserFuncSignature ParseCast
ParserFuncSignature ParseReciprocal
std::string ConvertShapeToString(std::vector< size_t > shape)
ParserFuncSignature ParseSigmoid
ParserFuseFuncSignature ParseFuseConvAdd
ParserFuncSignature ParseSoftmax
ParserFuncSignature ParseMean
ParserFuncSignature ParseSelu
ParserFuncSignature ParseSum
ParserFuncSignature ParseMin
ParserFuncSignature ParseRelu
ParserFuncSignature ParseConv
ParserFuncSignature ParseGemm
ParserFuncSignature ParseMul
ParserFuncSignature ParsePow
ParserFuncSignature ParseTanh
create variable transformations
std::unordered_map< std::string, ParserFuncSignature > fOperatorsMap