2#include "onnx_proto3.pb.h"
9#include <unordered_map>
14namespace Experimental {
146 std::vector<std::string> ops;
149 ops.emplace_back(it.first);
170std::unique_ptr<ROperator>
173 int idx = (nodes.size() > i) ? nodes[i] : (
int)i;
174 const auto &nodeproto = graphproto.node(idx);
175 const std::string op_type = nodeproto.op_type();
177 std::cout <<
"Parsing an operator " << op_type << std::endl;
180 if (op_type ==
"MatMul") {
182 int idx2 = (nodes.size() > i + 1) ? nodes[i + 1] : (
int)i + 1;
183 if (idx2 < graphproto.node_size() && graphproto.node(idx2).op_type() ==
"Add") {
186 }
else if (nodeproto.op_type() ==
"Conv" || nodeproto.op_type() ==
"ConvTranspose") {
188 int j = (nodes.size() > i + 1) ? nodes[i + 1] : (
int)i + 1;
189 if (j < graphproto.node_size() && graphproto.node(j).op_type() ==
"Add") {
190 if (nodeproto.op_type() ==
"Conv") {
199 if (idx > 0 && op_type ==
"Add") {
200 int idx0 = (nodes.size() > i) ? nodes[i - 1] : (
int)i - 1;
201 if (graphproto.node(idx0).op_type() ==
"MatMul")
203 else if (graphproto.node(idx0).op_type() ==
"ConvTranspose")
209 throw std::runtime_error(
"TMVA::SOFIE Operator type " + op_type +
" is not yet supported");
212 std::cout <<
"\tCreating operator " << op_type << std::endl;
214 return it->second(*
this, nodeproto);
226 std::string filename_nodir =
filename;
227 if (isep != std::string::npos) {
231 std::time_t ttime = std::time(0);
232 std::tm *gmt_time = std::gmtime(&ttime);
233 std::string parsetime(std::asctime(gmt_time));
235 GOOGLE_PROTOBUF_VERIFY_VERSION;
237 onnx::ModelProto model;
238 RModel rmodel(filename_nodir, parsetime);
242 std::fstream
input(
filename, std::ios::in | std::ios::binary);
243 if (!model.ParseFromIstream(&
input)) {
244 throw std::runtime_error(
"TMVA::SOFIE - Failed to parse onnx file " +
filename);
247 const onnx::GraphProto &
graph = model.graph();
248 google::protobuf::ShutdownProtobufLibrary();
252 std::cout <<
"ONNX Version " << model.ir_version() << std::endl;
255 std::unordered_set<std::string> initializer_names;
256 for (
int i = 0; i <
graph.initializer_size(); i++) {
257 initializer_names.insert(
graph.initializer(i).name());
261 std::cout <<
"Parsing model inputs...." << std::endl;
263 for (
int i = 0; i <
graph.input_size(); i++) {
268 std::cout <<
"\tgraph input " << i <<
" name " <<
graph.input(i).name() <<
" type "
269 <<
graph.input(i).type().tensor_type().elem_type() << std::endl;
271 if (initializer_names.find(
graph.input(i).name()) != initializer_names.end())
275 const onnx::ValueInfoProto &valueinfoproto =
graph.input(i);
276 std::string input_name = valueinfoproto.name();
280 throw std::runtime_error(
"TMVA::SOFIE Data type in input tensor " + input_name +
" not supported!\n");
284 bool existParam =
false;
285 if (!valueinfoproto.type().tensor_type().has_shape())
286 throw std::runtime_error(
"TMVA::SOFIE datanode with no shape restrictions is not supported yet");
287 for (
int j = 0; j < valueinfoproto.type().tensor_type().shape().dim_size(); j++) {
289 if (valueinfoproto.type().tensor_type().shape().dim(j).value_case() ==
290 onnx::TensorShapeProto_Dimension::ValueCase::kDimValue) {
291 dim.
dim = valueinfoproto.type().tensor_type().shape().dim(j).dim_value();
292 }
else if (valueinfoproto.type().tensor_type().shape().dim(j).value_case() ==
293 onnx::TensorShapeProto_Dimension::ValueCase::kDimParam) {
296 dim.
param = valueinfoproto.type().tensor_type().shape().dim(j).dim_param();
298 throw std::runtime_error(
"TMVA::SOFIE ONNX file error: Valueinfoproto " + input_name +
299 " has neither dim_value nor dim_param! \n");
303 if (valueinfoproto.type().tensor_type().shape().dim_size() == 0) {
310 std::vector<size_t> fShape_sizet;
312 fShape_sizet.push_back(j.dim);
322 std::map<std::string, int> allInitializedTensors;
325 std::cout <<
"\nParsing graph initializer list and fill model initialized tensors" << std::endl;
327 for (
int i = 0; i <
graph.initializer_size(); i++) {
328 onnx::TensorProto *tensorproto =
const_cast<onnx::TensorProto *
>(&
graph.initializer(i));
329 std::vector<std::size_t> shape;
330 std::size_t fLength = 1;
331 for (
int j = 0; j < tensorproto->dims_size(); j++) {
332 shape.push_back(tensorproto->dims(j));
333 fLength *= tensorproto->dims(j);
337 std::string input_name =
graph.initializer(i).name();
340 std::cout <<
"\t initializer " << i <<
" name " << input_name <<
" type " <<
graph.initializer(i).data_type()
345 std::shared_ptr<void>
data(
malloc(fLength *
sizeof(
float)),
free);
347 if (tensorproto->raw_data().empty() ==
false) {
348 auto raw_data_ptr =
reinterpret_cast<float *
>(
const_cast<char *
>(tensorproto->raw_data().c_str()));
349 std::memcpy(
data.get(), raw_data_ptr, fLength *
sizeof(
float));
351 tensorproto->mutable_float_data()->ExtractSubrange(0, tensorproto->float_data_size(),
352 static_cast<float *
>(
data.get()));
355 if (verbose) std::cout <<
"add FLOAT initialized tensor " << input_name <<
" shape " <<
ConvertShapeToString(shape) << std::endl;
357 allInitializedTensors[input_name] = i;
361 std::shared_ptr<void>
data(
malloc(fLength *
sizeof(int64_t)),
free);
363 if (tensorproto->raw_data().empty() ==
false) {
364 auto raw_data_ptr =
reinterpret_cast<int64_t *
>(
const_cast<char *
>(tensorproto->raw_data().c_str()));
365 std::memcpy(
data.get(), raw_data_ptr, fLength *
sizeof(int64_t));
367 tensorproto->mutable_int64_data()->ExtractSubrange(0, tensorproto->int64_data_size(),
368 static_cast<int64_t *
>(
data.get()));
371 if (verbose) std::cout <<
"add INT64 initialized tensor " << input_name <<
" shape " <<
ConvertShapeToString(shape) << std::endl;
373 allInitializedTensors[input_name] = i;
377 throw std::runtime_error(
"Data type in weight tensor " +
graph.initializer(i).name() +
" not supported!\n");
383 std::cout <<
"\nGraph operator list (ONNX order)\n";
384 for (
int i = 0; i <
graph.node_size(); i++) {
385 std::cout <<
"\tOperator " << i <<
" : " <<
graph.node(i).op_type() <<
" , " <<
graph.node(i).input_size()
387 for (
int j = 0; j <
graph.node(i).input_size(); j++) {
388 std::cout <<
graph.node(i).input(j);
389 if (j <
graph.node(i).input_size() - 1)
392 std::cout <<
" }" << std::endl;
398 std::cout <<
"\nRe-Order graph operator list\n";
399 std::vector<size_t> nodesOrder;
400 nodesOrder.reserve(
graph.node_size());
401 std::vector<bool> foundNodes(
graph.node_size());
403 std::map<std::string, int> allInputs;
404 for (
int i = 0; i <
graph.input_size(); i++) {
405 allInputs[
graph.input(i).name()] = -1;
408 auto psize = nodesOrder.size();
409 for (
int i = 0; i <
graph.node_size(); i++) {
413 bool existInputs =
true;
414 int input_size =
graph.node(i).input_size();
416 for (
int j = 0; j < input_size; j++) {
417 std::string
name =
graph.node(i).input(j);
420 existInputs &= (allInputs.find(
name) != allInputs.end() ||
421 allInitializedTensors.find(
name) != allInitializedTensors.end());
423 std::cout <<
graph.node(i).op_type() <<
" input " <<
name <<
" "
424 <<
bool(allInputs.find(
name) != allInputs.end()) <<
" " <<
425 bool(allInitializedTensors.find(
name) != allInitializedTensors.end()) <<
426 existInputs << std::endl;
432 std::cout <<
"skip op " <<
graph.node(i).op_type() <<
" inputs are ";
433 for (
int j = 0; j < input_size; j++) {
434 std::cout <<
graph.node(i).input(j) <<
" ";
436 std::cout << std::endl;
441 std::cout <<
"\tadd node " <<
graph.node(i).op_type() <<
" order " << i << std::endl;
443 nodesOrder.push_back(i);
444 foundNodes[i] =
true;
446 for (
int j = 0; j <
graph.node(i).output_size(); j++) {
447 allInputs[
graph.node(i).output(j)] = i;
451 if (nodesOrder.size() == psize) {
452 throw std::runtime_error(
"TMVA::SOFIE - cannot find a new node ");
454 }
while ((
int)nodesOrder.size() <
graph.node_size());
458 std::cout <<
"\nGraph operator list (re-ordered)\n";
459 for (
int k = 0; k <
graph.node_size(); k++) {
460 int i = nodesOrder[k];
461 std::cout <<
"\tOperator " << i <<
" : " <<
graph.node(i).op_type() <<
" , " <<
graph.node(i).input_size()
463 for (
int j = 0; j <
graph.node(i).input_size(); j++) {
464 std::cout <<
graph.node(i).input(j);
465 if (j <
graph.node(i).input_size() - 1)
468 std::cout <<
" }" << std::endl;
474 std::cout <<
"Fill RModel with operators...\n";
476 for (
int i = 0; i <
graph.node_size(); i++) {
477 std::string op_type =
graph.node(nodesOrder[i]).op_type();
480 std::cout <<
"\t" << i <<
" " << nodesOrder[i] <<
" parsing operator " << op_type << std::endl;
486 std::cout <<
"\t\tskipping operator since it is fused with previous one" << std::endl;
494 std::vector<std::string> outputnames;
496 std::cout <<
"\nParsing Graph output list\n";
497 for (
int i = 0; i <
graph.output_size(); i++) {
499 std::cout <<
"\toutput " << i <<
" name " <<
graph.output(i).name() << std::endl;
500 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 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 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