Skip to content

Commit 1cf89dd

Browse files
committed
TneosrRT 7.1 ONNX-Parser open source release
1 parent 2eb74d9 commit 1cf89dd

35 files changed

+1908
-984
lines changed

CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
1+
# Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
22
#
33
# Permission is hereby granted, free of charge, to any person obtaining a
44
# copy of this software and associated documentation files (the "Software"),
@@ -42,7 +42,7 @@ set(PARSER_LINKER_SCRIPT ${ONNX2TRT_ROOT}/libnvonnxparser.version)
4242
# Version information
4343
#--------------------------------------------------
4444
set(ONNX2TRT_MAJOR 7)
45-
set(ONNX2TRT_MINOR 0)
45+
set(ONNX2TRT_MINOR 1)
4646
set(ONNX2TRT_PATCH 0)
4747

4848
#--------------------------------------------------
@@ -56,6 +56,8 @@ set(IMPORTER_SOURCES
5656
onnx2trt_utils.cpp
5757
ShapedWeights.cpp
5858
ShapeTensor.cpp
59+
LoopHelpers.cpp
60+
RNNHelpers.cpp
5961
OnnxAttrs.cpp
6062
)
6163

ImporterContext.hpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
2+
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),
@@ -48,8 +48,10 @@ class ImporterContext final : public IImporterContext
4848
mTensorNameCounts; // Keep track of how many times a tensor name shows up, to avoid duplicate naming in TRT.
4949
StringMap<size_t>
5050
mLayerNameCounts; // Keep track of how many times a tensor name shows up, to avoid duplicate naming in TRT.
51-
std::unordered_set<std::string> mUnsupportedShapeTensors; // Container to hold any shape tensors that are the output of layers that do not support shape tensors.
51+
std::unordered_set<std::string> mUnsupportedShapeTensors; // Container to hold output tensor names of layers that produce shape tensor outputs but do not natively support them.
5252
StringMap<std::string> mLoopTensors; // Container to map subgraph tensors to their original outer graph names.
53+
std::string mOnnxFileLocation; // Keep track of the directory of the parsed ONNX file
54+
5355
public:
5456
ImporterContext(nvinfer1::INetworkDefinition* network, nvinfer1::ILogger* logger)
5557
: _network(network)
@@ -88,7 +90,14 @@ class ImporterContext final : public IImporterContext
8890
{
8991
return mLoopTensors;
9092
}
91-
93+
virtual void setOnnxFileLocation(std::string location) override
94+
{
95+
mOnnxFileLocation = location;
96+
}
97+
virtual std::string getOnnxFileLocation() override
98+
{
99+
return mOnnxFileLocation;
100+
}
92101
// This actually handles weights as well, but is named this way to be consistent with the tensors()
93102
virtual void registerTensor(TensorOrWeights tensor, const std::string& basename) override
94103
{

LICENSE

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
MIT License
22

3-
Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
4-
Copyright (c) 2018 Open Neural Network Exchange
3+
Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
4+
Copyright (c) 2020 Open Neural Network Exchange
55

66
Permission is hereby granted, free of charge, to any person obtaining a copy
77
of this software and associated documentation files (the "Software"), to deal

LoopHelpers.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include "LoopHelpers.hpp"
2+
#include "onnx2trt_utils.hpp"
3+
4+
namespace onnx2trt
5+
{
6+
7+
nvinfer1::ITensor* addLoopCounter(IImporterContext* ctx, nvinfer1::ILoop* loop, int32_t initial)
8+
{
9+
nvinfer1::ITensor* initialTensor = addConstantScalar(ctx, initial, ::ONNX_NAMESPACE::TensorProto::INT32, nvinfer1::Dims{1, 1})->getOutput(0);
10+
nvinfer1::ITensor* one = addConstantScalar(ctx, 1, ::ONNX_NAMESPACE::TensorProto::INT32, nvinfer1::Dims{1, 1})->getOutput(0);
11+
12+
auto counter = loop->addRecurrence(*initialTensor);
13+
nvinfer1::ITensor* addOne = ctx->network()->addElementWise(*counter->getOutput(0), *one, nvinfer1::ElementWiseOperation::kSUM)->getOutput(0);
14+
counter->setInput(1, *addOne);
15+
return counter->getOutput(0);
16+
}
17+
18+
} // namespace onnx2trt

LoopHelpers.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#pragma once
2+
3+
#include <NvInfer.h>
4+
5+
#include "ImporterContext.hpp"
6+
7+
namespace onnx2trt
8+
{
9+
10+
nvinfer1::ITensor* addLoopCounter(IImporterContext* ctx, nvinfer1::ILoop* loop, int32_t initial = 0);
11+
12+
} // namespace onnx2trt

ModelImporter.cpp

Lines changed: 59 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
2+
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),
@@ -31,6 +31,7 @@
3131
#include <google/protobuf/text_format.h>
3232

3333
#include <limits>
34+
#include <functional>
3435
#include <unordered_set>
3536

3637
namespace onnx2trt
@@ -81,8 +82,7 @@ Status setStringMap(
8182
return Status::success();
8283
}
8384

84-
Status parseGraph(
85-
IImporterContext* ctx, const ::ONNX_NAMESPACE::GraphProto& graph, bool deserializingINetwork, int* currentNode)
85+
Status parseGraph(IImporterContext* ctx, const ::ONNX_NAMESPACE::GraphProto& graph, bool deserializingINetwork, int* currentNode)
8686
{
8787
// Import initializers.
8888
for (const ::ONNX_NAMESPACE::TensorProto& initializer : graph.initializer())
@@ -129,17 +129,19 @@ Status parseGraph(
129129
LOG_VERBOSE(ssInputs.str());
130130

131131
// Dispatch to appropriate converter.
132-
if (!opImporters.count(node.op_type()))
132+
const NodeImporter* importFunc{nullptr};
133+
if (opImporters.count(node.op_type()))
133134
{
134-
return MAKE_ERROR("No importer registered for op: " + node.op_type(), ErrorCode::kUNSUPPORTED_NODE);
135+
importFunc = &opImporters.at(node.op_type());
136+
}
137+
else
138+
{
139+
LOG_INFO("No importer registered for op: " << node.op_type() << ". Attempting to import as plugin.");
140+
importFunc = &opImporters.at("FallbackPluginImporter");
135141
}
136-
const NodeImporter& importFunc = opImporters.at(node.op_type());
137142
std::vector<TensorOrWeights> outputs;
138143

139-
const int nbLayersBefore = ctx->network()->getNbLayers();
140-
GET_VALUE(importFunc(ctx, node, nodeInputs), &outputs);
141-
142-
ctx->registerLayer(ctx->network()->getLayer(nbLayersBefore), node.name());
144+
GET_VALUE((*importFunc)(ctx, node, nodeInputs), &outputs);
143145

144146
if (deserializingINetwork)
145147
{
@@ -333,6 +335,7 @@ bool ModelImporter::supportsModel(
333335
}
334336
}
335337
auto* ctx = &_importer_ctx;
338+
336339
auto checkForInput = [&input_node, &ctx](::ONNX_NAMESPACE::NodeProto const& node) {
337340
for (auto input : node.input())
338341
{
@@ -344,6 +347,28 @@ bool ModelImporter::supportsModel(
344347
return false;
345348
};
346349

350+
auto checkForShapeTensors = [&ctx](::ONNX_NAMESPACE::NodeProto const& node){
351+
for (int i = 0; i < ctx->network()->getNbInputs(); i++)
352+
{
353+
auto input = ctx->network()->getInput(i);
354+
if (input->isShapeTensor())
355+
{
356+
if (input->getType() == nvinfer1::DataType::kFLOAT || node.op_type() == "Loop" || node.op_type() == "Scan")
357+
{
358+
auto name = input->getName();
359+
for (auto input : node.input())
360+
{
361+
if (input == name)
362+
{
363+
return true;
364+
}
365+
}
366+
}
367+
}
368+
}
369+
return false;
370+
};
371+
347372
bool newSubGraph(true);
348373
// Sort and partition supported subgraphs
349374
std::vector<size_t> topological_order;
@@ -356,19 +381,19 @@ bool ModelImporter::supportsModel(
356381
for (int node_idx : topological_order)
357382
{
358383
::ONNX_NAMESPACE::NodeProto const& node = model.graph().node(node_idx);
359-
360384
// Add the node to the subgraph if:
361-
// 1. Importer function is registered for the operator type
362-
// 2. It is NOT directly connected to an unsupported input
363-
// 3. Parsing did NOT hit an error on the node
364-
// 4. Any shape tensor output is coming from a supported node
385+
// 1. There is an importer function registered for the operator type
386+
// 2. It is not directly connected to an unsupported input
387+
// 3. It is not directly connected to an unsupported shape tensor input
388+
// 4. It did not illegally produce a shape tensor output
389+
// 5. It was sucessfully parsed
365390
bool registered = supportsOperator(node.op_type().c_str());
366391
bool containsInput = (input_node.empty()) ? false : checkForInput(node);
392+
bool containsShapeInput = checkForShapeTensors(node);
393+
auto tensorName = node.name();
394+
bool supportedShapeTensor = ctx->unsupportedShapeTensors().count(tensorName) == 0 ? true : false;
367395
bool containsIndex = node_idx == error_node;
368-
auto const tensor = node.output(0);
369-
bool supportedShapeTensorOutput = ctx->unsupportedShapeTensors().count(tensor) == 0 ? true : false;
370-
371-
if (registered && !containsInput && !containsIndex && supportedShapeTensorOutput)
396+
if (registered && !containsInput && !containsShapeInput && supportedShapeTensor && !containsIndex)
372397
{
373398
if (newSubGraph)
374399
{
@@ -383,6 +408,7 @@ bool ModelImporter::supportsModel(
383408
}
384409
else
385410
{
411+
std::cout << "Found unsupported node: " << tensorName << std::endl;
386412
// This is not a supported node, reset newSubGraph
387413
newSubGraph = true;
388414
allSupported = false;
@@ -440,31 +466,29 @@ void removeShapeTensorCasts(IImporterContext* ctx)
440466
for (int i = 0, e = ctx->network()->getNbLayers(); i < e; ++i)
441467
{
442468
nvinfer1::ILayer* layer = ctx->network()->getLayer(i);
443-
constexpr nvinfer1::DataType SHAPE_TENSOR_TYPE = nvinfer1::DataType::kINT32;
444469
if (layer->getNbOutputs() > 0 && layer->getOutput(0)->isShapeTensor())
445470
{
446-
layer->resetPrecision();
447471
layer->resetOutputType(0);
448-
layer->setPrecision(SHAPE_TENSOR_TYPE);
449-
layer->setOutputType(0, SHAPE_TENSOR_TYPE);
450472
nvinfer1::ITensor& t = *layer->getOutput(0);
473+
// Assume that boolean tensors were not cast, and thus have their type correctly set.
474+
const nvinfer1::DataType shapeTensorType = t.getType() == nvinfer1::DataType::kBOOL ? nvinfer1::DataType::kBOOL : nvinfer1::DataType::kINT32;
475+
layer->setOutputType(0, shapeTensorType);
451476
// Set type only if necessary, to avoid TensorRT warnings
452477
// about setting type of non-input/output tensors.
453-
if (t.getType() != SHAPE_TENSOR_TYPE)
478+
if (t.getType() != shapeTensorType)
454479
{
455-
t.setType(SHAPE_TENSOR_TYPE);
480+
t.setType(shapeTensorType);
456481
}
457482
// Some layers do not support shape tensor outputs. Keep track of these tensor names
458483
// for supportsModel().
459484
auto type = layer->getType();
460-
auto elementwiseOp = layer->getType() == nvinfer1::LayerType::kELEMENTWISE ? (static_cast<nvinfer1::IElementWiseLayer*>(layer))->getOperation() : nvinfer1::ElementWiseOperation::kSUM;
461-
auto reduceOp = layer->getType() == nvinfer1::LayerType::kREDUCE ? (static_cast<nvinfer1::IReduceLayer*>(layer))->getOperation() : nvinfer1::ReduceOperation::kSUM;
462-
485+
auto elementwiseOp = type == nvinfer1::LayerType::kELEMENTWISE ? (static_cast<nvinfer1::IElementWiseLayer*>(layer))->getOperation() : nvinfer1::ElementWiseOperation::kSUM;
486+
auto reduceOp = type == nvinfer1::LayerType::kREDUCE ? (static_cast<nvinfer1::IReduceLayer*>(layer))->getOperation() : nvinfer1::ReduceOperation::kSUM;
463487
if (!supportsShapeTensor(type, elementwiseOp, reduceOp))
464488
{
465-
auto name = layer->getOutput(0)->getName();
489+
auto name = layer->getName();
466490
ctx->unsupportedShapeTensors().insert(name);
467-
LOG_ERROR("Found " << name << " as a shape tensor output from a layer that does not support it!");
491+
LOG_ERROR("Found unsupported shape-tensor producing layer:" << name);
468492
}
469493
}
470494
}
@@ -477,7 +501,7 @@ Status ModelImporter::importModel(
477501
auto* ctx = &_importer_ctx;
478502
_importer_ctx.clearOpsets();
479503
// Initialize plugin registry
480-
initLibNvInferPlugins(static_cast<void*>(&ctx->logger()), "ONNXTRT_NAMESPACE");
504+
initLibNvInferPlugins(static_cast<void*>(&ctx->logger()), "");
481505
for (int i = 0; i < model.opset_import().size(); ++i)
482506
{
483507
std::string domain = model.opset_import(i).domain();
@@ -486,9 +510,7 @@ Status ModelImporter::importModel(
486510
// ONNX spec says that the default domain is either an empty string or is "ai.onnx".
487511
if ((domain.empty() || domain == "ai.onnx") && version < 7)
488512
{
489-
LOG_WARNING(
490-
"TensorRT supports ONNX graphs generated with at least opset 7. Models using older opsets are not "
491-
"guaranteed to work.");
513+
LOG_WARNING("TensorRT supports ONNX graphs generated with at least opset 7. Models using older opsets are not guaranteed to work.");
492514
}
493515
_importer_ctx.addOpset(domain, version);
494516
}
@@ -630,6 +652,9 @@ bool ModelImporter::parseFromFile(const char* onnxModelFile, int verbosity)
630652
return EXIT_FAILURE;
631653
}
632654

655+
// Keep track of the absolute path to the ONNX file.
656+
_importer_ctx.setOnnxFileLocation(onnxModelFile);
657+
633658
if (verbosity >= (int) nvinfer1::ILogger::Severity::kWARNING)
634659
{
635660
int64_t opset_version = (onnx_model.opset_import().size() ? onnx_model.opset_import(0).version() : 0);

ModelImporter.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
2+
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),

NvOnnxParser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
2+
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),

NvOnnxParser.h

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
2+
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),
@@ -27,6 +27,12 @@
2727
#include <stddef.h>
2828
#include <vector>
2929

30+
//!
31+
//! \file NvOnnxParser.h
32+
//!
33+
//! This is the API for the ONNX Parser
34+
//!
35+
3036
#define NV_ONNX_PARSER_MAJOR 0
3137
#define NV_ONNX_PARSER_MINOR 1
3238
#define NV_ONNX_PARSER_PATCH 0
@@ -122,7 +128,7 @@ class IParser
122128
* This method has very limited diagnostic. If parsing the serialized model
123129
* fails for any reason (e.g. unsupported IR version, unsupported opset, etc.)
124130
* it the user responsibility to intercept and report the error.
125-
* To obtain a better diagnostic, use the parseFromFile method below.
131+
* To obtain a better diagnostic, use the parseFromFile method below.
126132
*
127133
* \param serialized_onnx_model Pointer to the serialized ONNX model
128134
* \param serialized_onnx_model_size Size of the serialized ONNX model
@@ -134,14 +140,14 @@ class IParser
134140
size_t serialized_onnx_model_size)
135141
= 0;
136142

137-
/** \brief Parse an onnx model file, can be a binary protobuf or a text onnx model
138-
* calls parse method inside.
143+
/** \brief Parse an onnx model file, can be a binary protobuf or a text onnx model
144+
* calls parse method inside.
139145
*
140146
* \param File name
141147
* \param Verbosity Level
142-
*
148+
*
143149
* \return true if the model was parsed successfully
144-
*
150+
*
145151
*/
146152
virtual bool parseFromFile(const char* onnxModelFile, int verbosity) = 0;
147153

OnnxAttrs.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
2+
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),
@@ -23,6 +23,7 @@
2323
#include "OnnxAttrs.hpp"
2424
#include "ShapedWeights.hpp"
2525
#include "onnx2trt_utils.hpp"
26+
#include <onnx/onnx_pb.h>
2627

2728
template <>
2829
float OnnxAttrs::get<float>(const std::string& key) const
@@ -109,10 +110,10 @@ onnx2trt::ShapedWeights OnnxAttrs::get<onnx2trt::ShapedWeights>(const std::strin
109110
{
110111
::ONNX_NAMESPACE::TensorProto const& onnx_weights_tensor = this->at(key)->t();
111112
onnx2trt::ShapedWeights weights;
112-
// Return empty weights if conversion failed
113-
if (!convertOnnxWeights(onnx_weights_tensor, &weights, mCtx))
113+
bool success = convertOnnxWeights(onnx_weights_tensor, &weights, mCtx);
114+
if (!success)
114115
{
115-
return onnx2trt::ShapedWeights::empty(::ONNX_NAMESPACE::TensorProto_DataType_FLOAT);
116+
throw std::runtime_error{"Unable to convert ONNX weights"};
116117
}
117118
return weights;
118119
}

0 commit comments

Comments
 (0)