NVIDIA NvNeural SDK  2022.2
GPU inference framework for NVIDIA Nsight Deep Learning Designer
ScriptEngine.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_SCRIPTENGINE_H
27 #define NVNEURAL_SCRIPTENGINE_H
28 
29 #include <nvneural/CoreTypes.h>
30 #include "ScriptEngineAnyOp.h"
31 #include "ScriptEngineLexyn.h"
32 #include "ScriptEngineUtils.h"
33 #include <string>
34 #include <map>
35 
36 namespace nvneural {
37 namespace detail {
38 
39 template <class T>
40 class ScriptInterpretInterface
41 {
42 public:
43 
44  virtual ~ScriptInterpretInterface()
45  {
46  }
47 
48  virtual void setReal(T& v, const std::string& str) = 0;
49  virtual void setInteger(T& v, const std::string& str) = 0;
50  virtual void setBufferPointer(T& v, const std::string& str, int argIndex) = 0;
51 
52  virtual void neg(T& v) = 0;
53  virtual void add(T& v, T& op) = 0;
54  virtual void sub(T& v, T& op) = 0;
55  virtual void mul(T& v, T& op) = 0;
56  virtual void div(T& v, T& op) = 0;
57 
58  virtual void setRealOption(T& v, const std::string& str) = 0;
59  virtual void setIntegerOption(T& v, const std::string& str) = 0;
60 
61  virtual void transform(T& v, const std::string& str) = 0;
62 
63  virtual void setActType(T& v) = 0;
64  virtual void setActAlhpaLeft(T& v) = 0;
65  virtual void setActAlhpaRight(T& v) = 0;
66 
67  virtual void setWeightsPointer(T& v, const std::string& str) = 0;
68 
69  virtual void setInputPointer(T& v, int index) = 0;
70  virtual void setInputDimValue(T& v, int index, const std::string& str) = 0;
71 
72  virtual void setOutputPointer(T& v, const std::string& name) = 0;
73  virtual void setOutputDimValue(T& v, const std::string& name, const std::string& str) = 0;
74 };
75 
76 struct ScriptEngineParameters
77 {
78  std::string name;
79  std::string type;
80  int numberOfInputs;
81  std::map<std::string, std::string> code; //tensor type as a key
82  //dim example: 1,in[0].c+in[1].c,in.h,in.w;... (without index mean in[0].h == in[1].h == in[2].h ...)
83  std::string dimNCHWCalculation;
84  //fwd example: calling_kernel_name(in[0],in[1],out.w,out.h,in[0].c,in[1].c,out,1+5*4,act,act.alpha,@option,parameter)
85  std::map<std::string, std::string> fwdEvalCall;
86  //parameters from XML (and also fused parameters, for example: _0_parameter, where 0 is index of layer in order of fusing)
87  std::map<std::string, std::string> parameters;
88  std::vector<std::string> optionLegends; //for UI
89  std::vector<std::string> outputList; //additional outputs
90  //weights for layer, example: {{"kernel","1,in.c,1,1"},{"kernel.internal","1,((in.c+7)/8)*8,1,1}}
91  //key - weights name, value - expression like in dim, see WDimInfoType for modifiers, default will be applied for not listed
92  std::map<std::string, std::string> weights;
93  std::vector<std::string> orderedWeightsNames;
94 };
95 
96 class ScriptEngine : public ScriptInterpretInterface<std::string>, public ScriptInterpretInterface<AnyOperand>
97 {
98 public:
99  explicit ScriptEngine(const ScriptEngineParameters& engineParameters);
100  virtual ~ScriptEngine() override
101  {
102  }
103 
104  const std::map<std::string, std::string>& code() const;
105  const std::vector<std::string>& outputList() const;
106  const std::map<std::string, std::string>& weights() const;
107  const std::vector<std::string>& orderedWeightsNames() const;
108 
109  const std::map<std::string, std::string>& parameters() const;
110  const std::map<std::string, Lexem>& parametersParsed() const;
111  const std::vector<std::string>& optionLegends() const;
112  std::map<std::string, std::string>& optionValues();
113  const std::string& optionType(const std::string& name) const;
114 
115  const SynParser::Node& fwdSyntree(const std::string& id) const;
116  const std::string& entry(const std::string& id) const;
117  const std::vector<AnyOperand>& ops(const std::string& id) const;
118  const TensorDimension& stepping(const std::string& id) const;
119  const std::string& fwdEvalCall(const std::string& id) const;
120 
121  const std::string& dimNchwCalculation() const;
122  const std::vector<SynParser::Node>& dimSyntree() const;
123 
124  std::map<int, std::vector<uint8_t>>& bufferArgs();
125 
126  bool cudaExists() const;
127  bool cubinExists() const;
128  bool dxmlExists() const;
129  bool csExists() const;
130 
131  bool actInternal() const;
132 
133  template <class T>
134  T interpretParameter(ScriptInterpretInterface<T>* pInterpret, const SynParser::Node& node, bool call, int argIndex = -1)
135  {
136  T rv;
137 
138  switch (node.lex.type)
139  {
140  case Lexem::FLOAT:
141  if (call)
142  {
143  pInterpret->setReal(rv, node.lex.value);
144  }
145  break;
146  case Lexem::INTEGER:
147  pInterpret->setInteger(rv, node.lex.value);
148  break;
149  case Lexem::STRING:
150  if (argIndex >= 0 && call)
151  {
152  pInterpret->setBufferPointer(rv, node.lex.value, argIndex);
153  }
154  break;
155  case Lexem::GRAMMAR:
156  if (node.lex.value == "UNAR")
157  {
158  rv = interpretParameter<T>(pInterpret, node.child[1], call);
159  pInterpret->neg(rv);
160  }
161  else if (node.lex.value == "ADDSUB" || node.lex.value == "MULDIV")
162  {
163  rv = interpretParameter<T>(pInterpret, node.child[0], call);
164  for (size_t i = 1; i < node.child.size(); i += 2)
165  {
166  T op = interpretParameter<T>(pInterpret, node.child[i + 1], call);
167  if (node.child[i].lex.value == "+")
168  pInterpret->add(rv, op);
169  else if (node.child[i].lex.value == "-")
170  pInterpret->sub(rv, op);
171  else if (node.child[i].lex.value == "*")
172  pInterpret->mul(rv, op);
173  else if (node.child[i].lex.value == "/")
174  pInterpret->div(rv, op);
175  }
176  }
177  else if (node.lex.value == "OPTION")
178  {
179  if (call)
180  {
181  if (m_optionType[node.child[0].lex.value] == "float")
182  {
183  pInterpret->setRealOption(rv, node.child[0].lex.value);
184  }
185  else
186  {
187  pInterpret->setIntegerOption(rv, node.child[0].lex.value);
188  }
189  }
190  }
191  else if (node.lex.value == "CALL")
192  {
193  if (node.child.size() == 2 && call)
194  {
195  rv = interpretParameter<T>(pInterpret, node.child[1], call);
196  pInterpret->transform(rv, node.child[0].lex.value);
197  }
198  }
199  else if (node.lex.value == "VAR")
200  {
201  bool dual_id = node.child.size() > 1;
202  std::string id = node.child[0].child[0].lex.value;
203  std::string second_id;
204  if (dual_id)
205  second_id = node.child[1].child[0].lex.value;
206  bool has_index = node.child[0].child.size() > 1;
207  int index = has_index ? std::atoi(node.child[0].child[1].lex.value.c_str()) : 0;
208 
209  if (id == "act")
210  {
211  if (dual_id)
212  {
213  if ((second_id == "alpha" || second_id == "alpha_left") && call)
214  pInterpret->setActAlhpaLeft(rv);
215  else if (second_id == "alpha_right" && call)
216  pInterpret->setActAlhpaRight(rv);
217  }
218  else
219  {
220  pInterpret->setActType(rv);
221  }
222  m_actInternal = true;
223  }
224  else if (id == "weights" && dual_id)
225  {
226  pInterpret->setWeightsPointer(rv, second_id);
227  }
228  else if (id == "in") //input
229  {
230  if (dual_id || has_index)
231  {
232  if (has_index)
233  {
234  if (!dual_id)
235  {
236  if (call)
237  {
238  pInterpret->setInputPointer(rv, index);
239  }
240  }
241  else
242  {
243  pInterpret->setInputDimValue(rv, index, second_id);
244  }
245  }
246  else if (dual_id)
247  {
248  pInterpret->setInputDimValue(rv, -1, second_id);
249  }
250  }
251  else if (call)
252  {
253  pInterpret->setInputPointer(rv, -1);
254  }
255  }
256  else if (indexOf(m_outputList, id) >= 0 && call)
257  {
258  if (!dual_id)
259  {
260  pInterpret->setOutputPointer(rv, id);
261  }
262  else
263  {
264  pInterpret->setOutputDimValue(rv, id, second_id);
265  }
266  }
267  else if (id == "out" && call) //tensor
268  {
269  if (!dual_id)
270  {
271  pInterpret->setOutputPointer(rv, "");
272  }
273  else if (has_index)
274  {
275  if (index < int(m_outputList.size()))
276  {
277  pInterpret->setOutputDimValue(rv, m_outputList[index], second_id);
278  }
279  }
280  else
281  {
282  pInterpret->setOutputDimValue(rv, "", second_id);
283  }
284  }
285  else if (m_parameters.find(id) != m_parameters.end())
286  {
287  if (m_parametersParsed[id].type == Lexem::INTEGER)
288  {
289  pInterpret->setInteger(rv, m_parametersParsed[id].value);
290  }
291  else if (m_parametersParsed[id].type == Lexem::FLOAT && call)
292  {
293  pInterpret->setReal(rv, m_parametersParsed[id].value);
294  }
295  else if (m_parametersParsed[id].type == Lexem::DIMENSION && dual_id)
296  {
297  std::vector<std::string> dim = split(m_parametersParsed[id].value, 'x', false);
298  for (size_t i = dim.size(); i < 3; i++)
299  {
300  dim.push_back("1");
301  }
302  if (second_id == "x")
303  {
304  pInterpret->setInteger(rv, dim[0]);
305  }
306  else if (second_id == "y")
307  {
308  pInterpret->setInteger(rv, dim[1]);
309  }
310  else if (second_id == "z")
311  {
312  pInterpret->setInteger(rv, dim[2]);
313  }
314  }
315  }
316  }
317  break;
318  default:
319  break;
320  };
321 
322  return rv;
323  }
324 
325  void setReal(AnyOperand& v, const std::string& /*str*/) override;
326  void setInteger(AnyOperand& v, const std::string& /*str*/) override;
327  void setBufferPointer(AnyOperand& v, const std::string& str, int argIndex) override;
328  void neg(AnyOperand& v) override;
329  void add(AnyOperand& v, AnyOperand& op) override;
330  void sub(AnyOperand& v, AnyOperand& op) override;
331  void mul(AnyOperand& v, AnyOperand& op) override;
332  void div(AnyOperand& v, AnyOperand& op) override;
333  void setRealOption(AnyOperand& v, const std::string& /*str*/) override;
334  void setIntegerOption(AnyOperand& v, const std::string& /*str*/) override;
335  void transform(AnyOperand& v, const std::string& str) override;
336  void setActType(AnyOperand& v) override;
337  void setActAlhpaLeft(AnyOperand& v) override;
338  void setActAlhpaRight(AnyOperand& v) override;
339  void setWeightsPointer(AnyOperand& v, const std::string& str) override;
340  void setInputPointer(AnyOperand& v, int index) override;
341  void setInputDimValue(AnyOperand& v, int index, const std::string& str) override;
342  void setOutputPointer(AnyOperand& v, const std::string& name) override;
343  void setOutputDimValue(AnyOperand& v, const std::string& name, const std::string& str) override;
344 
345  std::string generateParameter(const SynParser::Node& node, bool call, const std::string& pointerCast, bool inPlugin, int argIndex);
346 
347  void setReal(std::string& v, const std::string& str) override;
348  void setInteger(std::string& v, const std::string& str) override;
349  void setBufferPointer(std::string& v, const std::string& str, int argIndex) override;
350  void neg(std::string& v) override;
351  void add(std::string& v, std::string& op) override;
352  void sub(std::string& v, std::string& op) override;
353  void mul(std::string& v, std::string& op) override;
354  void div(std::string& v, std::string& op) override;
355  void setRealOption(std::string& v, const std::string& str) override;
356  void setIntegerOption(std::string& v, const std::string& str) override;
357  void transform(std::string& v, const std::string& str) override;
358  void setActType(std::string& v) override;
359  void setActAlhpaLeft(std::string& v) override;
360  void setActAlhpaRight(std::string& v) override;
361  void setWeightsPointer(std::string& v, const std::string& str) override;
362  void setInputPointer(std::string& v, int index) override;
363  void setInputDimValue(std::string& v, int index, const std::string& str) override;
364  void setOutputPointer(std::string& v, const std::string& name) override;
365  void setOutputDimValue(std::string& v, const std::string& name, const std::string& str) override;
366 
367  void setActFused();
368 
369 protected:
370 
371  bool m_inPlugin;
372  std::string m_pointerCast;
373 
374  std::string m_name;
375  std::string m_type;
376 
377  bool m_actInternal = false;
378 
379  bool m_cudaCodeExists = false;
380  bool m_cubinCodeExists = false;
381  bool m_dxmlCodeExists = false;
382  bool m_csCodeExists = false;
383 
384  int m_numberOfInputs;
385 
386  std::map<std::string, std::string> m_code;
387 
388  std::string m_dimNCHWCalculation;
389  std::map<std::string, std::string> m_fwdEvalCall;
390 
391  std::map<std::string, std::string> m_parameters;
392  std::vector<std::string> m_optionLegends;
393  std::map<std::string, std::string> m_optionType;
394  std::map<std::string, std::string> m_optionValues;
395 
396  std::map<std::string, Lexem> m_parametersParsed;
397 
398  std::map<std::string, SynParser::Node> m_fwdSyntreeAll;
399  std::vector<SynParser::Node> m_dimSyntree;
400  SynParser m_parser;
401 
402  bool m_genCheckN = false;
403  bool m_genCheckC = false;
404  bool m_genCheckH = false;
405  bool m_genCheckW = false;
406 
407  std::vector<std::string> m_outputList;
408 
409  std::map<std::string, std::vector<AnyOperand> > m_opsAll;
410  std::map<std::string, std::string> m_entryAll;
411  std::map<int, std::vector<uint8_t>> m_bufferArgs;
412 
413  std::map<std::string, std::string> m_weights;
414  std::map<std::string, SynParser::Node> m_weightsSyntree;
415  std::vector<std::string> m_orderedWeightsNames;
416 
417  std::map<std::string, TensorDimension> m_steppingValueAll;
418 };
419 
420 } // namespace detail
421 } // namespace nvneural
422 
423 #endif // !NVNEURAL_SCRIPTENGINE_H
std::vector< std::string > split(std::string strToSplit, char delimiter, bool skip_empty=false)
Splits a string by a delimiter, returns a vector of the split strings.
Definition: CoreHelpers.h:155
Fundamental NvNeural data types are declared here.
Internal helper classes for parsing script declarations.
Internal helper classes for parsing script declarations.
Internal helper classes for parsing script declarations.