Giter Club home page Giter Club logo

onnxparser-trt-plugin-sample's Introduction

onnxparser-trt-plugin-sample

It's a sample for onnxparser working with trt user defined plugins for TRT7.1. It implements grid sample op in torch introduced in this paper

Purposes

This complemetary sample works like a collection of purposes. It would like to demonstrate:

  1. How to export a custom op from torch via onnx
  2. How to parse an onnx model which contains TensorRT custom op into TensorRT using onnxparser
  3. How to enable dynamic shapes during this process
  4. How to write plugin supporting explicit batch and dynamic shape for this process
  5. How to write the python script to do so

Dependency

This project depends on:

  1. TensorRT 7.1
  2. CUDA 10+
  3. TensorRT OSS project

Prepare, Build and Run

(If below instructions cannot guide to run the sample successfully, please checkout commit fc251f67cb56241daf30e7b7fb4b7be02c8d07e8)

Follow instructions on TensorRT OSS project to prepare all env requirements. Make sure you can build TensorRT OSS project and run the sample.

In order to build the project successfully, remember to checkout release 7.1 or commit 30bb96724c90ba5d88cfcf6809f4cfcad86c32af of TensorRT OSS and TensorRT/parser/onnx.

You can choose to prepare this based on NGC docker image tensorrt 20.08

Once you being able to run the built samples, you can patch files here into the TensorRT OSS project

  1. copy TensorRT into TensorRT
  2. copy symbolic_opset10.py to /path/to/python/dist-packages/torch/onnx/, say within ngc container, it's /user/local/lib/python3.6/dist-packages/torch/onnx/

After the pacthing, you should cd into TensorRT/parsers/onnx, follow instructions to build onnx parser, link

Once built onnx parser, remember to make install and python setup.py build && python setup.py install to get it taking effect. (If it's not working, check whether /usr/local/lib is in your path)

After that, rebuild TensorRT OSS project.

Done. Run LD_PRELOAD=/PATH/TO/YOUR/BUILT/libnvinfer_plugin.so python test_plugin_result.py to see if it's working

How it works

Currently, to get torch-onnx-tensorrt working with custom op, you have to

  1. Let torch/onnx recoganize and export the custom op that not in standard opset, here we choose opset10. Thus we need to hack into symbolic_opset10.py. This is now done within the test_plugin_result.py script by manully register op into opset10 along with setting enable_onnx_checker=False during onnx export.
  2. Let onnxparser understand how to translate the custom op exists in onnx file to TensorRT layers including plugins. Thus we need to hack into builtin_op_importers.cpp
  3. Instead of hacking into onnxparser's source code, from TensorRT7.1, we support using onnxgraphsurgeon to modify the onnx model and replace the unknown node GridSampler with TRT_PluginV2 node, filled with corresponding buffer, refer to function modify_onnx().
  4. Let TensorRT know there's a new custom op named GridSampler. Here we implemented it as a plugin. Addtionally, since onnxparser only works with full dimension mode, we have to implement the trt plugin using IPluginV2DynamicExt introduced in TRT6.
  5. Dynamic shape can be used if you export onnx model using dynamic_axes as illustrated in test_plugin_result.py. This will be processed in onnx-tensorrt module and then addInput is called using -1 as dummpy input dim. About how to build engine and context for dynamic shape, please refer to test_plugin_result.py.

Limitations

  1. This is not officially supported, thus an experimental sample.
  2. Plugin namespace is not working.

TODO

  • FP16 support
  • dynamic shape support in c++ sample
  • dynamic shape support in python sample working with onnxparser
  • FP16 support in python sample
  • More tests to assure correctness
  • 3D support in grid sample

onnxparser-trt-plugin-sample's People

Contributors

trojanxu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

onnxparser-trt-plugin-sample's Issues

Converting from ONNX to Tensorflow

Thanks for the plugin. I converted the model from Pytorch to ONNX format.
How to convert it now to tensorflow format?

When I try to convert, I get an error:
` File "/home/user/anaconda3/envs/pytorch/lib/python3.7/site-packages/onnx_tf/backend.py", line 67, in prepare
super(TensorflowBackend, cls).prepare(model, device, **kwargs)
File "/home/user/anaconda3/envs/pytorch/lib/python3.7/site-packages/onnx/backend/base.py", line 76, in prepare
onnx.checker.check_model(model)
File "/home/user/anaconda3/envs/pytorch/lib/python3.7/site-packages/onnx/checker.py", line 106, in check_model
C.check_model(protobuf_string)
onnx.onnx_cpp2py_export.checker.ValidationError: No Op registered for TRT_PluginV2 with domain_version of 11

==> Context: Bad node spec for node. Name: GridSampler_1441 OpType: TRT_PluginV2`

Make it work in TRT6

Hi @TrojanXu,

Thanks for your wonderful work, it helps me immensely!

I have implemented it in TRT7 successfully on PC. However, for my platform is the Nvidia Drive Xavier, which is not able to support or upgrade to TRT7, I have to make it work in TRT6.
I have read your code test_plugin_result.py, in my opinion, you replaced GridSampler with TRT_PluginV2 which belongs to TRT7 ops set by using onnx-graphsurgeon of TRT7. Is there possibility to replace GridSampler with an op belongs to TRT6 by using onnx-graphsurgeon of TRT7, and save the modified .onnx file, then using the modified .onnx file directly in TRT6? For I think the TRT7 have to be used just because we have to use onnx-graphsurgeon.

I have compiled your plugin GridSampler in TRT6 without error occured.

Thanks and Regards,
AJ.

Error when converting onnx to tensorrt

Hi! I have already build the grid_sampler in the Tensorrt OSS project and convert my pytorch model to onnx. However it meets an error when I convert onnx to tensorrt. The error is shown below. Could you please tell me how to solve it?

[TensorRT] ERROR: INVALID_ARGUMENT: getPluginCreator could not find plugin ScatterND version 1
In node -1 (importFallbackPluginImporter): UNSUPPORTED_NODE: Assertion failed: creator && "Plugin not found, are the plugin name, version, and namespace correct?"
[TensorRT] ERROR: Network must have at least one output
[TensorRT] ERROR: Network validation failed.
Traceback (most recent call last):
File "zed_onnx2trt.py", line 9, in
trt_model = onnx2trt(model)
File "/home/nvidia/.local/lib/python3.6/site-packages/volksdep/converters/onnx2trt.py", line 119, in onnx2trt
trt_model = TRTModel(engine)
File "/home/nvidia/.local/lib/python3.6/site-packages/volksdep/converters/base.py", line 50, in init
self.context = self.engine.create_execution_context()
AttributeError: 'NoneType' object has no attribute 'create_execution_context'

Is plugin implementation on the TensorRT side necessary?

Hi,

First, thank you for this repo.

I understand that we need to implement custom layer on the onnx-tensorrt side inside builtin_op_importers.cpp in order tensorrt onnx parser (nvonnxparser) to be able to parse the custom layer. Shouldn't this be enough in order to parse the onnx model file and create a TensorRT inference engine?

I see that you implemented TensorRT plugin and even CUDA implementations for the grid sample op. I thought TensorRT plugins were necessary in order to parse unsupported layers by the uff or caffe parsers (maybe onnx also). But by just implementing custom layer inside builtin_op_importers.cpp and rebuilding onnx-tensorrt, nvonnxparser should be able to parse the model, shouldn't it?

Thanks in advance.

The example cannot work when plugin to a large model

When I use the method in this repo to export F.grid_sample in a large model, there is something wrong with the exported graph. The shapes of the inputs of GridSampler nodes are nonetype.

To reproduce

Change the model definition to (Note the +1 in the argument passed to F.grid_sample)

class MyModel(torch.nn.Module):
	def __init__(self):
		super(MyModel,self).__init__()

	def forward(self, input, grid):
		return F.grid_sample(input+1, grid, mode='bilinear', padding_mode='zeros', align_corners=True)

Then export the model, and print the nodeof op GridSampler with the following code.

def check_onnx(onnx_model_file):
	graph = gs.import_onnx(onnx.load(onnx_model_file))
	assert(graph is not None)
	for node in graph.nodes:
		if node.op == 'GridSampler':
			print(node)

And then the console prints

GridSampler_2 (GridSampler)
        Inputs: [Variable (3): (shape=None, dtype=None), Variable (grid): (shape=[1, 1, 128000, 2], dtype=float16)]
        Outputs: [Variable (4): (shape=[1, 17, 1, 128000], dtype=float16)]
Attributes: OrderedDict([('aligncorners', 1), ('interpolationmode', 0), ('paddingmode', 0)])

The desired behavior is that the shape and dtype of the input should not be None.

onnx_graphsurgeon

请问onnx_graphsurgeon是什么包?怎么安装?会提示找不到。

Cuda Runtime (an illegal memory access was encountered)

I build the TRT plugin using a makefile and used that in the trtexec to compile my onnx model which has F.grid_sample

While trying to execute it in the engine I get the error

1: [executionContext.cpp::executeInternal::667] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
1: [defaultAllocator.cpp::deallocate::42] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
1: [cudaResources.cpp::~ScopedCudaStream::47] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
1: [cudaResources.cpp::~ScopedCudaEvent::24] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
1: [cudaResources.cpp::~ScopedCudaEvent::24] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
1: [cudaResources.cpp::~ScopedCudaEvent::24] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
1: [cudaResources.cpp::~ScopedCudaEvent::24] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
1: [cudaResources.cpp::~ScopedCudaEvent::24] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
1: [cudaResources.cpp::~ScopedCudaEvent::24] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
1: [cudaResources.cpp::~ScopedCudaEvent::24] Error Code 1: Cuda Runtime (an illegal memory access was encountered)
1: [cudaResources.cpp::~ScopedCudaEvent::24] Error Code 1: Cuda Runtime (an illegal memory access was encountered)

I printed the inputs and there are

mBatch: 1
mInputChannel: 512
mInputHeight: 128
mInputWidth: 128
mGridHeight: 200
mGridWidth: 200
mInterpolationMode: Bilinear
mPaddingMode: Zeros
mAlignCorners: 0
dataType: half

How can I debug this issue?

Get inconsistent result with torch.nn.functional.grid_sample

The grid_sample plugin has inconsistent result with torch.nn.functional.grid_sample.

npy_files:
g_feat.npy: https://drive.google.com/file/d/18YPjH4R8GBew_LZdgziHwze2fMkaYvoP/view?usp=sharing
g_grid.npy: https://drive.google.com/file/d/18tOWjSN-rPUA6odTBBloS7_ERDQ-_a2N/view?usp=sharing

Code to reproduce is as follows,

def torch2onnx():
    import torch
    import numpy as np
    class Debug(torch.nn.Module):
        def __init__(self):
            super(Debug, self).__init__()

        def forward(self, feat, grid):
            return torch.nn.functional.grid_sample(feat, grid, 'bilinear', 'zeros', True)

    net = Debug().cuda()
    net.eval()
    feat = torch.from_numpy(np.load('g_feat.npy')).cuda()
    grid = torch.from_numpy(np.load('g_grid.npy')).cuda()
    with torch.no_grad():
        torch.onnx.export(
            net, (feat, grid), 'gs.onnx', verbose=True,
            input_names=['feat', 'grid'], output_names=['corr'],
            opset_version=16, do_constant_folding=True)

def check_torch_and_trt():
    trt_file = 'gs.trt'
    engine = load_engine(trt_file)

    context = engine.create_execution_context()

    feat = torch.from_numpy(np.load('g_feat.npy')).cuda()
    grid = torch.from_numpy(np.load('g_grid.npy')).cuda()

    out_list = [torch.from_numpy(np.load(key+'.npy')).cuda() for key in ['g_out']]

    out_pred = [torch.empty_like(item) for item in out_list]

    stream = cuda.Stream()
    bindings = [feat.data_ptr(), grid.data_ptr()] + [item.contiguous().data_ptr() for item in out_pred]

    context.execute_async_v2(bindings=bindings, stream_handle=stream.handle)
    #stream.synchronize()

    torch_out = torch.nn.functional.grid_sample(feat, grid, 'bilinear', 'zeros', True)
    print(torch.max(torch.abs(torch_out - out_pred[0])))

All values are 0.0 in output

Hi, I've added the all the 5 grid sample files to my example project written in TensorRT C++ API. Then, I feed an input and grid that I initialized in my main.cpp to the plugin layer in order to see how it works as follows:

nvinfer1::ITensor* input = network->addInput("INPUT", DataType::kFLOAT, nvinfer1::Dims{4, {1, 1, 4, 4}});
nvinfer1::ITensor* grid = network->addInput("GRID", DataType::kFLOAT, nvinfer1::Dims{4, {1, 8, 8, 2}});
assert(input); assert(grid);

auto interpolation_mode = torch::detail::GridSamplerInterpolation::Bilinear;
auto padding_mode = torch::detail::GridSamplerPadding::Zeros;
auto align_corners = true;

auto creator = getPluginRegistry()->getPluginCreator("GridSampler", "1");
const nvinfer1::PluginFieldCollection* pluginData = creator->getFieldNames();

nvinfer1::PluginFieldCollection mPFC;
std::vector<nvinfer1::PluginField> mPluginAttributes;
mPluginAttributes.emplace_back(nvinfer1::PluginField("interpolation_mode", &interpolation_mode,
                                                    nvinfer1::PluginFieldType::kINT32, 1));
mPluginAttributes.emplace_back(nvinfer1::PluginField("padding_mode", &padding_mode,
                                                    nvinfer1::PluginFieldType::kINT32, 1));
mPluginAttributes.emplace_back(nvinfer1::PluginField("align_corners", &align_corners,
                                                    nvinfer1::PluginFieldType::kINT32, 1));
mPFC.nbFields = mPluginAttributes.size();
mPFC.fields = mPluginAttributes.data();


nvinfer1::IPluginV2 *pluginObj = creator->createPlugin("GridSampler", &mPFC);
nvinfer1::ITensor* inputTensors[] = {input, grid};
auto grid_sample_plugin = network->addPluginV2(inputTensors, 2, *pluginObj);

grid_sample_plugin->getOutput(0)->setName("OUTPUT");
network->markOutput(*grid_sample_plugin->getOutput(0));

The code works but all the values of output are 0. I feed the same input and grid in python, so I know it should not be 0. I am using TensorRT 6.0 and CUDA 10.1. Any idea what I am doing wrong?

the output of engine is a array that all element are zeros

Hello, first of all thank you very much for the reference you provided on the custom plugin, but I meet some problems when using this project : I successfully registered this plugin, but when performing inference, the output of engine is a array that all element are zeros,I want to know, what should I do to get the correct output?

Issue with Grid Sampler while converting from Pytorch to ONNX

Hi @TrojanXu ,

I am trying to convert the Pytorch model to the ONNX model. But whie exporting I am facing an error as: RuntimeError: Exporting the operator grid_sampler to ONNX opset version 12 is not supported.

May I know how to resolve this issue?
As I have seen that you have written Grid sampler TRT plugin, so that can be used while converting from ONNX to TRT right? if yes then how do we have a ONNX model with grid sampler Op(which is not supported in ONNX)?

Thanks and Regards,
Darshan C G

UNSUPPORTED_NODE: No importer registered for op: GridSampler

hello, thanks for you proj.
I all process the same as your Readme.md, but I still got UNSUPPORTED_NODE: No importer registered for op: GridSampler when run : LD_PRELOAD=xxx/TensorRT/build/out/libnvinfer_plugin.so.7 python test_plugin_result.py

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.