Skip to content

Commit 1da7332

Browse files
kevinch-nvjywu-msftrajeevsrao
authored
TensorRT 8.4 GA ONNX Parser Release (#851)
* TensorRT 8.4 EA ONNX Parser Release * support protobuf >= 3.11 (#812) Signed-off-by: George Wu <jywu@microsoft.com> * missed other sections for supporting >= protobuf 3.11 (#817) * missed one other section for supporting >= protobuf 3.11 Signed-off-by: George Wu <jywu@microsoft.com> * one more section Signed-off-by: George Wu <jywu@microsoft.com> * fix ident Signed-off-by: George Wu <jywu@microsoft.com> * TensorRT 8.4-GA ONNX Parser Release * TensorRT 8.4.1.5 updates (#849) Signed-off-by: Rajeev Rao <rajeevrao@nvidia.com> Co-authored-by: George Wu <jywu@microsoft.com> Co-authored-by: Rajeev Rao <rajeevsrao@users.noreply.github.com>
1 parent 4ebfd96 commit 1da7332

26 files changed

+3948
-615
lines changed

CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ add_definitions("-DSOURCE_LENGTH=${SOURCE_LENGTH}")
2828
# Version information
2929
#--------------------------------------------------
3030
set(ONNX2TRT_MAJOR 8)
31-
set(ONNX2TRT_MINOR 2)
31+
set(ONNX2TRT_MINOR 4)
3232
set(ONNX2TRT_PATCH 1)
3333
set(ONNX2TRT_VERSION "${ONNX2TRT_MAJOR}.${ONNX2TRT_MINOR}.${ONNX2TRT_PATCH}" CACHE STRING "ONNX2TRT version")
3434

@@ -42,6 +42,7 @@ set(IMPORTER_SOURCES
4242
builtin_op_importers.cpp
4343
onnx2trt_utils.cpp
4444
onnxErrorRecorder.cpp
45+
ImporterContext.cpp
4546
ShapedWeights.cpp
4647
ShapeTensor.cpp
4748
LoopHelpers.cpp

ConditionalHelpers.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,23 @@ Status addConditionalInputLayer(IImporterContext* ctx, nvinfer1::IIfConditional*
7171

7272
// Take a snapshot of the network before and after parsing the subgraph and return a list
7373
// of newly added network layers.
74-
Status importSubgraph(
75-
IImporterContext* ctx, const ::ONNX_NAMESPACE::GraphProto& subgraph, std::vector<nvinfer1::ILayer*>& newLayers)
74+
Status importSubgraph(IImporterContext* ctx, ::ONNX_NAMESPACE::GraphProto const& subgraph,
75+
std::vector<nvinfer1::ILayer*>& newLayers, StringMap<TensorOrWeights>& subgraphTensors)
7676
{
7777
auto net = ctx->network();
7878
int32_t beforeSubgraph = net->getNbLayers();
79+
80+
// Establish scope for names local to the subgraph.
81+
NameScope nameScope(*ctx);
82+
7983
CHECK(onnx2trt::parseGraph(ctx, subgraph));
8084

85+
for (int32_t i = 0; i < subgraph.output_size(); ++i)
86+
{
87+
std::string name = subgraph.output(i).name();
88+
subgraphTensors.emplace(std::make_pair(name, ctx->tensors().at(name)));
89+
}
90+
8191
for (int32_t i = beforeSubgraph; i < net->getNbLayers(); i++)
8292
{
8393
newLayers.push_back(net->getLayer(i));
@@ -135,8 +145,9 @@ Status addIfInputLayers(IImporterContext* ctx, nvinfer1::IIfConditional* conditi
135145

136146
// Add an IConditionalOutputLayer to `layer`'s outputs.
137147
Status addIfOutputLayers(IImporterContext* ctx, nvinfer1::IIfConditional* conditional,
138-
const ::ONNX_NAMESPACE::GraphProto& thenGraph, const std::vector<nvinfer1::ILayer*>& thenLayers,
139-
const ::ONNX_NAMESPACE::GraphProto& elseGraph, const std::vector<nvinfer1::ILayer*>& elseLayers,
148+
::ONNX_NAMESPACE::GraphProto const& thenGraph, std::vector<nvinfer1::ILayer*> const& thenLayers,
149+
StringMap<TensorOrWeights> const& thenSubgraphTensors, ::ONNX_NAMESPACE::GraphProto const& elseGraph,
150+
std::vector<nvinfer1::ILayer*> const& elseLayers, StringMap<TensorOrWeights> const& elseSubgraphTensors,
140151
std::vector<TensorOrWeights>& graphOutputs)
141152
{
142153
// Reported outputs are outputs that the ONNX model reports as subgraph outputs. This list is
@@ -166,7 +177,8 @@ Status addIfOutputLayers(IImporterContext* ctx, nvinfer1::IIfConditional* condit
166177
// Retrieve the output tensors of a subgraph (tensors exiting the subgraph).
167178
auto getSubgraphOutputTensors
168179
= [](IImporterContext* ctx, std::vector<nvinfer1::ITensor*>& sgOutputs, SubgraphPortsMap& subgraphOutputs,
169-
const ::ONNX_NAMESPACE::GraphProto& subgraph, std::vector<nvinfer1::ILayer*> subgraphLayers) {
180+
::ONNX_NAMESPACE::GraphProto const& subgraph, std::vector<nvinfer1::ILayer*> subgraphLayers,
181+
StringMap<TensorOrWeights> const& subgraphTensors) {
170182
for (const auto& layer : subgraphLayers)
171183
{
172184
const auto layerName = layer->getName();
@@ -184,17 +196,18 @@ Status addIfOutputLayers(IImporterContext* ctx, nvinfer1::IIfConditional* condit
184196
for (int32_t outIdx = 0; outIdx < nbOutputs; outIdx++)
185197
{
186198
const auto thenName = subgraph.output(outIdx).name();
187-
auto* thenTensor = &convertToTensor(ctx->tensors().at(thenName), ctx);
199+
TensorOrWeights tw = subgraphTensors.at(thenName);
200+
auto* thenTensor = &convertToTensor(tw, ctx);
188201
sgOutputs.push_back(thenTensor);
189202
}
190203
}
191204
};
192205

193206
std::vector<nvinfer1::ITensor*> thenOutputTensors;
194-
getSubgraphOutputTensors(ctx, thenOutputTensors, thenOutputs, thenGraph, thenLayers);
207+
getSubgraphOutputTensors(ctx, thenOutputTensors, thenOutputs, thenGraph, thenLayers, thenSubgraphTensors);
195208

196209
std::vector<nvinfer1::ITensor*> elseSGOutputTensors;
197-
getSubgraphOutputTensors(ctx, elseSGOutputTensors, elseOutputs, elseGraph, elseLayers);
210+
getSubgraphOutputTensors(ctx, elseSGOutputTensors, elseOutputs, elseGraph, elseLayers, elseSubgraphTensors);
198211

199212
ASSERT(thenOutputTensors.size() == elseSGOutputTensors.size()
200213
&& "The then/else branches of an If operator must have the same number of outputs.",

ConditionalHelpers.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ Status getSubgraphOutputs(const std::vector<nvinfer1::ILayer*>& newLayers,
3434

3535
// Take a snapshot of the network before and after parsing the subgraph and return a list
3636
// of newly added network layers.
37-
Status importSubgraph(
38-
IImporterContext* ctx, const ::ONNX_NAMESPACE::GraphProto& subgraph, std::vector<nvinfer1::ILayer*>& newLayers);
37+
Status importSubgraph(IImporterContext* ctx, ::ONNX_NAMESPACE::GraphProto const& subgraph,
38+
std::vector<nvinfer1::ILayer*>& newLayers, StringMap<TensorOrWeights>& subgraphTensors);
3939

4040
using InputsMap = std::unordered_map<std::string, nvinfer1::IIfConditionalInputLayer*>;
4141

@@ -45,8 +45,9 @@ onnx2trt::Status addIfInputLayers(IImporterContext* ctx, nvinfer1::IIfConditiona
4545

4646
// Add IIfConditionalOutputLayers to the outputs of the subgraph indicated by `subgraph`.
4747
onnx2trt::Status addIfOutputLayers(IImporterContext* ctx, nvinfer1::IIfConditional* conditional,
48-
const ::ONNX_NAMESPACE::GraphProto& thenGraph, const std::vector<nvinfer1::ILayer*>& thenLayers,
49-
const ::ONNX_NAMESPACE::GraphProto& elseGraph, const std::vector<nvinfer1::ILayer*>& elseLayers,
48+
::ONNX_NAMESPACE::GraphProto const& thenGraph, std::vector<nvinfer1::ILayer*> const& thenLayers,
49+
StringMap<TensorOrWeights> const& thenSubgraphTensors, ::ONNX_NAMESPACE::GraphProto const& elseGraph,
50+
std::vector<nvinfer1::ILayer*> const& elseLayers, StringMap<TensorOrWeights> const& elseSubgraphTensors,
5051
std::vector<TensorOrWeights>& graphOutputs);
5152

5253
} // namespace onnx2trt

ImporterContext.cpp

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
#include "ImporterContext.hpp"
2+
3+
namespace onnx2trt
4+
{
5+
6+
void ImporterContext::pushBaseNameScope()
7+
{
8+
mBaseNameScopeStack.push_back({});
9+
}
10+
11+
void ImporterContext::popBaseNameScope()
12+
{
13+
auto& tensorMap = tensors();
14+
for (auto& binding : mBaseNameScopeStack.back())
15+
{
16+
if (binding.second.first)
17+
{
18+
tensorMap.erase(binding.first);
19+
}
20+
else
21+
{
22+
tensorMap.at(binding.first) = std::move(binding.second.second);
23+
}
24+
}
25+
mBaseNameScopeStack.pop_back();
26+
}
27+
28+
void ImporterContext::registerTensor(TensorOrWeights tensor, std::string const& basename)
29+
{
30+
// TRT requires unique tensor names.
31+
std::string const& uniqueName = generateUniqueName(mTensorNames, basename);
32+
33+
if (tensor)
34+
{
35+
if (tensor.is_tensor())
36+
{
37+
tensor.tensor().setName(uniqueName.c_str());
38+
// Logging macro refers to ctx.
39+
auto* ctx = this;
40+
LOG_VERBOSE("Registering tensor: " << uniqueName << " for ONNX tensor: " << basename);
41+
}
42+
else if (tensor.is_weights())
43+
{
44+
auto const& weights = tensor.weights();
45+
if (tensor.weights().type == ::ONNX_NAMESPACE::TensorProto::INT64)
46+
{
47+
tensor = ShapedWeights{::ONNX_NAMESPACE::TensorProto::INT32,
48+
convertINT64(reinterpret_cast<int64_t*>(weights.values), weights.shape, this), weights.shape};
49+
}
50+
// It may be possible for nested subgraphs to have different values for the same initializer.
51+
// For multiple name scopes - use unique name to keep track of weights.
52+
if (!mBaseNameScopeStack.empty())
53+
{
54+
tensor.weights().setName(uniqueName.c_str());
55+
}
56+
else
57+
{
58+
tensor.weights().setName(basename.c_str());
59+
}
60+
}
61+
}
62+
63+
auto const p = this->tensors().emplace(basename, TensorOrWeights{});
64+
bool nameIsDuplicate = false;
65+
if (!mBaseNameScopeStack.empty())
66+
{
67+
// Remember original binding so it can be restored when scope is popped.
68+
auto const q
69+
= mBaseNameScopeStack.back().emplace(basename, std::make_pair(p.second, std::move(p.first->second)));
70+
// Check that scope did not already have a binding for basename.
71+
nameIsDuplicate = !q.second;
72+
}
73+
else
74+
{
75+
// The condition here accounts for ModelImporter::importModel reserving
76+
// output names by registering null tensors.
77+
nameIsDuplicate = !p.second && !p.first->second.isNullTensor();
78+
}
79+
if (nameIsDuplicate)
80+
{
81+
throw std::runtime_error("ONNX graph has duplicate tensor name: " + basename);
82+
}
83+
p.first->second = std::move(tensor);
84+
}
85+
86+
void ImporterContext::registerLayer(nvinfer1::ILayer* layer, std::string const& basename)
87+
{
88+
// No layer will be added for Constant nodes in ONNX.
89+
if (layer)
90+
{
91+
std::string const name = basename.empty() ? layer->getName() : basename;
92+
std::string const& uniqueName = generateUniqueName(mLayerNames, name);
93+
94+
auto* ctx = this; // To enable logging.
95+
LOG_VERBOSE("Registering layer: " << uniqueName << " for ONNX node: " << basename);
96+
97+
layer->setName(uniqueName.c_str());
98+
if (layer->getType() == nvinfer1::LayerType::kCONSTANT)
99+
{
100+
if (basename != uniqueName)
101+
{
102+
LOG_ERROR("Constant layer: " << uniqueName << " can be a duplicate of: " << basename);
103+
assert(!"Internal error: duplicate constant layers for the same weights");
104+
}
105+
mConstantLayers.insert({uniqueName, static_cast<nvinfer1::IConstantLayer*>(layer)});
106+
}
107+
}
108+
}
109+
110+
} // namespace onnx2trt

ImporterContext.hpp

Lines changed: 49 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
#include "onnxErrorRecorder.hpp"
1010
#include "onnx/common/stl_backports.h"
1111
#include <list>
12+
#include <string>
1213
#include <unordered_map>
14+
#include <utility>
1315

1416
namespace onnx2trt
1517
{
@@ -84,8 +86,24 @@ class ImporterContext final : public IImporterContext
8486
int64_t mSuffixCounter{0}; // increasing suffix counter used to uniquify layer names.
8587
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.
8688
StringMap<std::string> mLoopTensors; // Container to map subgraph tensors to their original outer graph names.
87-
std::string mOnnxFileLocation; // Keep track of the directory of the parsed ONNX file
89+
std::string mOnnxFileLocation; // Keep track of the directory of the parsed ONNX file
8890
std::unique_ptr<ErrorRecorderWrapper> mErrorWrapper; // error recorder to control TRT errors
91+
StringMap<nvinfer1::IConstantLayer*> mConstantLayers;
92+
93+
//! Stack of names defined by nested ONNX graphs, with information about how to
94+
//! restore their associated values when popping back to the surrounding scope.
95+
//!
96+
//! The stack is empty when processing the top-level ONNX graph.
97+
//! back() corresponds to the innermost ONNX graph being processed.
98+
//!
99+
//! For each entry {name, {bool, TensorOrWeights}}:
100+
//!
101+
//! * If the bool is true, the name was newly introduced by the scope.
102+
//!
103+
//! * If the bool is false, the name shadows a name in a surrounding scope,
104+
//! and TensorOrWeights was the name's value before being shadowed.
105+
//!
106+
std::vector<StringMap<std::pair<bool, TensorOrWeights>>> mBaseNameScopeStack;
89107

90108
public:
91109
ImporterContext(nvinfer1::INetworkDefinition* network, nvinfer1::ILogger* logger)
@@ -134,52 +152,15 @@ class ImporterContext final : public IImporterContext
134152
{
135153
return mOnnxFileLocation;
136154
}
137-
// This actually handles weights as well, but is named this way to be consistent with the tensors()
138-
void registerTensor(TensorOrWeights tensor, const std::string& basename) override
139-
{
140-
// TRT requires unique tensor names.
141-
const std::string uniqueName = generateUniqueName(mTensorNames, basename);
142155

143-
if (tensor)
144-
{
145-
auto* ctx = this; // To enable logging.
146-
if (tensor.is_tensor())
147-
{
148-
tensor.tensor().setName(uniqueName.c_str());
156+
void pushBaseNameScope() override;
149157

150-
LOG_VERBOSE("Registering tensor: " << uniqueName << " for ONNX tensor: " << basename);
151-
}
152-
else if (tensor.is_weights())
153-
{
154-
const auto& weights = tensor.weights();
155-
if (tensor.weights().type == ::ONNX_NAMESPACE::TensorProto::INT64)
156-
{
157-
tensor = ShapedWeights{::ONNX_NAMESPACE::TensorProto::INT32,
158-
convertINT64(reinterpret_cast<int64_t*>(weights.values), weights.shape, ctx), weights.shape};
159-
}
160-
tensor.weights().setName(basename.c_str());
161-
}
158+
void popBaseNameScope() override;
162159

163-
}
164-
// Overwrite previous tensors registered with the same name (this only happens when there are subgraphs,
165-
// and in that case, overwriting is the desired behavior).
166-
this->tensors()[basename] = std::move(tensor);
167-
}
168-
169-
void registerLayer(nvinfer1::ILayer* layer, const std::string& basename) override
170-
{
171-
// No layer will be added for Constant nodes in ONNX.
172-
if (layer)
173-
{
174-
const std::string name = basename.empty() ? layer->getName() : basename;
175-
const std::string uniqueName = generateUniqueName(mLayerNames, name);
176-
177-
auto* ctx = this; // To enable logging.
178-
LOG_VERBOSE("Registering layer: " << uniqueName << " for ONNX node: " << basename);
160+
// This actually handles weights as well, but is named this way to be consistent with the tensors()
161+
void registerTensor(TensorOrWeights tensor, std::string const& basename) override;
179162

180-
layer->setName(uniqueName.c_str());
181-
}
182-
}
163+
void registerLayer(nvinfer1::ILayer* layer, std::string const& basename) override;
183164

184165
nvinfer1::ILogger& logger() override
185166
{
@@ -188,16 +169,10 @@ class ImporterContext final : public IImporterContext
188169

189170
ShapedWeights createTempWeights(ShapedWeights::DataType type, nvinfer1::Dims shape, uint8_t value = 0) override
190171
{
172+
std::string const& name = generateUniqueName(mTensorNames, "tmp_weight");
191173
ShapedWeights weights(type, nullptr, shape);
192-
// Need special logic for handling scalars.
193-
if (shape.nbDims == 0)
194-
{
195-
mTempBufs.push_back(std::vector<uint8_t>(getDtypeSize(type), value));
196-
}
197-
else
198-
{
199-
mTempBufs.push_back(std::vector<uint8_t>(weights.size_bytes(), value));
200-
}
174+
weights.setName(name.c_str());
175+
mTempBufs.push_back(std::vector<uint8_t>(weights.size_bytes(), value));
201176
weights.values = mTempBufs.back().data();
202177
return weights;
203178
}
@@ -256,8 +231,13 @@ class ImporterContext final : public IImporterContext
256231
{
257232
return mOpsets.begin()->second;
258233
}
234+
else if (mOpsets.count(domain))
235+
{
236+
return mOpsets.at(domain);
237+
}
259238
else
260239
{
240+
domain = "ai.onnx";
261241
assert(mOpsets.count(domain));
262242
return mOpsets.at(domain);
263243
}
@@ -271,8 +251,22 @@ class ImporterContext final : public IImporterContext
271251
{
272252
return mErrorWrapper ? mErrorWrapper->getErrorRecorder() : nullptr;
273253
}
254+
nvinfer1::IConstantLayer* getConstantLayer(const char* name) const final
255+
{
256+
if (name == nullptr)
257+
{
258+
return nullptr;
259+
}
260+
auto const iter = mConstantLayers.find(name);
261+
if (iter == mConstantLayers.end())
262+
{
263+
return nullptr;
264+
}
265+
return iter->second;
266+
}
267+
274268
private:
275-
std::string generateUniqueName(std::set<std::string>& namesSet, const std::string& basename)
269+
std::string const& generateUniqueName(std::set<std::string>& namesSet, const std::string& basename)
276270
{
277271
std::string candidate = basename;
278272

@@ -283,8 +277,8 @@ class ImporterContext final : public IImporterContext
283277
}
284278

285279
namesSet.insert(candidate);
286-
287-
return candidate;
280+
// Return reference to newly inserted string to avoid any c_str()'s going out of scope
281+
return *namesSet.find(candidate);
288282
}
289283
};
290284

0 commit comments

Comments
 (0)