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 
71  bool supportedByEditor() const;
72 
73  static void pushIncludeDirectory(const std::string& path);
74 
75  // "for inference"
76  struct ioDesc
77  {
78  std::string name;
79  std::string source;
80  std::string type;
81  };
82  const std::vector<ioDesc>& getOutputs() const;
83  const std::vector<ioDesc>& getInputs() const;
84 
85  int searchOutputDescIndex(const std::string& layerName) const;
86 
87  // static helpers for working with the XML model
88  static void cloneXmlNode(pugi::xml_node& dest, const pugi::xml_node& src);
89  static bool isCustomScripted(const pugi::xml_node& layer);
90  static bool isInputTypeLayer(const std::string& type);
91 
92  const static std::vector<std::string> m_prototypeCode;
93 
94  int currentModelVersion() const; // see header
95  static int actualModelVersion(); // see header
96  void updateModelVersion();
97 
98  std::string getLastError() const; // see header
99 
100  std::unordered_map<std::string, std::vector<std::string>> getInnerInlinedTemplates() const;
101  std::unordered_map<std::string, std::string> getSynonyms() const { return m_synonyms; }
102 
103  std::unordered_map<std::string, std::shared_ptr<XmlModelPreprocessor>> getInnerTemplates() const;
104 
105 private:
106  int m_modelVersion;
107 
108  struct rulex // rule lexeme
109  {
110  enum TypeCode : uint8_t
111  {
112  ID,
113  INTEGER,
114  FLOAT,
115  DIMENSION,
116  STRING,
117  OPERATOR,
118  COMMENT,
119  FATAL_ERROR,
120  };
121  TypeCode type = FATAL_ERROR;
122  std::string value;
123  };
124  std::vector<rulex> lexParser(const std::string& text);
125 
126  struct ruleSyntaxTreeNode
127  {
128  enum class TypeCode
129  {
130  RULE,
131  LAYER,
132  INPUTS,
133  SELECTION,
134  RANGE,
135  ANY,
136  CONSTANT,
137  PARAMETER,
138  OR,
139  AND,
140  COMP,
141  FATAL_ERROR,
142  };
143  TypeCode type = TypeCode::FATAL_ERROR;
144  rulex literal;
145  rulex flag;
146  std::vector<ruleSyntaxTreeNode> params;
147  };
148  ruleSyntaxTreeNode syntaxParser(std::vector<rulex>& lexemes);
149  ruleSyntaxTreeNode syntaxParseLayer(std::vector<rulex>& lexemes, size_t& offset);
150  ruleSyntaxTreeNode syntaxParseConditionOr(std::vector<rulex>& lexemes, size_t& offset);
151  ruleSyntaxTreeNode syntaxParseInputs(std::vector<rulex>& lexemes, size_t& offset);
152  ruleSyntaxTreeNode syntaxParseSelection(std::vector<rulex>& lexemes, size_t& offset);
153  ruleSyntaxTreeNode syntaxParseConditionAnd(std::vector<rulex>& lexemes, size_t& offset);
154  ruleSyntaxTreeNode syntaxParseComparison(std::vector<rulex>& lexemes, size_t& offset);
155  ruleSyntaxTreeNode syntaxParseOperand(std::vector<rulex>& lexemes, size_t& offset);
156  ruleSyntaxTreeNode syntaxParseRange(std::vector<rulex>& lexemes, size_t& offset);
157  void syntaxError(const ruleSyntaxTreeNode& errorResult, size_t offset) const;
158 
159  bool m_debugFusingScript = false;
160  void printSyntaxTree(const ruleSyntaxTreeNode& node, int indent) const;
161 
162  std::vector<ruleSyntaxTreeNode> m_fusingScripts;
163 
164  static std::vector<std::string> s_includeDirs;
165  static std::string findFile(const std::string& fileName);
166 
167  XmlModelPreprocessor* m_pParent;
168  bool m_inlineModels;
169  std::string m_fileName;
170  bool checkExternalCollision(const std::string& fileName) const;
171 
172  std::string m_lastError;
173  void setError(const std::string& text); // differs from original
174  void setError(const std::string& text, const pugi::xml_node& node);
175  void addError(const std::string& text);
176 
177  struct fusedTemplateLayerNode
178  {
179  std::string name; // Name of the layer
180  pugi::xml_node templateNode; // This contains the template instantiation node
181  std::string templateInstanceScope; // See associated comment in modelLayerNode
182  // Index associated to this layer during fusing
183  // All parameters in the fused node for that layer will be identifed as "_{fusedIndex}_{parameterName}"
184  std::size_t fuseIndex;
185  };
186 
187  struct modelLayerNode
188  {
189  std::string finalName;
190  std::vector<std::string> inputList;
191  pugi::xml_node xmlNode; // "layer node (can't be from template, only final nodes of model)"
192  pugi::xml_node templateNode; // "template node (for overwrites)"
193  // For any layer contained inside a template we need to keep track of the template instantiation scope.
194  // A layer can be inside multiple depth of nested template. The scope is used to identify parameter Set in template instance.
195  // Example of instance scope: template_test_0_inner_template_0
196  std::string templateInstanceScope;
197  bool isFused = false;
198  // We need to keep track of which template layer were fused to be able to apply template instantiation parameters
199  std::vector<fusedTemplateLayerNode> fusedTemplateLayerNodes;
200  };
201 
202  std::string inputLayerName(std::string input);
203  std::string inputLayerName(modelLayerNode &node, size_t index);
204 
205  std::vector<std::string> m_inputs;
206  std::vector<ioDesc> m_inputDescriptors;
207  std::unordered_map<std::string, modelLayerNode> m_table;
208  std::vector<std::string> m_outputs;
209  std::unordered_map<std::string, std::string> m_outputLink;
210  std::vector<ioDesc> m_outputDescriptors;
211  std::unordered_map<std::string, std::string> m_customLayers;
212  std::unordered_set<std::string> m_cutLayers;
213  std::unordered_map<std::string, std::vector<std::string>> m_innerInlinedTemplateLayers;
214  std::unordered_map<std::string, std::string> m_synonyms;
215 
216  std::vector<pugi::xml_node> m_extraNodes;
217 
218  bool tryFusingLayer(modelLayerNode& layer, ruleSyntaxTreeNode& rule);
219  std::string collectFusingInputs(modelLayerNode& layer, std::vector<std::string>& fusingInputs);
220  bool interpretLayer(modelLayerNode& layer, ruleSyntaxTreeNode& rule, std::vector<std::string>& fused);
221  bool interpretCondition(modelLayerNode& layer, ruleSyntaxTreeNode& rule);
222  bool interpretInputs(modelLayerNode& layer, ruleSyntaxTreeNode& rule, std::vector<std::string>& fused, size_t& in_index);
223  bool interpretSelection(modelLayerNode& layer, ruleSyntaxTreeNode& rule, std::vector<std::string>& fused, size_t& in_index);
224  bool interpretParameter(modelLayerNode& layer, ruleSyntaxTreeNode& rule, rulex& op);
225  bool interpretCheckBreak(ruleSyntaxTreeNode& rule, int count);
226 
227  XmlModelPreprocessor* getSubgraphAsModel(
228  const std::vector<std::string>& inputs,
229  const std::vector<std::string>& outputs);
230 
231  bool inlineTemplate(
232  pugi::xml_node& network,
233  const XmlModelPreprocessor* pTempModel,
234  std::unordered_map<std::string, std::string> &synonym,
235  const std::string& name,
236  pugi::xml_node& layer,
237  const std::string& input,
238  bool isInnerTemplate);
239 
240  pugi::xml_document m_model;
241 
242  bool parseModel(pugi::xml_node networkModel, int version);
243  bool backWayCollector(
244  const std::string& node,
245  std::unordered_set<std::string>& collection,
246  std::vector<std::string>& controlStack,
247  const std::vector<std::string>* pStopList);
248 
249  std::unordered_map<std::string, std::shared_ptr<XmlModelPreprocessor>> m_innerTemplates;
250  std::unordered_map<std::string, std::unique_ptr<XmlModelPreprocessor>> m_externTemplates;
251  std::unordered_map<std::string, std::unique_ptr<XmlModelPreprocessor>> m_patternTemplates;
252 
253  enum class FusingRuleLayoutScope
254  {
255  Nchw = 0,
256  Nhwc = 1,
257  Any = 2,
258  };
259 
260  enum class FusingRuleDataTypeScope
261  {
262  Float = 0,
263  Half = 1,
264  Any = 2,
265  };
266 
267  bool preprocessFusingScriptScope(std::vector<rulex>& lexemes, FusingRuleLayoutScope& layoutScope, FusingRuleDataTypeScope& dataTypeScope) const;
268  bool checkAndAddFusingScript(const std::vector<rulex> lexemes);
269  bool checkFusingScript(const std::vector<rulex>& lexemes); // equivalent to checkAndAdd without the add
270 };
271 
272 } } // namespace nvneural::detail
273 #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.