[tmva][sofie] Add support for parsing external ONNX data file for weights#21048
[tmva][sofie] Add support for parsing external ONNX data file for weights#21048lmoneta wants to merge 14 commits intoroot-project:masterfrom
Conversation
Test Results 22 files 22 suites 3d 14h 51m 37s ⏱️ Results for commit 9e5074b. |
sanjibansg
left a comment
There was a problem hiding this comment.
Thanks for this implement, couple of comments on using a different local for loop variable.
| for (int i = 0; i < graph.initializer_size(); i++) { | ||
| onnx::TensorProto *tensorproto = const_cast<onnx::TensorProto *>(&graph.initializer(i)); | ||
| std::vector<std::size_t> shape; | ||
| std::size_t fLength = 1; | ||
| std::size_t tensor_length = 1; | ||
| for (int j = 0; j < tensorproto->dims_size(); j++) { | ||
| shape.push_back(tensorproto->dims(j)); | ||
| fLength *= tensorproto->dims(j); | ||
| tensor_length *= tensorproto->dims(j); | ||
| } | ||
| // in case of scalars keep an empty shape but with length =1 | ||
|
|
||
| std::string input_name = graph.initializer(i).name(); | ||
| std::string tensor_name = graph.initializer(i).name(); | ||
|
|
||
| if (verbose) | ||
| std::cout << "\t initializer " << i << " name " << input_name << " type " << graph.initializer(i).data_type() | ||
| << std::endl; | ||
| std::cout << "\t initializer " << i << " name " << tensor_name << " type " << graph.initializer(i).data_type() | ||
| << " and length " << tensor_length << std::endl; | ||
|
|
||
|
|
||
| // register also the initialized tensors | ||
| auto tensor_type = static_cast<ETensorType>(graph.initializer(i).data_type()); | ||
| RegisterTensorType(input_name, tensor_type); | ||
|
|
||
| switch (tensor_type) { | ||
| case ETensorType::FLOAT: { | ||
| std::shared_ptr<void> data = GetInitializedTensorData<float>(tensorproto, fLength); | ||
| if (verbose) std::cout << "add FLOAT initialized tensor " << input_name << " shape " << ConvertShapeToString(shape) << std::endl; | ||
| rmodel.AddInitializedTensor(input_name, ETensorType::FLOAT, shape, data); | ||
| allInitializedTensors[input_name] = i; | ||
| break; | ||
| } | ||
| case ETensorType::DOUBLE: { | ||
| std::shared_ptr<void> data = GetInitializedTensorData<double>(tensorproto, fLength); | ||
| if (verbose) std::cout << "add DOUBLE initialized tensor " << input_name << " shape " << ConvertShapeToString(shape) << std::endl; | ||
| rmodel.AddInitializedTensor(input_name, ETensorType::DOUBLE, shape, data); | ||
| allInitializedTensors[input_name] = i; | ||
| break; | ||
| } | ||
| case ETensorType::INT32: { | ||
| std::shared_ptr<void> data = GetInitializedTensorData<int32_t>(tensorproto, fLength); | ||
| if (verbose) std::cout << "add INT32 initialized tensor " << input_name << " shape " << ConvertShapeToString(shape) << std::endl; | ||
| rmodel.AddInitializedTensor(input_name, ETensorType::INT32, shape, data); | ||
| allInitializedTensors[input_name] = i; | ||
| break; | ||
| } | ||
| case ETensorType::INT64: { | ||
| std::shared_ptr<void> data = GetInitializedTensorData<int64_t>(tensorproto, fLength); | ||
| if (verbose) std::cout << "add INT64 initialized tensor " << input_name << " shape " << ConvertShapeToString(shape) << std::endl; | ||
| rmodel.AddInitializedTensor(input_name, ETensorType::INT64, shape, data); | ||
| allInitializedTensors[input_name] = i; | ||
| break; | ||
| } | ||
| default: | ||
| throw std::runtime_error("Data type in weight tensor " + graph.initializer(i).name() + " not supported!\n"); | ||
| RegisterTensorType(tensor_name, tensor_type); | ||
|
|
||
| std::shared_ptr<void> data = GetInitializedTensorData(tensorproto, tensor_length * GetTypeSize(tensor_type), tensor_type); | ||
| rmodel.AddInitializedTensor(tensor_name, tensor_type, shape, data); | ||
| allInitializedTensors[tensor_name] = i; | ||
|
|
||
| if (verbose) { | ||
| std::cout << "add initialized tensor " << tensor_name << "with shape " << ConvertShapeToString(shape) << "and "; | ||
| if (tensor_type == ETensorType::FLOAT) { | ||
| std::cout << " float data: "; | ||
| for (int i = 0; i < std::min(int(tensor_length),3); i++) std::cout << static_cast<float*>(data.get())[0] << " "; |
There was a problem hiding this comment.
As the warning says, probably better to use something else than i here for the for loop variable, since this shadows the previous one which might cause errors in the future.
| } | ||
| else if (tensor_type == ETensorType::INT64) { | ||
| std::cout << " int64 data: "; | ||
| for (int i = 0; i < std::min(int(tensor_length),3); i++) std::cout << static_cast<int64_t*>(data.get())[0] << " "; |
There was a problem hiding this comment.
Same comment on using a different loop variable here.
Add an implementation of ScatterND operator which is needed to parse the MLPF model from CMS Include also 3 tests to probe the different type of scattering wich can be performed
- Fix in operator Reduce to return a scalar and not a tensor of shape [1] - Fix handling of output boolean type in Cast. Do not convert type in a string, because a boolean is converted to a uint8_t which can be a native uint8_t or a bool. Avoid then calling function ConvertStrigToType if possible - Fix fusion of operators. Perform fusion not at first op encountered but at the last onem in order to parse before all operators which can provide an input to last fused one. This was the case in MLPF where there was a MatMul + Constant + Add, where COnstant is an input to Add. - remove check in Generate on empty shapes because scalars tensors have empty shapes
Fix also a bug when doing Gemm and applying the bias in case of stacked matrix multiplications. The bias was not correctly broadcasted in this case
The exponent in the softmax (and also the log in the logsoftmax) can be implemented using the vdt fast_exo and fast_log funcitons which are faster
Apply fixes to the new impelmentation of Where added in one of the previous commits
When doing Transpose do not loop on a global index, but per dimension and compute the correct input/output indices using the strides. This is much more efficient then computing the coordinate indices using modulo and divisions Add also fast case when last dimensions are contigous Clean up also some other files by removing some debug statements
Fix some bugs in those operators used by MLPF model.
|
This is great! It tripped me up several times that you get silently wrong results with SOFIE when you use external ONNX data files. Is there anything blocking this PR? |
Add a new test where the matrix B is changing for each batch DO not use empty scopes in Gemm (it is a problem for CLAD on MacOS) and instead configure the spacing depending if using stack multiplication
Add Clip operator and a test for it
In case of ParT the Gemm is computed using as input a bias fector (constructed from the interaction feature) which is not an initialized tensor and has rank > 2. Add in SOFIE support for bias vector with larger rank and for dynamic shapes This fixes parsing of the ParT model
Add new GELU operator and corrisponding tests Add also Atan and Floor operators as new unary operators Include in ONNX parser support for bool initialized data type when reading the model initialized data
b30d212 to
941b3d1
Compare
sanjibansg
left a comment
There was a problem hiding this comment.
LGTM! Thanks for this implementation.
…ghts Support external_data when parsing the initialized tensor from an ONNX file To test the feture, run tutorial RMVA_SOFIE_ONNX.py changing when exporting to the ONNX file from external_data=False to external_data=True
941b3d1 to
986600e
Compare
Support external_data when parsing the initialized tensor from an ONNX file To test the feture, run tutorial RMVA_SOFIE_ONNX.py changing when exporting to the ONNX file from external_data=False to external_data=True