PyTorch Custom ONNX Operator Export
Introduction
In my previous article “TensorRT Custom Plugin Example”, I discussed how to implement a TensorRT custom plugin and how to integrate the TensorRT custom plugin into a TensorRT engine from an ONNX model with an ONNX custom operator. The ONNX custom operator I used in the previous article was created from scratch using ONNX graph surgeon. However, in practice, when the ONNX model graph becomes more complex, performing ONNX graph surgeon to create ONNX custom operators might become very difficult. Therefore, exporting the ONNX custom operators from PyTorch modules directly is a more practical approach.
In this article, I will discuss how to export PyTorch modules to ONNX custom operators for TensorRT custom plugin integration.
PyTorch Custom ONNX Operator Export
PyTorch official tutorials “How to Export Pytorch Model with Custom Op to ONNX and Run it in ONNX Runtime” and “Extending the ONNX Registry” have also discussed how to export PyTorch modules to ONNX custom operators. However, the assumption of those tutorials is that the custom operator implementations are already available in the ONNX registry or have been built into PyTorch C++ extension so that it can be run with PyTorch in Python. This assumption might not be true in practice. For example, TensorRT custom plugins are not quite straightforward to be run as part of PyTorch and ONNX export forward pass.
In our use cases, we want to export PyTorch modules to ONNX custom operators without having to implement and integrate the custom operators into ONNX registry or PyTorch C++ extension.
ONNX Opset 15 or Above
To export an ONNX model using ONNX Opset 15 or above (ONNX IR >= 8), we can employ the export_modules_as_functions
argument in the torch.onnx.export
function. This argument is a dictionary that maps the PyTorch module to the ONNX custom operator function. TensorRT parser will be able to map the ONNX custom operator function to the TensorRT custom plugin.
1 | # Define a PyTorch identity neural network and export it to ONNX format with custom ONNX operators. |
ONNX Opset 14 or Below
To export an ONNX model using ONNX Opset 14 or below (ONNX IR < 8), the export_modules_as_functions
argument in the torch.onnx.export
function cannot be used. Instead, we will have to implement a PyTorch dummy torch.autograd.Function
that uses exactly the same IO tensors of the same shape and type and the correct forward implementation is not necessary if the downstream ONNX graph is not data dependent, register it as a PyTorch custom operator for the PyTorch module that we want to export as an ONNX custom operator, and wrap it in a PyTorch dummy module. During the export, we will just switch the the forward pass of the PyTorch module to the forward pass of the PyTorch dummy module.
1 | # Define a PyTorch identity neural network and export it to ONNX format with custom ONNX operators. |
Custom ONNX Operator and TensorRT Custom Plugin Validation
Using the TensorRT custom plugin, the TensorRT engine builder, and the TensorRT engine runner we created from the previous article, we can validate our ONNX custom operator export approaches.
1 | $ python scripts/export_identity_neural_network_new_opset.py |
1 | $ python scripts/export_identity_neural_network_old_opset.py |
Source Code
The source code of the example can be found in my GitHub repository “TensorRT Custom Plugin Example”.
References
PyTorch Custom ONNX Operator Export
https://leimao.github.io/blog/PyTorch-Custom-ONNX-Operator-Export/