10
10
namespace onnx2trt
11
11
{
12
12
13
- using NodeName = std::string;
14
- using LayerName = std::string;
15
- using InputIndex = int32_t ;
16
-
17
- // A SubgraphPortsMap maps either the inputs or outputs ports of each node in an ONNX graph.
18
- using SubgraphPortsMap = std::unordered_map<nvinfer1::ITensor*, std::set<InputIndex>>;
19
-
20
- // An InputsMap tracks which IIfConditionalInputLayer we've added to a layer's inputs,
21
- // so that we can reuse them if needed.
22
- using InputsMap = std::unordered_map<LayerName, nvinfer1::IIfConditionalInputLayer*>;
23
-
24
- // Search for a network Layer name in a SubgraphPortsMap using partial (prefix) name matching.
25
- // ONNX nodes are matched to network layers using prefix-matching because an ONNX node may have
26
- // several network layers associcated with it.
13
+ // Search for a network Layer name in a SubgraphPortsMap.
27
14
SubgraphPortsMap::const_iterator findLayer (const SubgraphPortsMap& inputs, const std::string layerName)
28
15
{
29
- return std::find_if (inputs.begin (), inputs.end (), [&](const auto & item) {
30
- std::string const key = item.first ->getName ();
31
- return layerName.compare (0 , key.size (), key) == 0 ;
32
- });
16
+ return std::find_if (
17
+ inputs.begin (), inputs.end (), [&](const auto & item) { return layerName == item.first ->getName (); });
33
18
}
34
19
35
20
// Add an ConditionalInputLayer between `layer` and its inputs.
36
21
// I.e. input[inIdx] -> layer ==> input[inIdx] -> ConditionalInputLayer -> layer.
37
22
void addConditionalInputLayer (ImporterContext* ctx, nvinfer1::IIfConditional* conditional, InputsMap& inputsMap,
38
- nvinfer1::ILayer& layer, int32_t inIdx)
23
+ nvinfer1::ILayer& layer, int32_t inIdx, ::ONNX_NAMESPACE::NodeProto const * node )
39
24
{
40
25
auto input = layer.getInput (inIdx);
41
26
if (input == nullptr )
@@ -57,7 +42,7 @@ void addConditionalInputLayer(ImporterContext* ctx, nvinfer1::IIfConditional* co
57
42
inputLayer = N_CHECK (conditional->addInput (*input));
58
43
inputsMap[name] = inputLayer;
59
44
const std::string inputLayerName (name);
60
- ctx->registerLayer (inputLayer, inputLayerName + " _InputLayer" , nullptr );
45
+ ctx->registerLayer (inputLayer, inputLayerName + " _InputLayer" , node );
61
46
// Note: Since multiple conditionals may use the same external tensor, check unique names for output tensors of
62
47
// IfConditionalInputLayers to avoid tensor name duplication.
63
48
ctx->registerTensor (
@@ -100,7 +85,7 @@ void importSubgraph(ImporterContext* ctx, ::ONNX_NAMESPACE::GraphProto const& su
100
85
101
86
// Add an IConditionalInputLayer to `layer`'s inputs, if they don't already exist.
102
87
void addConditionalInputIfNeeded (ImporterContext* ctx, nvinfer1::IIfConditional* conditional, InputsMap& inputsMap,
103
- nvinfer1::ILayer& layer, SubgraphPortsMap subgraphInputsMap)
88
+ nvinfer1::ILayer& layer, SubgraphPortsMap subgraphInputsMap, ::ONNX_NAMESPACE::NodeProto const * node )
104
89
{
105
90
// Return all of the layer's inputs that are external to the subgraph that
106
91
// that the layer belongs to.
@@ -120,36 +105,29 @@ void addConditionalInputIfNeeded(ImporterContext* ctx, nvinfer1::IIfConditional*
120
105
for (auto inIdx : inIndices)
121
106
{
122
107
LOG_VERBOSE (" Adding Input layer for " << layer.getName ());
123
- addConditionalInputLayer (ctx, conditional, inputsMap, layer, inIdx);
108
+ addConditionalInputLayer (ctx, conditional, inputsMap, layer, inIdx, node );
124
109
}
125
110
}
126
111
127
112
// Add IConditionalInputLayers to `layer`'s inputs.
128
113
void addIfInputLayers (ImporterContext* ctx, nvinfer1::IIfConditional* conditional, InputsMap& inputsMap,
129
- const std::vector<nvinfer1::ILayer*>& newLayers)
114
+ const std::vector<nvinfer1::ILayer*>& newLayers, ::ONNX_NAMESPACE::NodeProto const * node )
130
115
{
131
116
// Find all of the tensors entering the subgraph.
132
- // The node-names are from the ONNX context.
133
- using InputIndex = int32_t ;
134
- std::unordered_map<nvinfer1::ITensor*, std::set<InputIndex>> subgraphInputsMap;
135
- getSubgraphInputs (newLayers, subgraphInputsMap);
117
+ SubgraphPortsMap externalInputs;
118
+ getSubgraphInputs (newLayers, externalInputs);
136
119
137
120
// Add a ConditionalInputLayer in front of each input that is external to the subgraph.
138
121
for (const auto & layer : newLayers)
139
122
{
140
- addConditionalInputIfNeeded (ctx, conditional, inputsMap, *layer, subgraphInputsMap );
123
+ addConditionalInputIfNeeded (ctx, conditional, inputsMap, *layer, externalInputs, node );
141
124
}
142
125
}
143
126
144
- // Given a subgraph, find all of its external inputs/outputs (tensors entering/exiting the subgraph).
145
- void getSubgraphTensors (const std::vector<nvinfer1::ILayer*>& newLayers,
146
- std::unordered_map<nvinfer1::ITensor*, std::set<int32_t >>& externalOutputs, bool extractOutputs,
147
- const std::vector<std::string>* reportedOutputs = nullptr )
127
+ // Given a subgraph, find all of its external inputs (tensors entering the subgraph).
128
+ void getSubgraphInputs (const std::vector<nvinfer1::ILayer*>& newLayers, SubgraphPortsMap& externalInputs)
148
129
{
149
- using NodeName = std::string;
150
- using TensorName = std::string;
151
130
using PortIndex = int32_t ;
152
- using Port = std::pair<NodeName, PortIndex>;
153
131
using TensorsSet = std::unordered_set<nvinfer1::ITensor*>;
154
132
TensorsSet outputTensors;
155
133
TensorsSet inputTensors;
@@ -176,20 +154,14 @@ void getSubgraphTensors(const std::vector<nvinfer1::ILayer*>& newLayers,
176
154
}
177
155
178
156
using TensorsVec = std::vector<nvinfer1::ITensor*>;
179
- auto getOutputs = [&](nvinfer1::ILayer const * l, TensorsVec& res) {
180
- getTensors (l, false , [&](nvinfer1::ITensor* t) { res.emplace_back (t); });
181
- };
182
-
183
157
auto getInputs = [&](nvinfer1::ILayer const * l, TensorsVec& res) {
184
158
getTensors (l, true , [&](nvinfer1::ITensor* t) { res.emplace_back (t); });
185
159
};
186
160
187
161
// Retrieve the list of tensors either exiting or entering the subgraph.
188
- std::unordered_map<nvinfer1::ITensor*, std::vector<Port>> externalPortsMap;
189
162
auto filterTensors = [&](TensorsSet const & tensors, auto getNodeAccessor) {
190
163
for (nvinfer1::ILayer const * l : newLayers)
191
164
{
192
- const auto & nodeName = l->getName ();
193
165
PortIndex i = 0 ;
194
166
195
167
TensorsVec nodeAccessor;
@@ -202,66 +174,14 @@ void getSubgraphTensors(const std::vector<nvinfer1::ILayer*>& newLayers,
202
174
}
203
175
if (tensors.count (tensor) == 0 )
204
176
{
205
- TensorName tensorName = tensor->getName ();
206
- auto prefixFound = false ;
207
- if (reportedOutputs)
208
- {
209
- // reportedOutputs are the names of the outputs as reported by the ONNX parser and help
210
- // us further filter the output tensors.
211
- // Exiting tensors := {outputs} - {inputs} - {unreported tensors}
212
- // An example: a Split node is internal to a subgraph and has 4 outputs, but only two are
213
- // connected to the rest of the graph. To prevent mistaking the 2 unused outputs as subgraph
214
- // outputs, we look for them in reportedOutputs which leads us to ignore the 2 tensors.
215
- const auto iter = std::find_if (
216
- reportedOutputs->begin (), reportedOutputs->end (), [&](const auto & outputName) {
217
- // Prefix name matching.
218
- return tensorName.compare (0 , outputName.size (), outputName) == 0 ;
219
- });
220
- prefixFound = iter != reportedOutputs->end ();
221
- }
222
- if (!reportedOutputs || prefixFound)
223
- {
224
- externalPortsMap[tensor].push_back (std::make_pair (nodeName, i));
225
- }
177
+ externalInputs[l].insert (i);
226
178
}
227
179
i++;
228
180
}
229
181
}
230
182
};
231
183
232
- if (extractOutputs)
233
- {
234
- filterTensors (inputTensors, getOutputs);
235
- }
236
- else
237
- {
238
- filterTensors (outputTensors, getInputs);
239
- }
240
-
241
- // Create the user's view of the external inputs, which uses the node-name as the key for
242
- // looking up input/output port index.
243
- for (auto const & input : externalPortsMap)
244
- {
245
- for (const Port& inPort : input.second )
246
- {
247
- auto * tensor = input.first ;
248
- auto const portIndex = inPort.second ;
249
- externalOutputs[tensor].insert (portIndex);
250
- }
251
- }
252
- }
253
-
254
- void getSubgraphOutputs (const std::vector<nvinfer1::ILayer*>& newLayers,
255
- std::unordered_map<nvinfer1::ITensor*, std::set<int32_t >>& externalOutputs,
256
- const std::vector<std::string>& reportedOutputs)
257
- {
258
- getSubgraphTensors (newLayers, externalOutputs, true , &reportedOutputs);
259
- }
260
-
261
- void getSubgraphInputs (const std::vector<nvinfer1::ILayer*>& newLayers,
262
- std::unordered_map<nvinfer1::ITensor*, std::set<int32_t >>& externalInputs)
263
- {
264
- getSubgraphTensors (newLayers, externalInputs, false );
184
+ filterTensors (outputTensors, getInputs);
265
185
}
266
186
267
187
} // namespace onnx2trt
0 commit comments