1010namespace onnx2trt
1111{
1212
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.
2714SubgraphPortsMap::const_iterator findLayer (const SubgraphPortsMap& inputs, const std::string layerName)
2815{
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 (); });
3318}
3419
3520// Add an ConditionalInputLayer between `layer` and its inputs.
3621// I.e. input[inIdx] -> layer ==> input[inIdx] -> ConditionalInputLayer -> layer.
3722void 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 )
3924{
4025 auto input = layer.getInput (inIdx);
4126 if (input == nullptr )
@@ -57,7 +42,7 @@ void addConditionalInputLayer(ImporterContext* ctx, nvinfer1::IIfConditional* co
5742 inputLayer = N_CHECK (conditional->addInput (*input));
5843 inputsMap[name] = inputLayer;
5944 const std::string inputLayerName (name);
60- ctx->registerLayer (inputLayer, inputLayerName + " _InputLayer" , nullptr );
45+ ctx->registerLayer (inputLayer, inputLayerName + " _InputLayer" , node );
6146 // Note: Since multiple conditionals may use the same external tensor, check unique names for output tensors of
6247 // IfConditionalInputLayers to avoid tensor name duplication.
6348 ctx->registerTensor (
@@ -100,7 +85,7 @@ void importSubgraph(ImporterContext* ctx, ::ONNX_NAMESPACE::GraphProto const& su
10085
10186// Add an IConditionalInputLayer to `layer`'s inputs, if they don't already exist.
10287void 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 )
10489{
10590 // Return all of the layer's inputs that are external to the subgraph that
10691 // that the layer belongs to.
@@ -120,36 +105,29 @@ void addConditionalInputIfNeeded(ImporterContext* ctx, nvinfer1::IIfConditional*
120105 for (auto inIdx : inIndices)
121106 {
122107 LOG_VERBOSE (" Adding Input layer for " << layer.getName ());
123- addConditionalInputLayer (ctx, conditional, inputsMap, layer, inIdx);
108+ addConditionalInputLayer (ctx, conditional, inputsMap, layer, inIdx, node );
124109 }
125110}
126111
127112// Add IConditionalInputLayers to `layer`'s inputs.
128113void 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 )
130115{
131116 // 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);
136119
137120 // Add a ConditionalInputLayer in front of each input that is external to the subgraph.
138121 for (const auto & layer : newLayers)
139122 {
140- addConditionalInputIfNeeded (ctx, conditional, inputsMap, *layer, subgraphInputsMap );
123+ addConditionalInputIfNeeded (ctx, conditional, inputsMap, *layer, externalInputs, node );
141124 }
142125}
143126
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)
148129{
149- using NodeName = std::string;
150- using TensorName = std::string;
151130 using PortIndex = int32_t ;
152- using Port = std::pair<NodeName, PortIndex>;
153131 using TensorsSet = std::unordered_set<nvinfer1::ITensor*>;
154132 TensorsSet outputTensors;
155133 TensorsSet inputTensors;
@@ -176,20 +154,14 @@ void getSubgraphTensors(const std::vector<nvinfer1::ILayer*>& newLayers,
176154 }
177155
178156 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-
183157 auto getInputs = [&](nvinfer1::ILayer const * l, TensorsVec& res) {
184158 getTensors (l, true , [&](nvinfer1::ITensor* t) { res.emplace_back (t); });
185159 };
186160
187161 // Retrieve the list of tensors either exiting or entering the subgraph.
188- std::unordered_map<nvinfer1::ITensor*, std::vector<Port>> externalPortsMap;
189162 auto filterTensors = [&](TensorsSet const & tensors, auto getNodeAccessor) {
190163 for (nvinfer1::ILayer const * l : newLayers)
191164 {
192- const auto & nodeName = l->getName ();
193165 PortIndex i = 0 ;
194166
195167 TensorsVec nodeAccessor;
@@ -202,66 +174,14 @@ void getSubgraphTensors(const std::vector<nvinfer1::ILayer*>& newLayers,
202174 }
203175 if (tensors.count (tensor) == 0 )
204176 {
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);
226178 }
227179 i++;
228180 }
229181 }
230182 };
231183
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);
265185}
266186
267187} // namespace onnx2trt
0 commit comments