Skip to content

Commit 7eb49ff

Browse files
kevinch-nvtdp2110
andauthored
Merge master changes -> 7.1 (#547)
* Prefix logging messages with [TRT] (#497) * Add local build instructions (#498) * fix duplicate layer names bug (#446) (#467) Suppose we have a network with (not all distinct) layer names layer layer_1 layer When ImporterContext sees "layer", it sees it's not in mLayerNameCounts, and sets mLayerNameCounts["layer"] = 1 and adds a TRT layer with name "layer". It then sees "layer_1", concludes it's not in mLayerNameCounts, so it sets mLayerNameCounts["layer_1"] = 1 and adds a TRT layer with name "layer_1". NOW when it sees "layer", it sees that mLayerNameCounts["layer"] == 1, so we produce a "uniqueName" of "layer" + "_" + std::to_string(mLayerNameCounts["layer"] ), ie "layer_1", which is a name conflict for the TRT net. This change keeps track of all inserted names in a set and in the case of duplicates, tries suffix-appended modifications of the duplicated name by ever increasing integers until a name appears which has not been used. * Support Dynamic and 3D instanceNormalization (#515) * Add restrictions on multi-input convolutions (#521) * Update resize limitations in TensorRT (#538) Signed-off-by: Kevin Chen <[email protected]> Co-authored-by: Thomas Peters <[email protected]>
1 parent 1cf89dd commit 7eb49ff

File tree

5 files changed

+95
-33
lines changed

5 files changed

+95
-33
lines changed

ImporterContext.hpp

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,12 @@
2626
#include "onnx2trt_utils.hpp"
2727

2828
#include <list>
29+
#include <set>
30+
#include <string>
2931
#include <unordered_map>
3032

3133
namespace onnx2trt
3234
{
33-
3435
class ImporterContext final : public IImporterContext
3536
{
3637
nvinfer1::INetworkDefinition* _network;
@@ -44,13 +45,17 @@ class ImporterContext final : public IImporterContext
4445
StringMap<float> mTensorRangeMins;
4546
StringMap<float> mTensorRangeMaxes;
4647
StringMap<nvinfer1::DataType> mLayerPrecisions;
47-
StringMap<size_t>
48-
mTensorNameCounts; // Keep track of how many times a tensor name shows up, to avoid duplicate naming in TRT.
49-
StringMap<size_t>
50-
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 output tensor names of layers that produce shape tensor outputs but do not natively support them.
52-
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
48+
std::set<std::string> mTensorNames; // keep track of tensor names used so far,
49+
// to avoid duplicate naming in TRT.
50+
std::set<std::string> mLayerNames; // keep track of layer names used so far,
51+
// to avoid duplicate naming in TRT.
52+
int64_t mSuffixCounter = 0; // increasing suffix counter used to uniquify layer names.
53+
std::unordered_set<std::string> mUnsupportedShapeTensors; // Container to hold any shape tensors that are
54+
// the output of layers that do not support
55+
// shape tensors.
56+
StringMap<std::string> mLoopTensors; // Container to map subgraph tensors to
57+
// their original outer graph names.
58+
std::string mOnnxFileLocation; // Keep track of the directory of the parsed ONNX file
5459

5560
public:
5661
ImporterContext(nvinfer1::INetworkDefinition* network, nvinfer1::ILogger* logger)
@@ -98,13 +103,12 @@ class ImporterContext final : public IImporterContext
98103
{
99104
return mOnnxFileLocation;
100105
}
101-
// This actually handles weights as well, but is named this way to be consistent with the tensors()
106+
// This actually handles weights as well, but is named this way to be
107+
// consistent with the tensors()
102108
virtual void registerTensor(TensorOrWeights tensor, const std::string& basename) override
103109
{
104110
// TRT requires unique tensor names.
105-
const std::string uniqueName
106-
= mTensorNameCounts[basename] ? (basename + "_" + std::to_string(mTensorNameCounts[basename])) : basename;
107-
++mTensorNameCounts[basename];
111+
const std::string uniqueName = generateUniqueName(mTensorNames, basename);
108112

109113
if (tensor)
110114
{
@@ -122,8 +126,9 @@ class ImporterContext final : public IImporterContext
122126
convertINT64(reinterpret_cast<int64_t*>(weights.values), weights.shape, ctx), weights.shape};
123127
}
124128
}
125-
// Overwrite previous tensors registered with the same name (this only happens when there are subgraphs,
126-
// and in that case, overwriting is the desired behavior).
129+
// Overwrite previous tensors registered with the same name (this only
130+
// happens when there are subgraphs, and in that case, overwriting is the
131+
// desired behavior).
127132
this->tensors()[basename] = std::move(tensor);
128133
}
129134

@@ -133,9 +138,7 @@ class ImporterContext final : public IImporterContext
133138
if (layer)
134139
{
135140
const std::string name = basename.empty() ? layer->getName() : basename;
136-
const std::string uniqueName
137-
= mLayerNameCounts[name] ? (name + "_" + std::to_string(mLayerNameCounts[name])) : name;
138-
++mLayerNameCounts[name];
141+
const std::string uniqueName = generateUniqueName(mLayerNames, basename);
139142

140143
auto* ctx = this; // To enable logging.
141144
LOG_VERBOSE("Registering layer: " << name << " for ONNX node: " << basename);
@@ -225,6 +228,22 @@ class ImporterContext final : public IImporterContext
225228
return _opsets.at(domain);
226229
}
227230
}
231+
232+
private:
233+
std::string generateUniqueName(std::set<std::string>& namesSet, const std::string& basename)
234+
{
235+
std::string candidate = basename;
236+
237+
while (namesSet.find(candidate) != namesSet.end())
238+
{
239+
candidate = basename + "_" + std::to_string(mSuffixCounter);
240+
++mSuffixCounter;
241+
}
242+
243+
namesSet.insert(candidate);
244+
245+
return candidate;
246+
}
228247
};
229248

230249
} // namespace onnx2trt

ModelImporter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ bool ModelImporter::supportsModel(
374374
std::vector<size_t> topological_order;
375375
if (!toposort(model.graph().node(), &topological_order))
376376
{
377-
cout << "Failed to sort model topologically, exiting ..." << endl;
377+
LOG_ERROR("Failed to sort model topologically, exiting ...");
378378
return false;
379379
}
380380

@@ -408,7 +408,7 @@ bool ModelImporter::supportsModel(
408408
}
409409
else
410410
{
411-
std::cout << "Found unsupported node: " << tensorName << std::endl;
411+
LOG_WARNING("Found unsupported node: " << tensorName);
412412
// This is not a supported node, reset newSubGraph
413413
newSubGraph = true;
414414
allSupported = false;

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,15 @@ Current supported ONNX operators are found in the [operator support matrix](oper
4343

4444
### Building
4545

46-
For building on master, we recommend following the instructions on the [master branch of TensorRT](https://github.com/NVIDIA/TensorRT/) as there are new dependencies that were introduced to support these new features.
46+
For building on master, we recommend following the instructions on the [master branch of TensorRT](https://github.com/NVIDIA/TensorRT/) to take advatange of the latest plugin code required for importing certain operators.
4747

48-
To build on older branches refer to their respective READMEs.
48+
To build only the ONNX-TensorRT parser, follow the following steps:
4949

50+
cd onnx-tensorrt
51+
mkdir build && cd build
52+
cmake .. -DTENSORRT_ROOT=<path_to_trt> && make -j
53+
// Ensure that you update your LD_LIBRARY_PATH to pick up the location of the newly built library:
54+
export LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH
5055

5156
## Executable usage
5257

builtin_op_importers.cpp

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ DEFINE_BUILTIN_OP_IMPORTER(Conv)
430430
ASSERT(inputs.at(0).is_tensor(), ErrorCode::kUNSUPPORTED_NODE);
431431
if (inputs.at(1).is_tensor())
432432
{
433-
ASSERT(inputs.at(1).is_tensor(), ErrorCode::kUNSUPPORTED_NODE);
433+
ASSERT(ctx->network()->hasExplicitPrecision() && "TensorRT only supports multi-input conv for explicit precision QAT networks!", ErrorCode::kUNSUPPORTED_NODE);
434434
if (inputs.size() == 3)
435435
{
436436
ASSERT(inputs.at(2).is_weights(), ErrorCode::kUNSUPPORTED_NODE);
@@ -1613,7 +1613,8 @@ DEFINE_BUILTIN_OP_IMPORTER(InstanceNormalization)
16131613
ASSERT(inputs.at(1).is_weights(), ErrorCode::kUNSUPPORTED_NODE);
16141614
ASSERT(inputs.at(2).is_weights(), ErrorCode::kUNSUPPORTED_NODE);
16151615
nvinfer1::ITensor* tensorPtr = &convertToTensor(inputs.at(0), ctx);
1616-
ASSERT(!isDynamic(tensorPtr->getDimensions()) && "InstanceNormalization does not support dynamic inputs!",
1616+
int nbDims = tensorPtr->getDimensions().nbDims;
1617+
ASSERT(nbDims >= 3 && nbDims <= 4 && "TensorRT only supports InstanceNormalization on 3D or 4D tensors!",
16171618
ErrorCode::kUNSUPPORTED_NODE);
16181619
auto scale_weights = inputs.at(1).weights();
16191620
auto bias_weights = inputs.at(2).weights();
@@ -2535,9 +2536,11 @@ DEFINE_BUILTIN_OP_IMPORTER(Resize)
25352536
{
25362537
nvinfer1::ITensor& input = convertToTensor(inputs.at(0), ctx);
25372538
// TRT does not support INT32 nor BOOL input types for this node
2538-
ASSERT(input.getType() != nvinfer1::DataType::kINT32 && input.getType() != nvinfer1::DataType::kBOOL, ErrorCode::kUNSUPPORTED_NODE);
2539+
ASSERT( (input.getType() != nvinfer1::DataType::kINT32
2540+
&& input.getType() != nvinfer1::DataType::kBOOL)
2541+
&& "This version of TensorRT does not support INT32 or BOOL input for the Resize operator.", ErrorCode::kUNSUPPORTED_NODE);
25392542
int inputRank = input.getDimensions().nbDims;
2540-
ASSERT(inputRank > 0, ErrorCode::kUNSUPPORTED_NODE);
2543+
ASSERT( (inputRank > 0) && "The input tensor cannot be a scalar.", ErrorCode::kUNSUPPORTED_NODE);
25412544
// Add resize layer
25422545
nvinfer1::IResizeLayer* layer = ctx->network()->addResize(input);
25432546
ctx->registerLayer(layer, node.name());
@@ -2562,22 +2565,57 @@ DEFINE_BUILTIN_OP_IMPORTER(Resize)
25622565
&& "This version of TensorRT only supports floor nearest_mode!",
25632566
ErrorCode::kUNSUPPORTED_NODE);
25642567

2565-
// Note both asymmetric and align_corners resize modes go through the same import path in TRT:
2566-
if (transformationMode == "asymmetric" || transformationMode == "align_corners")
2567-
{
2568-
layer->setAlignCorners(true);
2569-
}
2570-
25712568
// The existence of a fourth input means a shape was passed as the resize parameter
2569+
// For ONNX resize with the "sizes", TensorRT's resize maps to ONNX's in the following ways:
2570+
// Nearest:
2571+
// alignCorners = 0: ASYMMETRIC
2572+
// alignCorners = 1: ALIGN_CORNERS
2573+
// Linear:
2574+
// alignCorners = 0: HALF_PIXEL
2575+
// alignCorners = 1: ALIGN_CORNERS
25722576
if (inputs.size() == 4)
25732577
{
2578+
if (transformationMode == "align_corners")
2579+
{
2580+
layer->setAlignCorners(true);
2581+
}
2582+
if (mode == "nearest")
2583+
{
2584+
ASSERT((transformationMode == "asymmetric" || transformationMode == "align_corners") && "TensorRT only supports asymmetric and align_corners transformation modes for nearest neighbor resizes when sizes are provided!", ErrorCode::kUNSUPPORTED_NODE);
2585+
}
2586+
else if (mode == "linear")
2587+
{
2588+
ASSERT((transformationMode == "half_pixel" || transformationMode == "pytorch_half_pixel" || transformationMode == "align_corners") && "TensorRT only supports half_pixel, pytorch_half_pixel, and align_corners transofmration modes for linear resizes when sizes are provided!", ErrorCode::kUNSUPPORTED_NODE);
2589+
}
25742590
auto* resizeShape = &convertToTensor(inputs.at(3), ctx);
25752591
layer->setInput(1, *resizeShape);
25762592
layer->setResizeMode(resizeMode);
25772593
RETURN_FIRST_OUTPUT(layer);
25782594
}
2595+
// For ONNX resize with "scales", TensorRT's resize maps to ONNX's in the following ways:
2596+
// Nearest:
2597+
// alignCorners = 0: ASYMMETRIC
2598+
// alignCorners = 1: ASYMMETRIC
2599+
// Linear:
2600+
// alignCorners = 0: HALF_PIXEL
2601+
// alignCorners = 1: ASYMMETRIC
2602+
else
2603+
{
2604+
if (mode == "nearest")
2605+
{
2606+
ASSERT(transformationMode == "asymmetric" && "TensorRT only supports asymmetric tranformation mode for nearest neighbor resizes when scales are provided!",ErrorCode::kUNSUPPORTED_NODE);
2607+
}
2608+
else if (mode == "linear")
2609+
{
2610+
ASSERT((transformationMode == "asymmetric" || transformationMode == "pytorch_half_pixel" || transformationMode == "half_pixel") && "TensorRT only supports half pixel, pytorch half_pixel, and asymmetric tranformation mode for linear resizes when scales are provided!", ErrorCode::kUNSUPPORTED_NODE);
2611+
if (transformationMode == "asymmetric")
2612+
{
2613+
layer->setAlignCorners(true);
2614+
}
2615+
}
2616+
}
25792617
}
2580-
// For opset 10 resize, the only supported mode is asymmetric resize, which is mapped to TRT's alignCorners.
2618+
// For opset 10 resize, the only supported mode is asymmetric resize with scales.
25812619
else
25822620
{
25832621
transformationMode = "asymmetric";

onnx2trt_utils.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
do \
4040
{ \
4141
std::stringstream ss{}; \
42-
ss << __FILENAME__ << ":" << __LINE__ << ": " << msg; \
42+
ss << "[TRT]" << __FILENAME__ << ":" << __LINE__ << ": " << msg; \
4343
ctx->logger().log(severity, ss.str().c_str()); \
4444
} while (0)
4545

0 commit comments

Comments
 (0)