3#include "onnx_proto3.pb.h"
10#include <unordered_map>
15namespace Experimental {
176 std::vector<std::string> ops;
179 ops.emplace_back(it.first);
200std::unique_ptr<ROperator>
203 if (i >= nodes.size())
204 throw std::runtime_error(
"TMVA::SOFIE - Error in parsing ordered operators " + std::to_string(i) +
" is >= " + std::to_string(nodes.size()));
206 const auto &nodeproto = graphproto.node(idx);
207 const std::string op_type = nodeproto.op_type();
209 std::cout <<
"Parsing an operator " << op_type << std::endl;
212 if (i < nodes.size() - 1) {
213 int idx2 = nodes[i+1];
214 if (op_type ==
"MatMul") {
216 if (idx2 < graphproto.node_size() && graphproto.node(idx2).op_type() ==
"Add") {
222 }
else if (nodeproto.op_type() ==
"Conv" || nodeproto.op_type() ==
"ConvTranspose") {
224 if (idx2 < graphproto.node_size() && graphproto.node(idx2).op_type() ==
"Add") {
225 if (nodeproto.op_type() ==
"Conv") {
226 return ParseFuseConvAdd(*
this, graphproto.node(idx), graphproto.node(idx2));
235 if (idx > 0 && op_type ==
"Add") {
236 int idx0 = nodes[i - 1];
237 if (graphproto.node(idx0).op_type() ==
"MatMul")
239 else if (graphproto.node(idx0).op_type() ==
"ConvTranspose")
245 throw std::runtime_error(
"TMVA::SOFIE Operator type " + op_type +
" is not yet supported");
248 std::cout <<
"\tCreating operator " << op_type << std::endl;
250 return it->second(*
this, nodeproto);
262 std::string filename_nodir =
filename;
263 if (isep != std::string::npos) {
267 std::time_t ttime = std::time(0);
268 std::tm *gmt_time = std::gmtime(&ttime);
269 std::string parsetime(std::asctime(gmt_time));
271 GOOGLE_PROTOBUF_VERIFY_VERSION;
273 onnx::ModelProto model;
274 RModel rmodel(filename_nodir, parsetime);
278 std::fstream
input(
filename, std::ios::in | std::ios::binary);
279 if (!model.ParseFromIstream(&
input)) {
280 throw std::runtime_error(
"TMVA::SOFIE - Failed to parse onnx file " +
filename);
283 const onnx::GraphProto &
graph = model.graph();
284 google::protobuf::ShutdownProtobufLibrary();
288 std::cout <<
"ONNX Version " << model.ir_version() << std::endl;
291 std::unordered_set<std::string> initializer_names;
292 for (
int i = 0; i <
graph.initializer_size(); i++) {
293 initializer_names.insert(
graph.initializer(i).name());
297 std::cout <<
"Parsing model inputs...." << std::endl;
299 for (
int i = 0; i <
graph.input_size(); i++) {
304 std::cout <<
"\tgraph input " << i <<
" name " <<
graph.input(i).name() <<
" type "
305 <<
graph.input(i).type().tensor_type().elem_type() << std::endl;
307 if (initializer_names.find(
graph.input(i).name()) != initializer_names.end())
311 const onnx::ValueInfoProto &valueinfoproto =
graph.input(i);
312 std::string input_name = valueinfoproto.name();
316 throw std::runtime_error(
"TMVA::SOFIE Data type in input tensor " + input_name +
" not supported!\n");
320 bool existParam =
false;
321 if (!valueinfoproto.type().tensor_type().has_shape())
322 throw std::runtime_error(
"TMVA::SOFIE datanode with no shape restrictions is not supported yet");
323 for (
int j = 0; j < valueinfoproto.type().tensor_type().shape().dim_size(); j++) {
325 if (valueinfoproto.type().tensor_type().shape().dim(j).value_case() ==
326 onnx::TensorShapeProto_Dimension::ValueCase::kDimValue) {
327 dim.
dim = valueinfoproto.type().tensor_type().shape().dim(j).dim_value();
328 }
else if (valueinfoproto.type().tensor_type().shape().dim(j).value_case() ==
329 onnx::TensorShapeProto_Dimension::ValueCase::kDimParam) {
332 dim.
param = valueinfoproto.type().tensor_type().shape().dim(j).dim_param();
334 throw std::runtime_error(
"TMVA::SOFIE ONNX file error: Valueinfoproto " + input_name +
335 " has neither dim_value nor dim_param! \n");
339 if (valueinfoproto.type().tensor_type().shape().dim_size() == 0) {
346 std::vector<size_t> fShape_sizet;
348 fShape_sizet.push_back(j.dim);
358 std::map<std::string, int> allInitializedTensors;
361 std::cout <<
"\nParsing graph initializer list and fill model initialized tensors" << std::endl;
363 for (
int i = 0; i <
graph.initializer_size(); i++) {
364 onnx::TensorProto *tensorproto =
const_cast<onnx::TensorProto *
>(&
graph.initializer(i));
365 std::vector<std::size_t> shape;
366 std::size_t fLength = 1;
367 for (
int j = 0; j < tensorproto->dims_size(); j++) {
368 shape.push_back(tensorproto->dims(j));
369 fLength *= tensorproto->dims(j);
373 std::string input_name =
graph.initializer(i).name();
376 std::cout <<
"\t initializer " << i <<
" name " << input_name <<
" type " <<
graph.initializer(i).data_type()
381 std::shared_ptr<void>
data(
malloc(fLength *
sizeof(
float)),
free);
383 if (!tensorproto->raw_data().empty()) {
385 std::memcpy(
data.get(), tensorproto->raw_data().c_str(), fLength *
sizeof(
float));
387 for (std::size_t k = 0; k < fLength; ++k)
388 (
reinterpret_cast<uint32_t *
>(
data.get()))[k] =
389 Rbswap_32((
reinterpret_cast<const uint32_t *
>(tensorproto->raw_data().c_str()))[k]);
392 tensorproto->mutable_float_data()->ExtractSubrange(0, tensorproto->float_data_size(),
393 static_cast<float *
>(
data.get()));
396 if (verbose) std::cout <<
"add FLOAT initialized tensor " << input_name <<
" shape " <<
ConvertShapeToString(shape) << std::endl;
398 allInitializedTensors[input_name] = i;
402 std::shared_ptr<void>
data(
malloc(fLength *
sizeof(int64_t)),
free);
404 if (!tensorproto->raw_data().empty()) {
406 std::memcpy(
data.get(), tensorproto->raw_data().c_str(), fLength *
sizeof(int64_t));
408 for (std::size_t k = 0; k < fLength; ++k)
409 (
reinterpret_cast<uint64_t *
>(
data.get()))[k] =
410 Rbswap_64((
reinterpret_cast<const uint64_t *
>(tensorproto->raw_data().c_str()))[k]);
413 tensorproto->mutable_int64_data()->ExtractSubrange(0, tensorproto->int64_data_size(),
414 static_cast<int64_t *
>(
data.get()));
417 if (verbose) std::cout <<
"add INT64 initialized tensor " << input_name <<
" shape " <<
ConvertShapeToString(shape) << std::endl;
419 allInitializedTensors[input_name] = i;
423 throw std::runtime_error(
"Data type in weight tensor " +
graph.initializer(i).name() +
" not supported!\n");
429 std::cout <<
"\nGraph operator list (ONNX order)\n";
430 for (
int i = 0; i <
graph.node_size(); i++) {
431 std::cout <<
"\tOperator " << i <<
" : " <<
graph.node(i).op_type() <<
" , " <<
graph.node(i).input_size()
433 for (
int j = 0; j <
graph.node(i).input_size(); j++) {
434 std::cout <<
graph.node(i).input(j);
435 if (j <
graph.node(i).input_size() - 1)
438 std::cout <<
" }" << std::endl;
444 std::cout <<
"\nRe-Order graph operator list\n";
445 std::vector<size_t> nodesOrder;
446 nodesOrder.reserve(
graph.node_size());
447 std::vector<bool> foundNodes(
graph.node_size());
449 std::map<std::string, int> allInputs;
450 for (
int i = 0; i <
graph.input_size(); i++) {
451 allInputs[
graph.input(i).name()] = -1;
454 auto psize = nodesOrder.size();
455 for (
int i = 0; i <
graph.node_size(); i++) {
459 bool existInputs =
true;
460 int input_size =
graph.node(i).input_size();
462 for (
int j = 0; j < input_size; j++) {
463 std::string
name =
graph.node(i).input(j);
466 existInputs &= (allInputs.find(
name) != allInputs.end() ||
467 allInitializedTensors.find(
name) != allInitializedTensors.end());
469 std::cout <<
graph.node(i).op_type() <<
" input " <<
name <<
" "
470 <<
bool(allInputs.find(
name) != allInputs.end()) <<
" " <<
471 bool(allInitializedTensors.find(
name) != allInitializedTensors.end()) <<
472 existInputs << std::endl;
478 std::cout <<
"skip op " <<
graph.node(i).op_type() <<
" inputs are ";
479 for (
int j = 0; j < input_size; j++) {
480 std::cout <<
graph.node(i).input(j) <<
" ";
482 std::cout << std::endl;
487 std::cout <<
"\tadd node " <<
graph.node(i).op_type() <<
" order " << i << std::endl;
489 nodesOrder.push_back(i);
490 foundNodes[i] =
true;
492 for (
int j = 0; j <
graph.node(i).output_size(); j++) {
493 allInputs[
graph.node(i).output(j)] = i;
497 if (nodesOrder.size() == psize) {
498 throw std::runtime_error(
"TMVA::SOFIE - cannot find a new node ");
500 }
while ((
int)nodesOrder.size() <
graph.node_size());
504 std::cout <<
"\nGraph operator list (re-ordered)\n";
505 for (
int k = 0; k <
graph.node_size(); k++) {
506 int i = nodesOrder[k];
507 std::cout <<
"\tOperator " << i <<
" : " <<
graph.node(i).op_type() <<
" , " <<
graph.node(i).input_size()
509 for (
int j = 0; j <
graph.node(i).input_size(); j++) {
510 std::cout <<
graph.node(i).input(j);
511 if (j <
graph.node(i).input_size() - 1)
514 std::cout <<
" }" << std::endl;
520 std::cout <<
"Fill RModel with operators...\n";
522 for (
int i = 0; i <
graph.node_size(); i++) {
523 std::string op_type =
graph.node(nodesOrder[i]).op_type();
526 std::cout <<
"\t" << i <<
" " << nodesOrder[i] <<
" parsing operator " << op_type << std::endl;
532 std::cout <<
"\t\tskipping operator since it is fused with previous one" << std::endl;
540 std::vector<std::string> outputnames;
542 std::cout <<
"\nParsing Graph output list\n";
543 for (
int i = 0; i <
graph.output_size(); i++) {
545 std::cout <<
"\toutput " << i <<
" name " <<
graph.output(i).name() << std::endl;
546 outputnames.push_back(
graph.output(i).name());
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 data
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 AddInputTensorInfo(std::string input_name, ETensorType type, std::vector< Dim > shape)
void AddOutputTensorNameList(std::vector< std::string > output_tensor_names)
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 ParseGreater
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 ParseEq
ParserFuncSignature ParseIdentity
ParserFuncSignature ParseConvTranspose
ParserFuncSignature ParseReduceProd
ParserFuncSignature ParseSlice
ParserFuncSignature ParseTranspose
ParserFuncSignature ParseLess
ParserFuncSignature ParseShape
ParserFuncSignature ParseGRU
ParserFuncSignature ParseMatMul
ParserFuncSignature ParseErf
ParserFuncSignature ParseSub
ParserFuncSignature ParseReduceSumsquare
ParserFuncSignature ParseAdd
ParserFuncSignature ParseRange
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 ParseGreaterEq
ParserFuncSignature ParseMean
ParserFuncSignature ParseConstant
ParserFuncSignature ParseSelu
ParserFuncSignature ParseLessEq
ParserFuncSignature ParseSum
ParserFuncSignature ParseEyeLike
ParserFuncSignature ParseElu
ParserFuncSignature ParseMin
ParserFuncSignature ParseRelu
ParserFuncSignature ParseReduceSum
ParserFuncSignature ParseConv
ParserFuncSignature ParseGemm
ParserFuncSignature ParseMul
ParserFuncSignature ParsePow
ParserFuncSignature ParseTanh
create variable transformations
std::unordered_map< std::string, ParserFuncSignature > fOperatorsMap