NVIDIA NvNeural SDK  2022.2
GPU inference framework for NVIDIA Nsight Deep Learning Designer
ModelPreprocessor.h
Go to the documentation of this file.
1 /*
2 * SPDX-FileCopyrightText: Copyright (c) 2020-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: MIT
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 
25 
26 #ifndef NVNEURAL_MODELPREPROCESSOR_H
27 #define NVNEURAL_MODELPREPROCESSOR_H
28 
29 #include <nvneural/CoreTypes.h>
30 #include <Pugixml/pugixml.hpp>
31 #include <memory>
32 #include <unordered_map>
33 #include <unordered_set>
34 #include <vector>
35 
36 namespace nvneural { namespace detail {
37 
44 class XmlModelPreprocessor
45 {
46 public:
47  explicit XmlModelPreprocessor(XmlModelPreprocessor* pParent = nullptr, bool inlineModels = false);
48  ~XmlModelPreprocessor();
49  void clear();
50 
51  void addCustomLayer(const std::string& layer);
52 
53  enum class FusingRuleResult : std::uint16_t
54  {
55  Success = 0,
56  OutOfScope = 1,
57  Failure = 2
58  };
59  FusingRuleResult addFusingScript(const std::string& script);
60 
62  FusingRuleResult addScopedFusingScript(const TensorFormat& currentScope, const std::string& script);
63  void setScriptDebug(bool enable);
64 
65  void addCutLayer(const std::string name);
66 
67  bool loadModelText(const std::string& text, bool autoUpdateModelVersion = true);
68  bool loadModelFile(const std::string& fileName, bool autoUpdateModelVersion = true);
69  bool generateLinked(pugi::xml_document& doc);
70  std::string serializeCurrent() const;
71 
72  bool supportedByEditor() const;
73 
74  static void pushIncludeDirectory(const std::string& path);
75 
76  // "for inference"
77  struct ioDesc
78  {
79  std::string name;
80  std::string source;
81  std::string type;
82  };
83  const std::vector<ioDesc>& getOutputs() const;
84  const std::vector<ioDesc>& getInputs() const;
85 
86  int searchOutputDescIndex(const std::string& layerName) const;
87 
88  // static helpers for working with the XML model
89  static void cloneXmlNode(pugi::xml_node& dest, const pugi::xml_node& src);
90  static bool isCustomScripted(const pugi::xml_node& layer);
91  static bool isInputTypeLayer(const std::string& type);
92 
93  const static std::vector<std::string> m_prototypeCode;
94 
95  int currentModelVersion() const; // see header
96  static int actualModelVersion(); // see header
97  void updateModelVersion();
98 
99  std::string getLastError() const; // see header
100 
101  std::unordered_map<std::string, std::vector<std::string>> getInnerInlinedTemplates() const;
102  std::unordered_map<std::string, std::string> getSynonyms() const { return m_synonyms; }
103 
104  std::unordered_map<std::string, std::shared_ptr<XmlModelPreprocessor>> getInnerTemplates() const;
105 
106 private:
107  int m_modelVersion;
108 
109  struct rulex // rule lexeme
110  {
111  enum TypeCode : uint8_t
112  {
113  ID,
114  INTEGER,
115  FLOAT,
116  DIMENSION,
117  STRING,
118  OPERATOR,
119  COMMENT,
120  FATAL_ERROR,
121  };
122  TypeCode type = FATAL_ERROR;
123  std::string value;
124  };
125  std::vector<rulex> lexParser(const std::string& text);
126 
127  struct ruleSyntaxTreeNode
128  {
129  enum class TypeCode
130  {
131  RULE,
132  LAYER,
133  INPUTS,
134  SELECTION,
135  RANGE,
136  ANY,
137  CONSTANT,
138  PARAMETER,
139  OR,
140  AND,
141  COMP,
142  FATAL_ERROR,
143  };
144  TypeCode type = TypeCode::FATAL_ERROR;
145  rulex literal;
146  rulex flag;
147  std::vector<ruleSyntaxTreeNode> params;
148  };
149  ruleSyntaxTreeNode syntaxParser(std::vector<rulex>& lexemes);
150  ruleSyntaxTreeNode syntaxParseLayer(std::vector<rulex>& lexemes, size_t& offset);
151  ruleSyntaxTreeNode syntaxParseConditionOr(std::vector<rulex>& lexemes, size_t& offset);
152  ruleSyntaxTreeNode syntaxParseInputs(std::vector<rulex>& lexemes, size_t& offset);
153  ruleSyntaxTreeNode syntaxParseSelection(std::vector<rulex>& lexemes, size_t& offset);
154  ruleSyntaxTreeNode syntaxParseConditionAnd(std::vector<rulex>& lexemes, size_t& offset);
155  ruleSyntaxTreeNode syntaxParseComparison(std::vector<rulex>& lexemes, size_t& offset);
156  ruleSyntaxTreeNode syntaxParseOperand(std::vector<rulex>& lexemes, size_t& offset);
157  ruleSyntaxTreeNode syntaxParseRange(std::vector<rulex>& lexemes, size_t& offset);
158  void syntaxError(const ruleSyntaxTreeNode& errorResult, size_t offset) const;
159 
160  bool m_debugFusingScript = false;
161  void printSyntaxTree(const ruleSyntaxTreeNode& node, int indent) const;
162 
163  std::vector<ruleSyntaxTreeNode> m_fusingScripts;
164 
165  static std::vector<std::string> s_includeDirs;
166  static std::string findFile(const std::string& fileName);
167 
168  XmlModelPreprocessor* m_pParent;
169  bool m_inlineModels;
170  std::string m_fileName;
171  bool checkExternalCollision(const std::string& fileName) const;
172 
173  std::string m_lastError;
174  void setError(const std::string& text); // differs from original
175  void setError(const std::string& text, const pugi::xml_node& node);
176  void addError(const std::string& text);
177 
178  struct fusedTemplateLayerNode
179  {
180  std::string name; // Name of the layer
181  pugi::xml_node templateNode; // This contains the template instantiation node
182  std::string templateInstanceScope; // See associated comment in modelLayerNode
183  // Index associated to this layer during fusing
184  // All parameters in the fused node for that layer will be identifed as "_{fusedIndex}_{parameterName}"
185  std::size_t fuseIndex;
186  };
187 
188  struct modelLayerNode
189  {
190  std::string finalName;
191  std::vector<std::string> inputList;
192  pugi::xml_node xmlNode; // "layer node (can't be from template, only final nodes of model)"
193  pugi::xml_node templateNode; // "template node (for overwrites)"
194  // For any layer contained inside a template we need to keep track of the template instantiation scope.
195  // A layer can be inside multiple depth of nested template. The scope is used to identify parameter Set in template instance.
196  // Example of instance scope: template_test_0_inner_template_0
197  std::string templateInstanceScope;
198  bool isFused = false;
199  // We need to keep track of which template layer were fused to be able to apply template instantiation parameters
200  std::vector<fusedTemplateLayerNode> fusedTemplateLayerNodes;
201  };
202 
203  std::string inputLayerName(std::string input);
204  std::string inputLayerName(modelLayerNode &node, size_t index);
205 
206  std::vector<std::string> m_inputs;
207  std::vector<ioDesc> m_inputDescriptors;
208  std::unordered_map<std::string, modelLayerNode> m_table;
209  std::vector<std::string> m_outputs;
210  std::unordered_map<std::string, std::string> m_outputLink;
211  std::vector<ioDesc> m_outputDescriptors;
212  std::unordered_map<std::string, std::string> m_customLayers;
213  std::unordered_set<std::string> m_cutLayers;
214  std::unordered_map<std::string, std::vector<std::string>> m_innerInlinedTemplateLayers;
215  std::unordered_map<std::string, std::string> m_synonyms;
216 
217  std::vector<pugi::xml_node> m_extraNodes;
218 
219  bool tryFusingLayer(modelLayerNode& layer, ruleSyntaxTreeNode& rule);
220  std::string collectFusingInputs(modelLayerNode& layer, std::vector<std::string>& fusingInputs);
221  bool interpretLayer(modelLayerNode& layer, ruleSyntaxTreeNode& rule, std::vector<std::string>& fused);
222  bool interpretCondition(modelLayerNode& layer, ruleSyntaxTreeNode& rule);
223  bool interpretInputs(modelLayerNode& layer, ruleSyntaxTreeNode& rule, std::vector<std::string>& fused, size_t& in_index);
224  bool interpretSelection(modelLayerNode& layer, ruleSyntaxTreeNode& rule, std::vector<std::string>& fused, size_t& in_index);
225  bool interpretParameter(modelLayerNode& layer, ruleSyntaxTreeNode& rule, rulex& op);
226  bool interpretCheckBreak(ruleSyntaxTreeNode& rule, int count);
227 
228  XmlModelPreprocessor* getSubgraphAsModel(
229  const std::vector<std::string>& inputs,
230  const std::vector<std::string>& outputs);
231 
232  bool inlineTemplate(
233  pugi::xml_node& network,
234  const XmlModelPreprocessor* pTempModel,
235  std::unordered_map<std::string, std::string> &synonym,
236  const std::string& name,
237  pugi::xml_node& layer,
238  const std::string& input,
239  bool isInnerTemplate);
240 
241  pugi::xml_document m_model;
242 
243  bool parseModel(pugi::xml_node networkModel, int version);
244  bool backWayCollector(
245  const std::string& node,
246  std::unordered_set<std::string>& collection,
247  std::vector<std::string>& controlStack,
248  const std::vector<std::string>* pStopList);
249 
250  std::unordered_map<std::string, std::shared_ptr<XmlModelPreprocessor>> m_innerTemplates;
251  std::unordered_map<std::string, std::unique_ptr<XmlModelPreprocessor>> m_externTemplates;
252  std::unordered_map<std::string, std::unique_ptr<XmlModelPreprocessor>> m_patternTemplates;
253 
254  enum class FusingRuleLayoutScope
255  {
256  Nchw = 0,
257  Nhwc = 1,
258  Any = 2,
259  };
260 
261  enum class FusingRuleDataTypeScope
262  {
263  Float = 0,
264  Half = 1,
265  Any = 2,
266  };
267 
268  bool preprocessFusingScriptScope(std::vector<rulex>& lexemes, FusingRuleLayoutScope& layoutScope, FusingRuleDataTypeScope& dataTypeScope) const;
269  bool checkAndAddFusingScript(const std::vector<rulex> lexemes);
270  bool checkFusingScript(const std::vector<rulex>& lexemes); // equivalent to checkAndAdd without the add
271 };
272 
273 } } // namespace nvneural::detail
274 #endif // NVNEURAL_MODELPREPROCESSOR_H
Fundamental NvNeural data types are declared here.
@ Float
32-bit floating point elements (float)
@ Half
16-bit floating point elements (__half)
@ Success
Operation succeeded. Generic result.
@ Failure
Operation failed. Generic result.