28#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
29#include <numpy/arrayobject.h>
32namespace Experimental{
94 std::string fNodeType =
PyStringAsString(PyDict_GetItemString(fNode,
"nodeType"));
97 throw std::runtime_error(
"TMVA::SOFIE - Parsing PyTorch node " +fNodeType+
" is not yet supported ");
99 return (findNode->second)(fNode);
115 PyObject* fAttributes = PyDict_GetItemString(fNode,
"nodeAttributes");
116 PyObject* fInputs = PyDict_GetItemString(fNode,
"nodeInputs");
117 PyObject* fOutputs = PyDict_GetItemString(fNode,
"nodeOutputs");
118 std::string fNodeDType =
PyStringAsString(PyList_GetItem(PyDict_GetItemString(fNode,
"nodeDType"),0));
125 float fAttrAlpha = (float)(
PyFloat_AsDouble(PyDict_GetItemString(fAttributes,
"alpha")));
126 float fAttrBeta = (float)(
PyFloat_AsDouble(PyDict_GetItemString(fAttributes,
"beta")));
130 if(PyDict_Contains(fAttributes,PyUnicode_FromString(
"transB"))){
131 fAttrTransB = (
int_t)(PyLong_AsLong(PyDict_GetItemString(fAttributes,
"transB")));
132 fAttrTransA = !fAttrTransB;
135 fAttrTransA=(
int_t)(PyLong_AsLong(PyDict_GetItemString(fAttributes,
"transA")));
136 fAttrTransB = !fAttrTransA;
139 std::unique_ptr<ROperator> op;
142 op.reset(
new ROperator_Gemm<float>(fAttrAlpha, fAttrBeta, fAttrTransA, fAttrTransB, fNameA, fNameB, fNameC, fNameY ));
146 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Gemm does not yet support input type " + fNodeDType);
161 PyObject* fInputs = PyDict_GetItemString(fNode,
"nodeInputs");
162 PyObject* fOutputs = PyDict_GetItemString(fNode,
"nodeOutputs");
163 std::string fNodeDType =
PyStringAsString(PyList_GetItem(PyDict_GetItemString(fNode,
"nodeDType"),0));
166 std::unique_ptr<ROperator> op;
173 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Relu does not yet support input type " + fNodeDType);
188 PyObject* fInputs = PyDict_GetItemString(fNode,
"nodeInputs");
189 PyObject* fOutputs = PyDict_GetItemString(fNode,
"nodeOutputs");
190 std::string fNodeDType =
PyStringAsString(PyList_GetItem(PyDict_GetItemString(fNode,
"nodeDType"),0));
192 std::unique_ptr<ROperator> op;
199 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Selu does not yet support input type " + fNodeDType);
214 PyObject* fInputs = PyDict_GetItemString(fNode,
"nodeInputs");
215 PyObject* fOutputs = PyDict_GetItemString(fNode,
"nodeOutputs");
216 std::string fNodeDType =
PyStringAsString(PyList_GetItem(PyDict_GetItemString(fNode,
"nodeDType"),0));
218 std::unique_ptr<ROperator> op;
225 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Sigmoid does not yet support input type " + fNodeDType);
240 PyObject* fAttributes = PyDict_GetItemString(fNode,
"nodeAttributes");
241 PyObject* fInputs = PyDict_GetItemString(fNode,
"nodeInputs");
242 PyObject* fOutputs = PyDict_GetItemString(fNode,
"nodeOutputs");
243 std::string fNodeDType =
PyStringAsString(PyList_GetItem(PyDict_GetItemString(fNode,
"nodeDType"),0));
246 std::vector<int_t> fAttrPermute;
247 PyObject* fPermute=PyDict_GetItemString(fAttributes,
"perm");
248 for(
Py_ssize_t permIter=0; permIter<PyList_Size(fPermute);++permIter){
249 fAttrPermute.push_back((
int_t)PyLong_AsLong(PyList_GetItem(fPermute,permIter)));
254 std::unique_ptr<ROperator> op;
261 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Transpose does not yet support input type " + fNodeDType);
277 PyObject* fAttributes = PyDict_GetItemString(fNode,
"nodeAttributes");
278 PyObject* fInputs = PyDict_GetItemString(fNode,
"nodeInputs");
279 PyObject* fOutputs = PyDict_GetItemString(fNode,
"nodeOutputs");
280 std::string fNodeDType =
PyStringAsString(PyList_GetItem(PyDict_GetItemString(fNode,
"nodeDType"),0));
283 PyObject* fDilations = PyDict_GetItemString(fAttributes,
"dilations");
284 PyObject* fGroup = PyDict_GetItemString(fAttributes,
"group");
285 PyObject* fKernelShape = PyDict_GetItemString(fAttributes,
"kernel_shape");
286 PyObject* fPads = PyDict_GetItemString(fAttributes,
"pads");
287 PyObject* fStrides = PyDict_GetItemString(fAttributes,
"strides");
289 std::string fAttrAutopad =
"NOTSET";
290 std::vector<size_t> fAttrDilations = GetDataFromList(fDilations);
291 size_t fAttrGroup = PyLong_AsLong(fGroup);
292 std::vector<size_t> fAttrKernelShape = GetDataFromList(fKernelShape);
293 std::vector<size_t> fAttrPads = GetDataFromList(fPads);
294 std::vector<size_t> fAttrStrides = GetDataFromList(fStrides);
300 std::unique_ptr<ROperator> op;
303 op.reset(
new ROperator_Conv<float>(fAttrAutopad, fAttrDilations, fAttrGroup, fAttrKernelShape, fAttrPads, fAttrStrides, nameX, nameW, nameB, nameY));
307 throw std::runtime_error(
"TMVA::SOFIE - Unsupported - Operator Conv does not yet support input type " + fNodeDType);
357RModel Parse(std::string filename, std::vector<std::vector<size_t>> inputShapes, std::vector<ETensorType> inputDTypes){
364 size_t isep = filename.rfind(sep, filename.length());
365 std::string filename_nodir = filename;
366 if (isep != std::string::npos){
367 filename_nodir = (filename.substr(isep+1, filename.length() - isep));
371 if(!std::ifstream(filename).good()){
372 throw std::runtime_error(
"Model file "+filename_nodir+
" not found!");
376 std::time_t ttime = std::time(0);
377 std::tm* gmt_time = std::gmtime(&ttime);
378 std::string parsetime (std::asctime(gmt_time));
380 RModel rmodel(filename_nodir, parsetime);
388 throw std::runtime_error(
"Can't init global namespace for Python");
391 throw std::runtime_error(
"Can't init local namespace for Python");
399 PyRunString(
"print('Torch Version: '+torch.__version__)",fGlobalNS,fLocalNS);
400 PyRunString(
"from torch.onnx.utils import _model_to_graph",fGlobalNS,fLocalNS);
401 PyRunString(
"from torch.onnx.symbolic_helper import _set_onnx_shape_inference",fGlobalNS,fLocalNS);
403 PyRunString(
"globals().update(locals())",fGlobalNS,fLocalNS);
409 for(
long unsigned int it=0;it<inputShapes.size();++it){
411 for(
long unsigned int itr=0;itr<inputShapes[it].size();++itr){
414 PyRunString(
"dummyInputs.append(torch.rand(*inputShape))",fGlobalNS,fLocalNS);
418 PyRunString(
"_set_onnx_shape_inference(True)",fGlobalNS,fLocalNS);
419 PyRunString(
"graph=_model_to_graph(model,dummyInputs)",fGlobalNS,fLocalNS);
425 " globals().update(locals())\n"
427 " nodeData['nodeType']=i.kind()\n"
428 " nodeAttributeNames=[x for x in i.attributeNames()]\n"
429 " nodeAttributes={j:i[j] for j in nodeAttributeNames}\n"
430 " nodeData['nodeAttributes']=nodeAttributes\n"
431 " nodeInputs=[x for x in i.inputs()]\n"
432 " nodeInputNames=[x.debugName() for x in nodeInputs]\n"
433 " nodeData['nodeInputs']=nodeInputNames\n"
434 " nodeOutputs=[x for x in i.outputs()]\n"
435 " nodeOutputNames=[x.debugName() for x in nodeOutputs]\n"
436 " nodeData['nodeOutputs']=nodeOutputNames\n"
437 " nodeDType=[x.type().scalarType() for x in nodeOutputs]\n"
438 " nodeData['nodeDType']=nodeDType\n"
439 " modelData.append(nodeData)",fGlobalNS,fLocalNS);
441 PyObject* fPModel = PyDict_GetItemString(fLocalNS,
"modelData");
442 Py_ssize_t fPModelSize = PyList_Size(fPModel);
444 std::string fNodeType;
447 for(
Py_ssize_t fModelIterator=0;fModelIterator<fPModelSize;++fModelIterator){
448 fNode = PyList_GetItem(fPModel,fModelIterator);
452 if(fNodeType ==
"onnx::Gemm"){
455 else if(fNodeType ==
"onnx::Selu" || fNodeType ==
"onnx::Sigmoid"){
458 else if (fNodeType ==
"onnx::Conv") {
466 PyRunString(
"weightNames=[k for k in graph[1].keys()]",fGlobalNS,fLocalNS);
467 PyRunString(
"weights=[v.numpy() for v in graph[1].values()]",fGlobalNS,fLocalNS);
468 PyRunString(
"weightDTypes=[v.type()[6:-6] for v in graph[1].values()]",fGlobalNS,fLocalNS);
469 PyObject* fPWeightNames = PyDict_GetItemString(fLocalNS,
"weightNames");
470 PyObject* fPWeightTensors = PyDict_GetItemString(fLocalNS,
"weights");
471 PyObject* fPWeightDTypes = PyDict_GetItemString(fLocalNS,
"weightDTypes");
472 PyArrayObject* fWeightTensor;
473 std::string fWeightName;
475 std::vector<std::size_t> fWeightShape;
476 std::size_t fWeightSize;
478 for(
Py_ssize_t weightIter=0; weightIter<PyList_Size(fPWeightTensors);++weightIter){
479 fWeightTensor = (PyArrayObject*)PyList_GetItem(fPWeightTensors,weightIter);
483 fWeightShape.clear();
484 for(
int j=0; j<PyArray_NDIM(fWeightTensor); ++j){
485 fWeightShape.push_back((std::size_t)(PyArray_DIM(fWeightTensor,j)));
486 fWeightSize*=(std::size_t)(PyArray_DIM(fWeightTensor,j));
488 switch(fWeightDType){
490 float* fWeightValue = (
float*)PyArray_DATA(fWeightTensor);
491 std::shared_ptr<void> fData(
malloc(fWeightSize *
sizeof(
float)),
free);
492 std::memcpy(fData.get(),fWeightValue,fWeightSize *
sizeof(
float));
497 throw std::runtime_error(
"Type error: TMVA SOFIE does not yet supports weights of data type"+
ConvertTypeToString(fWeightDType));
503 PyRunString(
"inputs=[x for x in model.graph.inputs()]",fGlobalNS,fLocalNS);
504 PyRunString(
"inputs=inputs[1:]",fGlobalNS,fLocalNS);
505 PyRunString(
"inputNames=[x.debugName() for x in inputs]",fGlobalNS,fLocalNS);
506 PyObject* fPInputs= PyDict_GetItemString(fLocalNS,
"inputNames");
507 std::string fInputName;
508 std::vector<size_t>fInputShape;
510 for(
Py_ssize_t inputIter=0; inputIter<PyList_Size(fPInputs);++inputIter){
512 fInputShape = inputShapes[inputIter];
513 fInputDType = inputDTypes[inputIter];
520 throw std::runtime_error(
"Type Error: TMVA SOFIE does not yet support the input tensor data type"+
ConvertTypeToString(fInputDType));
526 PyRunString(
"outputs=[x for x in graph[0].outputs()]",fGlobalNS,fLocalNS);
527 PyRunString(
"outputNames=[x.debugName() for x in outputs]",fGlobalNS,fLocalNS);
528 PyObject* fPOutputs= PyDict_GetItemString(fLocalNS,
"outputNames");
529 std::vector<std::string> fOutputNames;
530 for(
Py_ssize_t outputIter = 0; outputIter < PyList_Size(fPOutputs);++outputIter){
531 fOutputNames.push_back(
PyStringAsString(PyList_GetItem(fPOutputs,outputIter)));
548RModel Parse(std::string filepath,std::vector<std::vector<size_t>> inputShapes){
550 return Parse(filepath,inputShapes,dtype);
typedef void(GLAPIENTRYP _GLUfuncptr)(void)
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 AddBlasRoutines(std::vector< std::string > routines)
void AddNeededStdLib(std::string libname)
void AddOperator(std::unique_ptr< ROperator > op, int order_execution=-1)
static std::vector< size_t > GetDataFromList(PyObject *listObject)
Utility function which retrieves and returns the values of the List object as a vector of size_t.
static const char * PyStringAsString(PyObject *string)
Returns const char* from Python string in PyObject.
void PyRunString(TString code, TString errorMessage="Failed to run python code", int start=Py_single_input)
Execute Python code from string.
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
std::unique_ptr< ROperator > MakePyTorchGemm(PyObject *fNode)
Prepares a ROperator_Gemm object.
std::unique_ptr< ROperator > MakePyTorchNode(PyObject *fNode)
Prepares equivalent ROperator with respect to PyTorch ONNX node.
std::unique_ptr< ROperator > MakePyTorchConv(PyObject *fNode)
Prepares a ROperator_Conv object.
std::unique_ptr< ROperator > MakePyTorchSigmoid(PyObject *fNode)
Prepares a ROperator_Sigmoid object.
std::unique_ptr< ROperator > MakePyTorchSelu(PyObject *fNode)
Prepares a ROperator_Selu object.
std::unique_ptr< ROperator > MakePyTorchRelu(PyObject *fNode)
Prepares a ROperator_Relu object.
const PyTorchMethodMap mapPyTorchNode
std::unordered_map< std::string, std::unique_ptr< ROperator >(*)(PyObject *fNode)> PyTorchMethodMap
std::unique_ptr< ROperator > MakePyTorchTranspose(PyObject *fNode)
Prepares a ROperator_Transpose object.
static const char *(&) PyStringAsString(PyObject *)
static void(&) PyRunString(TString, PyObject *, PyObject *)
RModel Parse(std::string filepath, std::vector< std::vector< size_t > > inputShapes, std::vector< ETensorType > dtype)
Parser function for translating PyTorch .pt model into a RModel object.
std::string ConvertTypeToString(ETensorType type)
ETensorType ConvertStringToType(std::string type)
create variable transformations