3#include "onnx_proto3.pb.h"
11#include <unordered_map>
16namespace Experimental {
130 throw std::runtime_error(
"TMVA::SOFIE - Failed to read float initialized tensor - actual size is " + std::to_string(
tensor->float_data_size()));
131 tensor->mutable_float_data()->ExtractSubrange(0,
tensor->float_data_size(),
132 static_cast<float *
>(
data));
139 throw std::runtime_error(
"TMVA::SOFIE - Failed to read double initialized tensor - actual size is " + std::to_string(
tensor->double_data_size()));
140 tensor->mutable_double_data()->ExtractSubrange(0,
tensor->double_data_size(),
141 static_cast<double *
>(
data));
148 throw std::runtime_error(
"TMVA::SOFIE - Failed to read int32 initialized tensor - actual size is " + std::to_string(
tensor->int32_data_size()));
149 tensor->mutable_int32_data()->ExtractSubrange(0,
tensor->int32_data_size(),
150 static_cast<int32_t *
>(
data));
157 throw std::runtime_error(
"TMVA::SOFIE - Failed to read int64 initialized tensor - actual size is " + std::to_string(
tensor->int64_data_size()));
158 tensor->mutable_int64_data()->ExtractSubrange(0,
tensor->int64_data_size(),
159 static_cast<int64_t *
>(
data));
169template <std::
size_t N>
173 auto dst =
static_cast<unsigned char *
>(
dest);
174 auto src =
static_cast<const unsigned char *
>(
source);
175 for (std::size_t k = 0; k <
nbytes; k +=
N) {
177 std::memcpy(&
v,
src + k,
N);
179 std::memcpy(
dst + k, &
v,
N);
205 std::shared_ptr<void>
data(
malloc(tensor_size), free);
208 if (
tensorproto->data_location() != onnx::TensorProto::EXTERNAL) {
211 throw std::runtime_error(
"TMVA::SOFIE - Failed to read raw data of initialized tensor - actual raw size is " +
241 throw std::runtime_error(
"TMVA::SOFIE - ExtractData from TP in BOOL not supported");
245 throw std::runtime_error(
"TMVA::SOFIE - ExtractData from TP in UINT8 not supported");
256 std::cout <<
"Initialized data are stored externally in file " <<
fDataFileName;
259 std::string location;
263 if (
kv.key() ==
"location") location =
kv.value();
264 else if (
kv.key() ==
"offset")
offset = std::stoull(
kv.value());
268 std::cout <<
" at location " << location <<
" offset " <<
offset <<
" and with length " <<
buffer_size << std::endl;
271 throw std::runtime_error(
"TMVA::SOFIE ONNX : invalid stored data size vs tensor size");
277 throw std::runtime_error(
"TMVA::SOFIE ONNX: error reading external weight ONNX data file " +
fDataFileName);
410 std::vector<std::string>
ops;
413 ops.emplace_back(it.first);
436std::unique_ptr<ROperator>
439 if (i >= nodes.size())
440 throw std::runtime_error(
"TMVA::SOFIE - Error in parsing ordered operators " + std::to_string(i) +
" is >= " + std::to_string(nodes.size()));
445 std::cout <<
"Parsing operator " <<
op_type << std::endl;
451 std::cout <<
"\tFusing operators " <<
graphproto.node(
idx1).name()
468 if (children.size() == 1) {
469 int idx2 = children.front();
487 }
else if (
nodeproto.op_type() ==
"Gemm") {
493 }
else if (
nodeproto.op_type() ==
"BatchNormalization") {
503 std::cout <<
"operator " <<
op_type <<
" is not supported" << std::endl;
504 throw std::runtime_error(
"TMVA::SOFIE Operator type " +
op_type +
" is not yet supported");
507 std::cout <<
"\tCreating operator " <<
op_type << std::endl;
521 throw std::runtime_error(
"TMVA::SOFIE - Failed to load onnx file " +
filename);
523 const onnx::GraphProto &graph = model->graph();
526 std::time_t
ttime = std::time(0);
537 if (
isep != std::string::npos) {
556 throw std::runtime_error(
"TMVA::SOFIE - Failed to parse ONNX model from input stream");
558 const onnx::GraphProto &graph = model->graph();
560 std::time_t
ttime = std::time(0);
570 std::fstream
input(
filename, std::ios::in | std::ios::binary);
572 std::cerr <<
"TMVA::SOFIE - Failed to open onnx file " <<
filename << std::endl;
581 auto model = std::make_unique<onnx::ModelProto>();
583 if (!model->ParseFromIstream(&
input)) {
584 std::cerr <<
"TMVA::SOFIE - Failed to parse ONNX model from input stream" << std::endl;
590 std::cout <<
"ONNX Version " << model->ir_version() << std::endl;
592 google::protobuf::ShutdownProtobufLibrary();
599 std::cout <<
"\n" << graph.name() <<
" Graph operator list\n";
600 for (
int i = 0; i < graph.node_size(); i++) {
601 const auto & node = graph.node(i);
602 const std::string
opType = node.op_type();
604 std::cout <<
"\tOperator " << i <<
" : " <<
opType <<
" (" << node.name() <<
"), " << graph.node(i).input_size()
607 std::cout << graph.node(i).input(
j);
608 if (
j < graph.node(i).input_size() - 1)
611 std::cout <<
" }" << std::endl;
617 for (
int j = 0;
j < node.attribute_size();
j++) {
632 if (!model)
return false;
634 const onnx::GraphProto &graph = model->graph();
637 std::cout <<
"\nModel operator list " << model->producer_name() <<
"\n";
644 std::cout <<
"List of missing operators for model loaded from file " <<
filename << std::endl;
646 std::cout <<
op.first <<
" " <<
op.second << std::endl;
650 std::cout <<
"All operators in the loaded model are supported!\n";
662 std::cout <<
"\nParsing Graph - " <<
graphName << std::endl;
665 for (
int i = 0; i < graph.initializer_size(); i++) {
670 std::cout <<
"Parsing model inputs...." << std::endl;
672 for (
int i = 0; i < graph.input_size(); i++) {
674 static_cast<ETensorType>(graph.input(i).type().tensor_type().elem_type()));
677 std::cout <<
"\tgraph input " << i <<
" name " << graph.input(i).name() <<
" type "
678 << graph.input(i).type().tensor_type().elem_type() << std::endl;
692 throw std::runtime_error(
"TMVA::SOFIE data node with no shape restrictions is not supported yet");
693 for (
int j = 0;
j <
valueinfoproto.type().tensor_type().shape().dim_size();
j++) {
696 onnx::TensorShapeProto_Dimension::ValueCase::kDimValue) {
705 }
else if (
valueinfoproto.type().tensor_type().shape().dim(
j).value_case() ==
706 onnx::TensorShapeProto_Dimension::ValueCase::kDimParam) {
711 throw std::runtime_error(
"TMVA::SOFIE ONNX file error: Valueinfoproto " +
input_name +
712 " has neither dim_value nor dim_param! \n");
716 if (
valueinfoproto.type().tensor_type().shape().dim_size() == 0) {
738 std::cout <<
"\nParsing graph initializer list and fill model initialized tensors" << std::endl;
740 for (
int i = 0; i < graph.initializer_size(); i++) {
741 onnx::TensorProto *
tensorproto =
const_cast<onnx::TensorProto *
>(&graph.initializer(i));
742 std::vector<std::size_t> shape;
750 std::string tensor_name = graph.initializer(i).name();
753 std::cout <<
"\t initializer " << i <<
" name " << tensor_name <<
" type " << graph.initializer(i).data_type()
766 std::cout <<
"add initialized tensor " << tensor_name <<
"with shape " <<
ConvertShapeToString(shape) <<
"and ";
768 std::cout <<
" float data: ";
772 std::cout <<
" int64 data: ";
776 std::cout <<
" uint8 data: ";
780 std::cout <<
" Boolean data: ";
783 std::cout << std::endl;
789 std::cout <<
"\nGraph operator list (ONNX order)\n";
790 for (
int i = 0; i < graph.node_size(); i++) {
791 std::cout <<
"\tOperator " << i <<
" : " << graph.node(i).op_type() <<
" , " << graph.node(i).input_size()
794 std::cout << graph.node(i).input(
j);
795 if (
j < graph.node(i).input_size() - 1)
798 std::cout <<
" }" << std::endl;
804 std::cout <<
"\n***********************\nRe-Order graph operator list\n*************************\n";
807 std::vector<bool>
foundNodes(graph.node_size());
811 for (
int i = 0; i < graph.input_size(); i++) {
816 for (
int i = 0; i < graph.node_size(); i++) {
824 std::cout <<
"Checking input of Node " << i <<
" : " << graph.node(i).name() << std::endl;
826 std::string
name = graph.node(i).input(
j);
832 std::cout <<
"\t\t input " <<
name <<
" "
841 std::cout <<
"skip node " << graph.node(i).op_type() <<
" " << graph.node(i).name() <<
" inputs are not existing ";
843 std::cout << graph.node(i).input(
j) <<
" ";
845 std::cout << std::endl;
852 std::cout <<
"===> New node " << graph.node(i).op_type() <<
" " << graph.node(i).name() <<
" order " << i << std::endl;
858 if (
fVerbose) std::cout <<
"\toutput : " << graph.node(i).output(
j) << std::endl;
865 std::cout <<
"cannot find a new node after " << graph.node(
ilast).op_type() <<
" " << graph.node(
ilast).name() << std::endl;
866 throw std::runtime_error(
"TMVA::SOFIE - cannot find a new node ");
868 }
while ((
int)
nodesOrder.size() < graph.node_size());
872 std::vector<std::vector<int>>
nodesChildren(graph.node_size());
874 for (
int k = 0; k < graph.node_size(); k++) {
877 if (graph.node(i).output_size() > 0)
nodesChildren[i].reserve(graph.node(i).output_size());
878 for (
const auto&
output_name : graph.node(i).output()) {
880 for (
int l = k;
l < graph.node_size();
l++) {
882 for (
const auto&
input_name : graph.node(
j).input()) {
892 std::cout <<
"\nGraph operator list (re-ordered)\n";
893 for (
int k = 0; k < graph.node_size(); k++) {
895 std::cout <<
"\tOperator " << i <<
" : " << graph.node(i).op_type() <<
" , " << graph.node(i).name() <<
" input tensors : {";
896 for (
int j = 0;
j < graph.node(i).input_size();
j++) {
897 std::cout << graph.node(i).input(
j);
898 if (
j < graph.node(i).input_size() - 1)
902 std::cout <<
" children : {";
904 std::cout <<
" [ " <<
ichild <<
" " << graph.node(
ichild).op_type() <<
" , " << graph.node(
ichild).name() <<
"]";
906 std::cout <<
"}" << std::endl;
912 std::cout <<
"Fill RModel with operators...\n";
918 for (
int i = 0; i < graph.node_size(); i++) {
922 std::cout <<
"\t" << i <<
" " <<
nodesOrder[i] <<
" parsing operator " <<
op_type << std::endl;
928 std::cout <<
"\t\tskipping operator since it is fused with previous one" << std::endl;
938 std::cout <<
"\nParsing Graph output list\n";
939 for (
int i = 0; i < graph.output_size(); i++) {
941 std::cout <<
"\toutput " << i <<
" name " << graph.output(i).name() << std::endl;
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 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 dest
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 offset
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 length
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t src
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
const_iterator begin() const
const_iterator end() const
void RegisterOperator(const std::string &name, ParserFuncSignature func)
std::unique_ptr< ROperator > ParseOperator(const size_t, const onnx::GraphProto &, const std::vector< size_t > &, const std::vector< int > &)
std::string fDataFileName
bool IsRegisteredOperator(const std::string &name)
void CheckGraph(const onnx::GraphProto &g, int &level, std::map< std::string, int > &missingOperators)
void ParseONNXGraph(RModel &model, const onnx::GraphProto &g, std::string name="")
RModelParser_ONNX() noexcept
std::unordered_map< std::string, ETensorType > fTensorTypeMap
RModel Parse(std::string const &filename, bool verbose=false)
std::shared_ptr< void > GetInitializedTensorData(onnx::TensorProto *tensorproto, size_t tensor_length, ETensorType type)
std::map< int, std::pair< EFusedOp, int > > fFusedOperators
bool IsRegisteredTensorType(const std::string &)
void RegisterTensorType(const std::string &, ETensorType)
ETensorType GetTensorType(const std::string &name)
std::vector< std::string > GetRegisteredOperators()
std::unique_ptr< onnx::ModelProto > LoadModel(const std::string &filename)
std::unique_ptr< OperatorsMapImpl > fOperatorsMapImpl
bool CheckModel(std::string filename, bool verbose=false)
std::string Clean_name(std::string input_tensor_name)
ParserFuncSignature ParseIsNaN
ParserFuncSignature ParseSqrt
ParserFuncSignature ParseBatchNormalization
ParserFuncSignature ParseGreater
std::function< std::unique_ptr< ROperator >(RModelParser_ONNX &, const onnx::NodeProto &, const onnx::NodeProto &)> ParserFuseFuncSignature
ParserFuncSignature ParseReshape
ParserFuseFuncSignature ParseFuseConvTransposeAdd
ParserFuncSignature ParseReduceMean
ParserFuseFuncSignature ParseFuseMatMulAdd
ParserFuncSignature ParseGather
ParserFuncSignature ParseNeg
ParserFuncSignature ParseWhere
ParserFuncSignature ParseCos
ParserFuncSignature ParseLog
ParserFuncSignature ParseLeakyRelu
ParserFuncSignature ParseExp
std::function< std::unique_ptr< ROperator >(RModelParser_ONNX &, const onnx::NodeProto &)> ParserFuncSignature
ParserFuncSignature ParseEinsum
ParserFuncSignature ParsePool
ParserFuncSignature ParseDiv
ParserFuncSignature ParseLayerNormalization
ParserFuncSignature ParseConcat
ParserFuncSignature ParseTopK
ParserFuncSignature ParseMax
ParserFuncSignature ParseEq
ParserFuncSignature ParseIdentity
ParserFuncSignature ParseConvTranspose
ParserFuncSignature ParseReduceProd
ParserFuncSignature ParseNot
ParserFuncSignature ParseSlice
ParserFuncSignature ParseRandom
ParserFuncSignature ParseTranspose
ParserFuncSignature ParseLess
ParserFuncSignature ParseShape
ParserFuncSignature ParseClip
constexpr size_t GetTypeSize(ETensorType type)
ParserFuncSignature ParseScatterND
ParserFuncSignature ParseGRU
ParserFuncSignature ParseMatMul
ParserFuncSignature ParseErf
ParserFuncSignature ParseSub
ParserFuncSignature ParseAdd
ParserFuncSignature ParseNonZero
ParserFuncSignature ParseIf
ParserFuncSignature ParseRange
ParserFuncSignature ParseSoftplus
ParserFuncSignature ParseExpand
ParserFuncSignature ParseRNN
ParserFuncSignature ParseHardSigmoid
ParserFuncSignature ParseLSTM
ParserFuncSignature ParseCast
ParserFuncSignature ParseReciprocal
ParserFuncSignature ParseSwish
ParserFuncSignature ParseSigmoid
ParserFuseFuncSignature ParseFuseConvAdd
ParserFuncSignature ParseAtan
ParserFuncSignature ParseFloor
ParserFuseFuncSignature ParseFuseBatchnormRelu
ParserFuncSignature ParseIsInf
ParserFuncSignature ParseSoftmax
ParserFuncSignature ParseGreaterEq
ParserFuncSignature ParseMod
std::string ConvertTypeToString(ETensorType type)
ParserFuncSignature ParseGelu
ParserFuncSignature ParseMean
ParserFuncSignature ParseSplit
ParserFuncSignature ParseConstant
ParserFuncSignature ParseSelu
ParserFuncSignature ParseLessEq
ParserFuncSignature ParseHardSwish
ParserFuncSignature ParseGatherND
ParserFuncSignature ParseSum
ParserFuncSignature ParseEyeLike
ParserFuncSignature ParsePad
ParserFuncSignature ParseElu
std::string ConvertShapeToString(const std::vector< size_t > &shape)
ParserFuncSignature ParseMin
ParserFuncSignature ParseRelu
ParserFuncSignature ParseReduceSum
ParserFuncSignature ParseConv
ParserFuncSignature ParseInstanceNormalization
ParserFuncSignature ParseScatterElements
ParserFuncSignature ParseGemm
ParserFuncSignature ParseTile
ParserFuncSignature ParseMul
ParserFuseFuncSignature ParseFuseGemmRelu
ParserFuncSignature ParsePow
ParserFuncSignature ParseAbs
ParserFuncSignature ParseSin
ParserFuncSignature ParseReduceSumSquare
ParserFuncSignature ParseTanh
create variable transformations
Helper templated class for swapping bytes; specializations for N={2,4,8} are provided below.
std::unordered_map< std::string, ParserFuncSignature > fOperatorsMap