1 | /** |
2 | * Copyright (c) Glow Contributors. See CONTRIBUTORS file. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | #include "NodeBuilder.h" |
17 | |
18 | #include <fstream> |
19 | #include <iostream> |
20 | |
21 | int main(int argc, char **argv) { |
22 | if (argc != 6) { |
23 | std::cerr << "Usage: " << argv[0] |
24 | << " output.h output.cpp output.def import.h export.h\n" ; |
25 | return -1; |
26 | } |
27 | |
28 | std::cout << "Writing node descriptors to:\n\t" << argv[1] << "\n\t" |
29 | << argv[2] << "\n\t" << argv[3] << "\n\t" << argv[4] << "\n\t" |
30 | << argv[5] << "\n" ; |
31 | |
32 | std::ofstream hFile(argv[1]); |
33 | std::ofstream cFile(argv[2]); |
34 | std::ofstream dFile(argv[3]); |
35 | std::ofstream iFile(argv[4]); |
36 | std::ofstream eFile(argv[5]); |
37 | |
38 | Builder BB(hFile, cFile, dFile, iFile, eFile); |
39 | |
40 | //===--------------------------------------------------------------------===// |
41 | // Input/Output nodes |
42 | //===--------------------------------------------------------------------===// |
43 | |
44 | BB.includeHeader("glow/Graph/Nodes.h" ); |
45 | |
46 | BB.declareNode("Storage" ); |
47 | BB.declareNode("Constant" ); |
48 | BB.declareNode("Placeholder" ); |
49 | |
50 | BB.newNode("Save" ) |
51 | .addInput("Input" ) |
52 | .addInput("Output" ) |
53 | .addExtraMethod("Placeholder *getPlaceholder() const;" , |
54 | "Placeholder *SaveNode::getPlaceholder() const { return " |
55 | "llvm::cast<Placeholder>(Output_.getNode()); };" ) |
56 | .addOverwrittenInput("Output" ) |
57 | .setHasSideEffects(true) |
58 | .dataParallel() |
59 | .skipAutogenSerialization() |
60 | .setDocstring("Specifies a node whose Input will be copied to Output." |
61 | "This node prevents graph optimizations from eliminating " |
62 | "this node and all of its ancestor nodes. Generally " |
63 | "intended to save the final result of a network." ); |
64 | |
65 | //===--------------------------------------------------------------------===// |
66 | // Convolution / Pool / FC |
67 | //===--------------------------------------------------------------------===// |
68 | |
69 | BB.newNode("Pad" ) |
70 | .addInput("Input" ) |
71 | .addMember(MemberType::Enum, "Mode" ) |
72 | .addMember(MemberType::VectorSigned, "Pads" ) |
73 | .addMember(MemberType::Float, "Value" ) |
74 | .addResultFromCtorArg() |
75 | .setDocstring( |
76 | "Performs padding of a given input tensor. The Padding information " |
77 | "must be specified for each dimension of the tensor in Pads (start " |
78 | "and end padding). In case the padding is negative, it means that " |
79 | "the tensor must be cropped. Mode defines how extra padding elements " |
80 | "are created. Supported modes are defined in the PaddingMode enum: " |
81 | "CONSTANT, REFLECT, EDGE. Value is only used with the CONSTANT " |
82 | "mode." ); |
83 | |
84 | BB.newNode("Convolution" ) |
85 | .addInput("Input" ) |
86 | .addInput("Filter" ) |
87 | .addInput("Bias" ) |
88 | .addMember(MemberType::VectorUnsigned, "Kernels" ) |
89 | .addMember(MemberType::VectorUnsigned, "Strides" ) |
90 | .addMember(MemberType::VectorUnsigned, "Pads" , /* addSetter */ true) |
91 | .addMember(MemberType::Unsigned, "Group" , /* addSetter */ true) |
92 | .addMember(MemberType::VectorUnsigned, "Dilation" ) |
93 | .addMember(MEMBER_TYPE_INFO(glow::ConvolutionLayout), "Layout" ) |
94 | .addFusedActivation() |
95 | .addResultFromCtorArg() |
96 | .addGradient() |
97 | .setDocstring( |
98 | "Performs 2D Convolution using a given Input, Filter, and " |
99 | "Bias tensors, as well as provided Kernels, Strides, Pads, " |
100 | "Group and Dilation. Supported Layouts are defined in the " |
101 | "ConvolutionLayout enum: NHWC and NCHW. Supported FusedActivations " |
102 | "are defined in the FusedActivation enum." ); |
103 | |
104 | BB.newNode("ChannelwiseQuantizedConvolution" ) |
105 | .addInput("Input" ) |
106 | .addInput("Filter" ) |
107 | .addInput("Bias" ) |
108 | .addInput("FilterScales" ) |
109 | .addInput("FilterOffsets" ) |
110 | .addInput("BiasScales" ) |
111 | .addInput("BiasOffsets" ) |
112 | .addMember(MemberType::VectorUnsigned, "Kernels" , /* addSetter */ true) |
113 | .addMember(MemberType::VectorUnsigned, "Strides" ) |
114 | .addMember(MemberType::VectorUnsigned, "Pads" , /* addSetter */ true) |
115 | .addMember(MemberType::Unsigned, "Group" , /* addSetter */ true) |
116 | .addMember(MemberType::VectorUnsigned, "Dilation" ) |
117 | .addFusedActivation() |
118 | .addResultFromCtorArg() |
119 | .setDocstring( |
120 | "Performs 2D Convolution using a given Input, Filter, and " |
121 | "Bias tensors, as well as provided Kernels, Strides, Pads, " |
122 | "and Group. The filter channel wise quantization parameters " |
123 | "are provided by FilterScales and FilterOffsets while the " |
124 | "bias channel wise quantization parameters are provided by " |
125 | "BiasScales and BiasOffsets." ); |
126 | |
127 | BB.newNode("ConvTranspose" ) |
128 | .addInput("Input" ) |
129 | .addInput("Filter" ) |
130 | .addInput("Bias" ) |
131 | .addMember(MemberType::VectorUnsigned, "Kernels" ) |
132 | .addMember(MemberType::VectorUnsigned, "Strides" ) |
133 | .addMember(MemberType::VectorUnsigned, "Pads" ) |
134 | .addMember(MemberType::Unsigned, "Group" ) |
135 | .addMember(MemberType::VectorUnsigned, "Dilation" ) |
136 | .addResultFromCtorArg() |
137 | .setDocstring("Performs 2D Transposed Convolution using a given Input," |
138 | "Filter, and Bias tensors, as well as provided Kernels," |
139 | "Strides, Pads, and Group." ); |
140 | |
141 | BB.newNode("Convolution3D" ) |
142 | .addInput("Input" ) |
143 | .addInput("Filter" ) |
144 | .addInput("Bias" ) |
145 | .addMember(MemberType::VectorUnsigned, "Kernels" ) |
146 | .addMember(MemberType::VectorUnsigned, "Strides" ) |
147 | .addMember(MemberType::VectorUnsigned, "Pads" ) |
148 | .addMember(MemberType::Unsigned, "Group" ) |
149 | .addResultFromCtorArg() |
150 | .addGradient() |
151 | .setDocstring("Performs 3D Convolution using a given Input, Filter, and " |
152 | "Bias tensors, as well as provided Kernels, Strides, Pads, " |
153 | "and Group." ); |
154 | |
155 | BB.newNode("MaxPool" ) |
156 | .addInput("Input" ) |
157 | .addMember(MemberType::VectorUnsigned, "Kernels" ) |
158 | .addMember(MemberType::VectorUnsigned, "Strides" ) |
159 | .addMember(MemberType::VectorUnsigned, "Pads" , /* addSetter */ true) |
160 | .addMember(MemberType::Enum, "Layout" ) |
161 | .addResultFromCtorArg("Result" ) |
162 | .addResultFromCtorArg("Argmax" ) |
163 | .addGradient() |
164 | .setDocstring( |
165 | "Performs a Max Pool with Argmax operation on the Input " |
166 | "given provided Kernels, Strides, and Pads. Argmax is a flattened " |
167 | "index corresponding to respective max element. Supported layouts " |
168 | "are defined in the ConvolutionLayout enum: NHWC and NCHW." ); |
169 | |
170 | BB.newNode("ArgMax" ) |
171 | .addInput("Input" ) |
172 | .addMember(MemberType::Unsigned, "Axis" ) |
173 | .addMember(MemberType::Boolean, "KeepDims" ) |
174 | .addResultFromCtorArg() |
175 | .setDocstring("Finds index of a maximum element along Axis. " |
176 | "If KeepDims is not true, the axis is removed from output" ); |
177 | |
178 | BB.newNode("ArgMin" ) |
179 | .addInput("Input" ) |
180 | .addMember(MemberType::Unsigned, "Axis" ) |
181 | .addMember(MemberType::Boolean, "KeepDims" ) |
182 | .addResultFromCtorArg() |
183 | .setDocstring("Finds index of a minimum element along Axis. " |
184 | "If KeepDims is not true, the axis is removed from output" ); |
185 | |
186 | BB.newNode("AvgPool" ) |
187 | .addInput("Input" ) |
188 | .addMember(MemberType::VectorUnsigned, "Kernels" ) |
189 | .addMember(MemberType::VectorUnsigned, "Strides" ) |
190 | .addMember(MemberType::VectorUnsigned, "Pads" , /* addSetter */ true) |
191 | .addMember(MemberType::Enum, "Layout" ) |
192 | .addMember(MemberType::Boolean, "CountIncludePads" ) |
193 | .addResultFromCtorArg() |
194 | .addGradient() |
195 | .setDocstring( |
196 | "Performs an Average Pool operation on the Input given " |
197 | "provided Kernels, Strides, and Pads. Supported layouts are defined " |
198 | "in the ConvolutionLayout enum: NHWC, NCHW, NTHWC and NCTHW." ); |
199 | |
200 | BB.newNode("AdaptiveAvgPool" ) |
201 | .addInput("Input" ) |
202 | .addResultFromCtorArg() |
203 | .addGradient() |
204 | .setDocstring( |
205 | "Performs an Adaptive Average Pool operation on the Input given" ); |
206 | |
207 | BB.newNode("Gemm" ) |
208 | .addInput("A" ) |
209 | .addInput("B" ) |
210 | .addInput("C" ) |
211 | .addMember(MemberType::Float, "Alpha" ) |
212 | .addMember(MemberType::Float, "Beta" ) |
213 | .addMember(MemberType::Boolean, "TransposeA" ) |
214 | .addMember(MemberType::Boolean, "TransposeB" ) |
215 | .addResultFromCtorArg() |
216 | .setDocstring( |
217 | "Computes Y = Alpha * A * B + Beta * C where Alpha, Beta are scalars " |
218 | "and A, B, C are matrices. If TransposeA or TransposeB is used then " |
219 | "A or B is additionally transposed." ); |
220 | |
221 | BB.newNode("FullyConnected" ) |
222 | .addInput("Input" ) |
223 | .addInput("Weights" ) |
224 | .addInput("Bias" ) |
225 | .addResultFromCtorArg() |
226 | .addGradient() |
227 | .setDocstring("Creates a FullyConnected node where the Input tensor and " |
228 | "Weights tensor are multiplied, and then the Bias tensor " |
229 | "is added to it, producing the Output." ); |
230 | |
231 | BB.newNode("RowwiseQuantizedFullyConnected" ) |
232 | .addInput("Input" ) |
233 | .addInput("Weights" ) |
234 | .addInput("Scales" ) |
235 | .addInput("Offsets" ) |
236 | .addInput("Bias" ) |
237 | .addResultFromCtorArg() |
238 | .setDocstring( |
239 | "Creates a RowwiseQuantizedFullyConnected node where the Input " |
240 | "matrix and the transpose of Weights matrix are multiplied, and " |
241 | "then the Bias vector is broadcast-added to the result. Input, " |
242 | "Bias and Result are regularly quantized, while Weights use row-wise" |
243 | "quantization." ); |
244 | |
245 | BB.newNode("DynamicQuantizedFullyConnected" ) |
246 | .addInput("Input" ) |
247 | .addInput("Weights" ) |
248 | .addInput("Bias" ) |
249 | .addMember(MemberType::Boolean, "IsSymmetric" ) |
250 | .addMember(MemberType::Boolean, "IsPerBatchElement" ) |
251 | .addResultFromCtorArg() |
252 | .setDocstring( |
253 | "Creates a DynamicQuantizedFullyConnectedNode which implement the " |
254 | "functionality of dynamic_quantization => quantized_fc => " |
255 | "dequantize, which support symmteric/asymmetric quantization. " |
256 | "Quantize parameters are automatically selected from range of input, " |
257 | "while weights are pre-quantized to int8 and bias are whether float " |
258 | "or int32" ); |
259 | |
260 | BB.newNode("DynamicRowwiseQuantizedFullyConnected" ) |
261 | .addInput("Input" ) |
262 | .addInput("Weights" ) |
263 | .addInput("Bias" ) |
264 | .addInput("Scales" ) |
265 | .addInput("Offsets" ) |
266 | .addMember(MemberType::Boolean, "IsSymmetric" ) |
267 | .addMember(MemberType::Boolean, "IsPerBatchElement" ) |
268 | .addResultFromCtorArg() |
269 | .setDocstring( |
270 | "Creates a DynamicRowwiseQuantizedFullyConnectedNode which implement " |
271 | "the functionality of dynamic_quantization => quantized_fc => " |
272 | "dequantize, which support symmteric/asymmetric quantization. " |
273 | "Quantize parameters are automatically selected from range of input, " |
274 | "while weights are pre-rowwise-quantized to int8, whose rowwise " |
275 | "params stored in Scales and Offsets, and bias are whether float " |
276 | "or int32" ); |
277 | //===--------------------------------------------------------------------===// |
278 | // Normalization |
279 | //===--------------------------------------------------------------------===// |
280 | |
281 | BB.newNode("BatchNormalization" ) |
282 | .addInput("Input" ) |
283 | .addInput("Scale" ) |
284 | .addInput("Bias" ) |
285 | .addInput("Mean" ) |
286 | .addInput("Var" ) |
287 | .addMember(MemberType::Unsigned, "ChannelIdx" ) |
288 | .addMember(MemberType::Float, "Epsilon" ) |
289 | .addMember(MemberType::Float, "Momentum" ) |
290 | .addResultFromCtorArg() |
291 | .addGradient() |
292 | .setDocstring("Performs batch normalization on the Input tensor with the " |
293 | "provided Scale, Bias, Mean, Var, ChannelIdx, Epsilon, and " |
294 | "Momentum. Similar to Caffe2 SpatialBN, and ONNX " |
295 | "BatchNormalization operator." ); |
296 | |
297 | BB.newNode("InstanceNormalization" ) |
298 | .addInput("Input" ) |
299 | .addInput("Scale" ) |
300 | .addInput("Bias" ) |
301 | .addMember(MemberType::Unsigned, "ChannelIdx" ) |
302 | .addMember(MemberType::Float, "Epsilon" ) |
303 | .addResult("Input.getType()" ) |
304 | .setDocstring("Performs instance normalization on the Input tensor with " |
305 | "the provided Scale, Bias, Epsilon. Similar to ONNX " |
306 | "InstanceNormalization operator." ); |
307 | |
308 | BB.newNode("MeanVarNormalization" ) |
309 | .addInput("Input" ) |
310 | .addInput("Mean" ) |
311 | .addInput("Var" ) |
312 | .addMember(MemberType::Unsigned, "ChannelIdx" ) |
313 | .addMember(MemberType::Float, "Momentum" ) |
314 | .addResult("Mean.getType()" , "NewMean" ) |
315 | .addResult("Var.getType()" , "NewVar" ) |
316 | .setDocstring("Calculates new normalized mean and variance based on the " |
317 | "input mean, variance, and input." ); |
318 | |
319 | BB.newNode("LocalResponseNormalization" ) |
320 | .addInput("Input" ) |
321 | .addMember(MemberType::Unsigned, "HalfWindowSize" ) |
322 | .addMember(MemberType::Float, "Alpha" ) |
323 | .addMember(MemberType::Float, "Beta" ) |
324 | .addMember(MemberType::Float, "K" ) |
325 | .addResult("Input.getType()" ) |
326 | .addGradient() |
327 | .setDocstring("Performs local response normalization on the Input tensor " |
328 | "with the provided Scale, Bias, Mean, Var, ChannelIdx, " |
329 | "Epsilon, and Momentum. Similar to Caffe2 and ONNX LRN." ); |
330 | |
331 | BB.newNode("LayerNormalization" ) |
332 | .addInput("Input" ) |
333 | .addInput("Scale" ) |
334 | .addInput("Bias" ) |
335 | .addMember(MemberType::Float, "Epsilon" ) |
336 | .addResultFromCtorArg() |
337 | .setDocstring("Performs layer normalization on the Input tensor with the " |
338 | "provided Scale, Bias, and Epsilon. Layer sizes are " |
339 | "determined by the dimensions of Scale and Bias. Similar " |
340 | "to PyTorch layer_norm." ); |
341 | |
342 | BB.newNode("BatchBoxCox" ) |
343 | .addInput("Input" ) |
344 | .addInput("Lambda1" ) |
345 | .addInput("Lambda2" ) |
346 | .addMember(MemberType::Float, "Epsilon" ) |
347 | .addResult("Input.getType()" ) |
348 | .setDocstring("Apply box-cox transform for each column for each column " |
349 | "in NxD input tensor" ); |
350 | |
351 | BB.newNode("VectorNorm" ) |
352 | .addInput("Input" ) |
353 | .addMember(MemberType::Unsigned, "Axis" ) |
354 | .addMember(MemberType::Unsigned, "P" ) |
355 | .addResultFromCtorArg() |
356 | .setDocstring("Performs L2 norm of the Input operand based on Axis." ); |
357 | |
358 | //===--------------------------------------------------------------------===// |
359 | // Bucketing |
360 | //===--------------------------------------------------------------------===// |
361 | |
362 | BB.newNode("Bucketize" ) |
363 | .addInput("Input" ) |
364 | .addMember(MemberType::VectorFloat, "Boundaries" ) |
365 | .addResultFromCtorArg() |
366 | .setDocstring("Performs bucketization on the input given Boundaries" ); |
367 | |
368 | //===--------------------------------------------------------------------===// |
369 | // Loss operations |
370 | //===--------------------------------------------------------------------===// |
371 | |
372 | BB.newNode("SoftMax" ) |
373 | .addInput("Input" ) |
374 | .addInput("Selected" ) |
375 | .addResultFromCtorArg() |
376 | .addGradient() |
377 | .setDocstring("Performs SoftMax normalization on the Input tensor." ); |
378 | |
379 | BB.newNode("LogSoftMax" ) |
380 | .addInput("Input" ) |
381 | .addInput("Selected" ) |
382 | .addResultFromCtorArg() |
383 | .addGradient() |
384 | .setDocstring("Performs LogSoftMax normalization on the Input tensor." ); |
385 | |
386 | BB.newNode("CrossEntropyLoss" ) |
387 | .addInput("P" ) |
388 | .addInput("Labels" ) |
389 | .addResultFromCtorArg("CE" ) |
390 | .addGradient() |
391 | .setDocstring("Computes the average cross entropy loss of the input." ); |
392 | |
393 | BB.newNode("Regression" ) |
394 | .addInput("Input" ) |
395 | .addInput("Expected" ) |
396 | .addResult("Input.getType()" ) |
397 | .addGradient() |
398 | .setDocstring( |
399 | "Takes an Input tensor and creates a regression output layer." ); |
400 | |
401 | BB.newNode("SigmoidCrossEntropyWithLogits" ) |
402 | .addInput("Logits" ) |
403 | .addInput("Targets" ) |
404 | .addResultFromCtorArg() |
405 | .setDocstring("Computes the sigmoid cross entropy between two inputs." ); |
406 | |
407 | //===--------------------------------------------------------------------===// |
408 | // Arithmetic |
409 | //===--------------------------------------------------------------------===// |
410 | |
411 | BB.newNode("Add" ) |
412 | .addInput("LHS" ) |
413 | .addInput("RHS" ) |
414 | .addResultFromCtorArg() |
415 | .dataParallel() |
416 | .addGradient() |
417 | .setDocstring("Performs Add on the LHS and RHS operands." ); |
418 | |
419 | BB.newNode("Mul" ) |
420 | .addInput("LHS" ) |
421 | .addInput("RHS" ) |
422 | .addResultFromCtorArg() |
423 | .dataParallel() |
424 | .addGradient() |
425 | .setDocstring("Performs Mul on the LHS and RHS operands." ); |
426 | |
427 | BB.newNode("Sub" ) |
428 | .addInput("LHS" ) |
429 | .addInput("RHS" ) |
430 | .addResultFromCtorArg() |
431 | .dataParallel() |
432 | .addGradient() |
433 | .setDocstring("Performs Sub on the LHS and RHS operands." ); |
434 | |
435 | BB.newNode("Div" ) |
436 | .addInput("LHS" ) |
437 | .addInput("RHS" ) |
438 | .addResultFromCtorArg() |
439 | .dataParallel() |
440 | .addGradient() |
441 | .setDocstring("Performs Div on the LHS and RHS operands." ); |
442 | |
443 | BB.newNode("FloorDiv" ) |
444 | .addInput("LHS" ) |
445 | .addInput("RHS" ) |
446 | .addMember(MemberType::Boolean, "Truncate" ) |
447 | .addResultFromCtorArg() |
448 | .dataParallel() |
449 | .setDocstring( |
450 | "Performs Div on the LHS and RHS operands, then Floor. If Truncate " |
451 | "is set to true then truncate the quotient to zero instead." ); |
452 | |
453 | BB.newNode("Fmod" ) |
454 | .addInput("LHS" ) |
455 | .addInput("RHS" ) |
456 | .addResultFromCtorArg() |
457 | .dataParallel() |
458 | .setDocstring("Computes the element-wise remainder of division." ); |
459 | |
460 | BB.newNode("Max" ) |
461 | .addInput("LHS" ) |
462 | .addInput("RHS" ) |
463 | .addResultFromCtorArg() |
464 | .dataParallel() |
465 | .setDocstring("Performs Max on the LHS and RHS operands." ); |
466 | |
467 | BB.newNode("Min" ) |
468 | .addInput("LHS" ) |
469 | .addInput("RHS" ) |
470 | .addResultFromCtorArg() |
471 | .dataParallel() |
472 | .setDocstring("Performs Min on the LHS and RHS operands." ); |
473 | |
474 | BB.newNode("CmpEQ" ) |
475 | .addInput("LHS" ) |
476 | .addInput("RHS" ) |
477 | .addResultFromCtorArg() |
478 | .dataParallel() |
479 | .setDocstring("Performs an element-wise EQUAL comparison between the " |
480 | "LHS and RHS operands." ); |
481 | |
482 | BB.newNode("CmpNEQ" ) |
483 | .addInput("LHS" ) |
484 | .addInput("RHS" ) |
485 | .addResultFromCtorArg() |
486 | .dataParallel() |
487 | .setDocstring("Performs an element-wise NOT EQUAL comparison between " |
488 | "the LHS and RHS operands." ); |
489 | |
490 | BB.newNode("CmpLT" ) |
491 | .addInput("LHS" ) |
492 | .addInput("RHS" ) |
493 | .addResultFromCtorArg() |
494 | .dataParallel() |
495 | .setDocstring("Performs an element-wise LESS THAN comparison between " |
496 | "the LHS and RHS operands." ); |
497 | |
498 | BB.newNode("CmpLTE" ) |
499 | .addInput("LHS" ) |
500 | .addInput("RHS" ) |
501 | .addResultFromCtorArg() |
502 | .dataParallel() |
503 | .setDocstring("Performs an element-wise LESS THAN OR EQUAL comparison " |
504 | "between the LHS and RHS operands." ); |
505 | |
506 | BB.newNode("Pow" ) |
507 | .addInput("LHS" ) |
508 | .addInput("RHS" ) |
509 | .addResultFromCtorArg() |
510 | .dataParallel() |
511 | .setDocstring("Performs elementwise pow(LHS, RHS)." ); |
512 | |
513 | BB.newNode("And" ) |
514 | .addInput("LHS" ) |
515 | .addInput("RHS" ) |
516 | .addResultFromCtorArg() |
517 | .dataParallel() |
518 | .setDocstring("Performs an element-wise logical AND between the LHS and " |
519 | "RHS operands." ); |
520 | |
521 | BB.newNode("BitwiseAnd" ) |
522 | .addInput("LHS" ) |
523 | .addInput("RHS" ) |
524 | .addResultFromCtorArg() |
525 | .dataParallel() |
526 | .setDocstring("Performs an element-wise bitwise AND between the LHS and " |
527 | "RHS operands." ); |
528 | |
529 | BB.newNode("Or" ) |
530 | .addInput("LHS" ) |
531 | .addInput("RHS" ) |
532 | .addResultFromCtorArg() |
533 | .dataParallel() |
534 | .setDocstring("Performs an element-wise logical OR between the LHS and " |
535 | "RHS operands." ); |
536 | |
537 | BB.newNode("BitwiseOr" ) |
538 | .addInput("LHS" ) |
539 | .addInput("RHS" ) |
540 | .addResultFromCtorArg() |
541 | .dataParallel() |
542 | .setDocstring("Performs an element-wise bitwise OR between the LHS and " |
543 | "RHS operands." ); |
544 | |
545 | BB.newNode("Xor" ) |
546 | .addInput("LHS" ) |
547 | .addInput("RHS" ) |
548 | .addResultFromCtorArg() |
549 | .dataParallel() |
550 | .setDocstring("Performs an element-wise logical XOR between the LHS and " |
551 | "RHS operands." ); |
552 | |
553 | BB.newNode("BitwiseXor" ) |
554 | .addInput("LHS" ) |
555 | .addInput("RHS" ) |
556 | .addResultFromCtorArg() |
557 | .dataParallel() |
558 | .setDocstring("Performs an element-wise bitwise XOR between the LHS and " |
559 | "RHS operands." ); |
560 | |
561 | BB.newNode("Not" ) |
562 | .addInput("Input" ) |
563 | .addResultFromCtorArg() |
564 | .dataParallel() |
565 | .setDocstring("Performs an element-wise logical NOT of the Input " |
566 | "operand." ); |
567 | |
568 | BB.newNode("BitwiseNot" ) |
569 | .addInput("Input" ) |
570 | .addResultFromCtorArg() |
571 | .dataParallel() |
572 | .setDocstring("Performs an element-wise bitwise NOT of the Input " |
573 | "operand." ); |
574 | |
575 | BB.newNode("Neg" ) |
576 | .addInput("Input" ) |
577 | .addResultFromCtorArg() |
578 | .dataParallel() |
579 | .setDocstring("Performs an element-wise negation (sign flip) of the " |
580 | "Input operand." ); |
581 | |
582 | BB.newNode("Abs" ) |
583 | .addInput("Input" ) |
584 | .addResultFromCtorArg() |
585 | .dataParallel() |
586 | .setDocstring("Performs an element-wise ABS(x) of the Input operand." ); |
587 | |
588 | BB.newNode("Floor" ) |
589 | .addInput("Input" ) |
590 | .addResultFromCtorArg() |
591 | .dataParallel() |
592 | .setDocstring("Performs an element-wise FLOOR(x) of the Input operand." ); |
593 | |
594 | BB.newNode("Sign" ) |
595 | .addInput("Input" ) |
596 | .addResultFromCtorArg() |
597 | .dataParallel() |
598 | .setDocstring("Performs an element-wise Sign(x) of the Input operand" ); |
599 | |
600 | BB.newNode("Ceil" ) |
601 | .addInput("Input" ) |
602 | .addResultFromCtorArg() |
603 | .dataParallel() |
604 | .setDocstring("Performs an element-wise CEIL(x) of the Input operand." ); |
605 | |
606 | BB.newNode("Round" ) |
607 | .addInput("Input" ) |
608 | .addResultFromCtorArg() |
609 | .dataParallel() |
610 | .setDocstring("Performs an element-wise ROUND(x) of the Input operand." ); |
611 | |
612 | BB.newNode("Truncate" ) |
613 | .addInput("Input" ) |
614 | .addResultFromCtorArg() |
615 | .dataParallel() |
616 | .setDocstring( |
617 | "Performs an element-wise TRUNCATE(x) of the Input operand." ); |
618 | |
619 | BB.newNode("Sqrt" ) |
620 | .addInput("Input" ) |
621 | .addResultFromCtorArg() |
622 | .dataParallel() |
623 | .setDocstring("Performs an element-wise SQRT(x) of the Input operand." ); |
624 | |
625 | BB.newNode("Rsqrt" ) |
626 | .addInput("Input" ) |
627 | .addResultFromCtorArg() |
628 | .dataParallel() |
629 | .setDocstring("Performs an element-wise RSQRT(x) = 1 / SQRT(x) of the " |
630 | "Input operand." ); |
631 | |
632 | BB.newNode("Reciprocal" ) |
633 | .addInput("Input" ) |
634 | .addResultFromCtorArg() |
635 | .dataParallel() |
636 | .setDocstring("Performs an element-wise RECIPROCAL(x) = 1 / x of the " |
637 | "Input operand." ); |
638 | |
639 | BB.newNode("Sin" ) |
640 | .addInput("Input" ) |
641 | .addResultFromCtorArg() |
642 | .dataParallel() |
643 | .setDocstring("Performs an element-wise SIN(x) of the Input operand." ); |
644 | |
645 | BB.newNode("Cos" ) |
646 | .addInput("Input" ) |
647 | .addResultFromCtorArg() |
648 | .dataParallel() |
649 | .setDocstring("Performs an element-wise COS(x) of the Input operand." ); |
650 | |
651 | // clang-format off |
652 | BB.newNode("Log" ) |
653 | .addInput("Input" ) |
654 | .addResultFromCtorArg() |
655 | .dataParallel() |
656 | .setDocstring("Performs element-wise natural log to the Input." ); |
657 | |
658 | BB.newNode("Acos" ) |
659 | .addInput("Input" ) |
660 | .addResultFromCtorArg() |
661 | .dataParallel() |
662 | .setDocstring("Performs an element-wise Arccosine(x) of the Input operand." ); |
663 | |
664 | BB.newNode("Asin" ) |
665 | .addInput("Input" ) |
666 | .addResultFromCtorArg() |
667 | .dataParallel() |
668 | .setDocstring("Performs an element-wise Arcsine(x) of the Input operand." ); |
669 | |
670 | BB.newNode("Atan" ) |
671 | .addInput("Input" ) |
672 | .addResultFromCtorArg() |
673 | .dataParallel() |
674 | .setDocstring("Performs an element-wise Arctan(x) of the Input operand." ); |
675 | |
676 | BB.newNode("Erf" ) |
677 | .addInput("Input" ) |
678 | .addResultFromCtorArg() |
679 | .dataParallel() |
680 | .setDocstring("Performs an element-wise Erf(x) of the Input operand." ); |
681 | |
682 | BB.newNode("Exp" ) |
683 | .addInput("Input" ) |
684 | .addResultFromCtorArg() |
685 | .dataParallel() |
686 | .setDocstring("Performs element-wise exponential to the Input." ); |
687 | // clang-format on |
688 | |
689 | BB.newNode("Logit" ) |
690 | .addInput("Input" ) |
691 | .addMember(MemberType::Float, "Epsilon" ) |
692 | .addResultFromCtorArg() |
693 | .dataParallel() |
694 | .setDocstring("Computes elementwise: result = log(input / (1 - input))." ); |
695 | |
696 | BB.newNode("NonZero" ) |
697 | .addInput("Cond" ) |
698 | .addResultFromCtorArg() |
699 | .dataParallel() |
700 | .setDocstring("Selects indices of the true elements in Cond" ); |
701 | |
702 | BB.newNode("Select" ) |
703 | .addInput("Cond" ) |
704 | .addInput("LHS" ) |
705 | .addInput("RHS" ) |
706 | .addResultFromCtorArg() |
707 | .dataParallel() |
708 | .setDocstring("Selects between values on the LHS or RHS, depending on " |
709 | "the value of Cond. Cond is generated by the compare " |
710 | "instruction, and is target- and type-specific." ); |
711 | |
712 | BB.newNode("BatchedAdd" ) |
713 | .addInput("Batch" ) |
714 | .addInput("Slice" ) |
715 | .addResultFromCtorArg() |
716 | .setDocstring( |
717 | "Adds the 'Slice' operand to each one of the slices in the batch." ); |
718 | |
719 | BB.newNode("BatchedMul" ) |
720 | .addInput("Batch" ) |
721 | .addInput("Slice" ) |
722 | .addResultFromCtorArg() |
723 | .setDocstring("Multiplies the 'Slice' operand to each one of the slices " |
724 | "in the batch." ); |
725 | |
726 | BB.newNode("MatMul" ) |
727 | .addInput("LHS" ) |
728 | .addInput("RHS" ) |
729 | .addResultFromCtorArg() |
730 | .setDocstring("Performs matrix multiplication between the LHS and RHS." |
731 | "Example: (A, Z) x (Z, B) => (A, B)" ); |
732 | |
733 | BB.newNode("BatchMatMul" ) |
734 | .addInput("LHS" ) |
735 | .addInput("RHS" ) |
736 | .addResultFromCtorArg() |
737 | .setDocstring("Performs batch matrix multiplication between the LHS and " |
738 | "RHS. The operands are a stack of two dimensional " |
739 | "matrices. Example: (N, A, Z) x (N, Z, B) => (N, A, B)" ); |
740 | |
741 | BB.newNode("BatchedReduceAdd" ) |
742 | .addInput("Batch" ) |
743 | .addMember(MemberType::Unsigned, "Axis" ) |
744 | .addResultFromCtorArg() |
745 | .setDocstring("Accumulates all of the layers in the batch and produce a " |
746 | "tensor that has the same dimensions as the input tensor " |
747 | "without the first dimension." ); |
748 | |
749 | BB.newNode("BatchedReduceSumSquare" ) |
750 | .addInput("Batch" ) |
751 | .addMember(MemberType::Unsigned, "Axis" ) |
752 | .addResultFromCtorArg() |
753 | .setDocstring( |
754 | "Accumulates squares of all of the layers in the batch and produce a " |
755 | "tensor that has the same dimensions as the input tensor " |
756 | "without the first dimension." ); |
757 | |
758 | BB.newNode("BatchedReduceMean" ) |
759 | .addInput("Batch" ) |
760 | .addMember(MemberType::VectorUnsigned, "Axes" ) |
761 | .addResultFromCtorArg() |
762 | .setDocstring("Performs Average Mean operation on the Input given " |
763 | "Axes." ); |
764 | |
765 | BB.newNode("BatchedReduceMin" ) |
766 | .addInput("Batch" ) |
767 | .addMember(MemberType::VectorUnsigned, "Axes" ) |
768 | .addResultFromCtorArg() |
769 | .setDocstring("Performs Reduce Min operation on the Input given " |
770 | "Axes." ); |
771 | |
772 | BB.newNode("BatchedReduceMax" ) |
773 | .addInput("Batch" ) |
774 | .addMember(MemberType::VectorUnsigned, "Axes" ) |
775 | .addResultFromCtorArg() |
776 | .setDocstring("Performs Reduce Max operation on the Input given " |
777 | "Axes." ); |
778 | |
779 | BB.newNode("BatchedReduceProd" ) |
780 | .addInput("Batch" ) |
781 | .addMember(MemberType::Unsigned, "Axis" ) |
782 | .addResultFromCtorArg() |
783 | .setDocstring("Accumulates the product all of the layers in the batch " |
784 | " and produce a tensor that has the same dimensions as " |
785 | " the input tensor without the first dimension." ); |
786 | |
787 | BB.newNode("ChannelShuffle" ) |
788 | .addInput("Input" ) |
789 | .addMember(MemberType::Unsigned, "Group" ) |
790 | .addMember(MemberType::Unsigned, "Kernel" ) |
791 | .addResultFromCtorArg() |
792 | .setDocstring("Performs Channel shuffle." ); |
793 | |
794 | BB.newNode("CumSum" ) |
795 | .addInput("Input" ) |
796 | .addMember(MemberType::Int64, "Dim" ) |
797 | .addMember(MemberType::Unsigned, "Exclusive" ) |
798 | .addMember(MemberType::Unsigned, "Reverse" ) |
799 | .addResultFromCtorArg() |
800 | .dataParallel() |
801 | .setDocstring("Performs a Cumulative Sum operation over a 1D vector with " |
802 | "flags for working in exclusive mode and in reverse. In " |
803 | "each case the output size is the same as in input size." |
804 | "e.g (default) [1, 2, 3, 4] -> [1, 3, 6, 10]. " |
805 | "(exclusive) [1, 2, 3, 4] -> [0, 1, 3, 6]. " |
806 | "(reverse) [1, 2, 3, 4] -> [10, 9, 7, 4]. " ); |
807 | |
808 | BB.newNode("LengthsSum" ) |
809 | .addInput("Data" ) |
810 | .addInput("Lengths" ) |
811 | .addResultFromCtorArg() |
812 | .setDocstring("Sums slices of the outermost dimension of Data in groups " |
813 | "defined by Lengths. The first Lengths[0] slices are " |
814 | "added together and stored in Result[0], the subsequent " |
815 | "Lengths[1] slices are added together and stored in " |
816 | "Result[1], etc." ); |
817 | |
818 | BB.newNode("SparseLengthsSum" ) |
819 | .addInput("Data" ) |
820 | .addInput("Indices" ) |
821 | .addInput("Lengths" ) |
822 | .addMember(MEMBER_TYPE_INFO(glow::LengthsMode), "LengthsMode" ) |
823 | .addMember(MemberType::Float, "AvgLength" ) |
824 | .addResultFromCtorArg() |
825 | .addGradient() |
826 | .setDocstring("Gathers slices of the outer-most dimension of Data " |
827 | "indexed by Indices vector, and then accumulates them into " |
828 | "len(Lengths) entries: first Lengths[0] slices are " |
829 | "aggregated to Result[0], next Lengths[1] slices are " |
830 | "aggregated to Result[1], etc. I.e. sum(Lengths) must be " |
831 | "equal to len(Indices)." ); |
832 | |
833 | BB.newNode("SparseLengthsWeightedSum" ) |
834 | .addInput("Data" ) |
835 | .addInput("Weights" ) |
836 | .addInput("Indices" ) |
837 | .addInput("Lengths" ) |
838 | .addMember(MEMBER_TYPE_INFO(glow::LengthsMode), "LengthsMode" ) |
839 | .addMember(MemberType::Float, "AvgLength" ) |
840 | .addResultFromCtorArg() |
841 | .addGradient() |
842 | .setDocstring("Gathers slices of the outer-most dimension of Data " |
843 | "indexed by Indices vector, and then accumulates them into " |
844 | "len(Lengths) entries: first Lengths[0] slices are " |
845 | "aggregated to Result[0], next Lengths[1] slices are " |
846 | "aggregated to Result[1], etc. I.e. sum(Lengths) must be " |
847 | "equal to len(Indices). Before doing aggregation, each " |
848 | "individual slice is scaled by its weight: Result[0] = " |
849 | "Weights[0] * Slice(0) + Weights[1] * Slice(1) + ... " |
850 | "It implies that len(Weights) == len(Indices)." ); |
851 | |
852 | BB.newNode("Embedding" ) |
853 | .addInput("Weights" ) |
854 | .addInput("Indices" ) |
855 | .addMember(MemberType::Int64, "PadIdx" ) |
856 | .addMember(MemberType::Boolean, "Scale" ) |
857 | .addMember(MemberType::Boolean, "Sparse" ) |
858 | .addResultFromCtorArg() |
859 | .setDocstring("Gathers slices of the outer-most dimension of Weights " |
860 | "indexed by Indices tensor." ); |
861 | |
862 | BB.newNode("EmbeddingBag" ) |
863 | .addInput("Data" ) |
864 | .addInput("Weights" ) |
865 | .addInput("Indices" ) |
866 | .addInput("Offsets" ) |
867 | .addMember(MemberType::Boolean, "HasEndOffset" ) |
868 | .addMember(MEMBER_TYPE_INFO(glow::LengthsMode), "LengthsMode" ) |
869 | .addMember(MemberType::Float, "AvgLength" ) |
870 | .addResultFromCtorArg() |
871 | .setDocstring( |
872 | "Gathers slices of the outer-most dimension of Data " |
873 | "indexed by Indices vector, and then accumulates them into " |
874 | "len(Offsets) entries: first slice between Offsets[0] and Offsets[1] " |
875 | "(or total length if there's only one elem in Offsets) are " |
876 | "aggregated to Result[0], etc. I.e. largest offset must be " |
877 | "less than or equal to len(Indices). Before doing aggregation, each " |
878 | "individual slice is scaled by its weight: Result[0] = " |
879 | "Weights[0] * Slice(0) + Weights[1] * Slice(1) + ... " |
880 | "It implies that len(Weights) == len(Indices)." ); |
881 | |
882 | BB.newNode("EmbeddingBagByteRowwiseOffsets" ) |
883 | .addInput("Data" ) |
884 | .addInput("Weights" ) |
885 | .addInput("Indices" ) |
886 | .addInput("Offsets" ) |
887 | .addMember(MemberType::Boolean, "UseFP16Accumulation" , |
888 | /* addSetter */ true) |
889 | .addMember(MemberType::Boolean, "HasEndOffset" ) |
890 | .addMember(MEMBER_TYPE_INFO(glow::LengthsMode), "LengthsMode" ) |
891 | .addMember(MemberType::Float, "AvgLength" ) |
892 | .addResultFromCtorArg() |
893 | .setDocstring("Same as FusedRowwiseQuantizedSparseLengthsWeightedSum but " |
894 | "using offsets instead of lengths." ); |
895 | |
896 | BB.newNode("RowwiseQuantizedSparseLengthsWeightedSum" ) |
897 | .addInput("Data" ) |
898 | .addInput("Scales" ) |
899 | .addInput("Offsets" ) |
900 | .addInput("Weights" ) |
901 | .addInput("Indices" ) |
902 | .addInput("Lengths" ) |
903 | .addMember(MemberType::Boolean, "UseFP16Accumulation" , |
904 | /* addSetter */ true) |
905 | .addMember(MEMBER_TYPE_INFO(glow::LengthsMode), "LengthsMode" ) |
906 | .addMember(MemberType::Float, "AvgLength" ) |
907 | .addResultFromCtorArg() |
908 | .setDocstring("Gathers slices of the outer-most dimension of Data " |
909 | "indexed by Indices vector, and then accumulates them into " |
910 | "len(Lengths) entries: first Lengths[0] slices are " |
911 | "aggregated to Result[0], next Lengths[1] slices are " |
912 | "aggregated to Result[1], etc. I.e. sum(Lengths) must be " |
913 | "equal to len(Indices). Before doing aggregation, each " |
914 | "individual slice is scaled by its weight: Result[0] = " |
915 | "Weights[0] * Slice(0) + Weights[1] * Slice(1) + ... " |
916 | "It implies that len(Weights) == len(Indices). The input " |
917 | "data is rowwise-quantized, where the Scales and Offsets " |
918 | "are 1D tensors of length equal to the first dim of Data." ); |
919 | |
920 | BB.newNode("FusedRowwiseQuantizedSparseLengthsWeightedSum" ) |
921 | .addInput("Data" ) |
922 | .addInput("Weights" ) |
923 | .addInput("Indices" ) |
924 | .addInput("Lengths" ) |
925 | .addMember(MemberType::Boolean, "UseFP16Accumulation" , |
926 | /* addSetter */ true) |
927 | .addMember(MEMBER_TYPE_INFO(glow::LengthsMode), "LengthsMode" ) |
928 | .addMember(MemberType::Float, "AvgLength" ) |
929 | .addResultFromCtorArg() |
930 | .setDocstring("Gathers slices of the outer-most dimension of Data " |
931 | "indexed by Indices vector, and then accumulates them into " |
932 | "len(Lengths) entries: first Lengths[0] slices are " |
933 | "aggregated to Result[0], next Lengths[1] slices are " |
934 | "aggregated to Result[1], etc. I.e. sum(Lengths) must be " |
935 | "equal to len(Indices). Before doing aggregation, each " |
936 | "individual slice is scaled by its weight: Result[0] = " |
937 | "Weights[0] * Slice(0) + Weights[1] * Slice(1) + ... " |
938 | "It implies that len(Weights) == len(Indices). The input " |
939 | "data is fused rowwise-quantized, where the Scales and " |
940 | "Offsets are appended to the end of each row. Thus, Data " |
941 | "must be a two-dimensional tensor." ); |
942 | |
943 | BB.newNode("FusedRowwiseQuantizedSparseLengthsSum" ) |
944 | .addInput("Data" ) |
945 | .addInput("Indices" ) |
946 | .addInput("Lengths" ) |
947 | .addMember(MemberType::Boolean, "UseFP16Accumulation" , |
948 | /* addSetter */ true) |
949 | .addMember(MEMBER_TYPE_INFO(glow::LengthsMode), "LengthsMode" ) |
950 | .addMember(MemberType::Float, "AvgLength" ) |
951 | .addResultFromCtorArg() |
952 | .setDocstring("Gathers slices of the outer-most dimension of Data " |
953 | "indexed by Indices vector, and then accumulates them into " |
954 | "len(Lengths) entries: first Lengths[0] slices are " |
955 | "aggregated to Result[0], next Lengths[1] slices are " |
956 | "aggregated to Result[1], etc. I.e. sum(Lengths) must be " |
957 | "equal to len(Indices). The input " |
958 | "data is fused rowwise-quantized, where the Scales and " |
959 | "Offsets are appended to the end of each row. Thus, Data " |
960 | "must be a two-dimensional tensor." ); |
961 | |
962 | BB.newNode("LengthsToRanges" ) |
963 | .addInput("Lengths" ) |
964 | .addResultFromCtorArg() |
965 | .setDocstring("Given a vector of segment lengths, calculates offsets of " |
966 | "each segment and packs them next to the lengths. For the " |
967 | "input vector of length N the output is a Nx2 matrix with " |
968 | "(offset, lengths) packaged for each segment." ); |
969 | |
970 | BB.newNode("LengthsRangeFill" ) |
971 | .addInput("Lengths" ) |
972 | .addResultFromCtorArg() |
973 | .setDocstring( |
974 | "Converts an input Lengths 1D vector into a range sequence." ); |
975 | |
976 | BB.newNode("BatchSparseToDense" ) |
977 | .addInput("Lengths" ) |
978 | .addInput("Indices" ) |
979 | .addInput("Values" ) |
980 | .addMember(MemberType::Float, "DefaultValue" ) |
981 | .addMember(MemberType::Unsigned, "DenseLastDim" ) |
982 | .addResultFromCtorArg() |
983 | .setDocstring( |
984 | "Converts the sparse representation specified by " |
985 | "(Lengths, Indices, Values) into a dense one. In the dense " |
986 | "representation, elements of the lengths vector represent the number " |
987 | "of indices in the corresponding batch, where each batch " |
988 | "contains each value from Values at the " |
989 | "corresponding index specified in Indices, and is filled with " |
990 | "DefaultValue otherwise. Within each batch, Indices shouldn't " |
991 | "contain duplicate indices." ); |
992 | |
993 | BB.newNode("FillExamplesWithIndicator" ) |
994 | .addInput("Data" ) |
995 | .addInput("Indicator" ) |
996 | .addResultFromCtorArg() |
997 | .setDocstring("Inserts zeros into data along axis=0 for indices where " |
998 | "indicator is zero." ); |
999 | |
1000 | BB.newNode("SparseToDenseMask" ) |
1001 | .addInput("Indices" ) |
1002 | .addInput("Values" ) |
1003 | .addInput("DefaultValue" ) |
1004 | .addInput("Lengths" ) |
1005 | .addMember(MemberType::VectorDimT, "Mask" ) |
1006 | .addResultFromCtorArg() |
1007 | .setDocstring( |
1008 | "Converts the sparse representation specified by the pair " |
1009 | "(Indices, Values) into a dense one, where compacted tensor only " |
1010 | "contains IDs from given Mask. Indices cannot contain duplicate " |
1011 | "values. Lengths is used to distinguish elements from different " |
1012 | "examples of one batch. That is, first Lengths[0] index-value pairs " |
1013 | "belong to batch's example 0, next Lengths[1] pairs belong to " |
1014 | "example 1, and so on." ); |
1015 | |
1016 | // clang-format off |
1017 | BB.newNode("IsNaN" ) |
1018 | .addInput("Input" ) |
1019 | .addResultFromCtorArg() |
1020 | .dataParallel() |
1021 | .setDocstring("Determines whether each element of the Input is NaN and " |
1022 | "generates a mask that can be consumed by a Select node." ); |
1023 | // clang-format on |
1024 | |
1025 | BB.newNode("ReplaceNaN" ) |
1026 | .addInput("Input" ) |
1027 | .addMember(MemberType::Float, "Value" ) |
1028 | .addResultFromCtorArg() |
1029 | .setDocstring("Replaces NaNs found in Input with Value." ); |
1030 | |
1031 | BB.newNode("Modulo" ) |
1032 | .addInput("Input" ) |
1033 | .addMember(MemberType::Int64, "Divisor" ) |
1034 | .addMember(MemberType::Boolean, "SignFollowDivisor" ) |
1035 | .addResultFromCtorArg() |
1036 | .dataParallel() |
1037 | .setDocstring("Performs elementwise modulo operation on the input where " |
1038 | "each element in the output is the corresponding element " |
1039 | "in the input data modulo Divisor." ); |
1040 | |
1041 | BB.newNode("BatchedPairwiseDotProduct" ) |
1042 | .addMember(MemberType::VectorNodeValue, "Inputs" ) |
1043 | .addResultFromCtorArg() |
1044 | .setDocstring( |
1045 | "Performs batched pairwise dot products of the input vectors" ); |
1046 | |
1047 | BB.newNode("BatchedPairwiseDotProductGrad" ) |
1048 | .addInput("OutputGrad" ) |
1049 | .hasExtraResults() |
1050 | .addMember(MemberType::VectorNodeValue, "OriginalInputs" ) |
1051 | .setDocstring( |
1052 | "Performs the gradient operation for BatchedPairwiseDotProduct" ); |
1053 | |
1054 | BB.newNode("BatchedUnaryEmbeddingsBags" ) |
1055 | .addInput("Weights" ) |
1056 | .addInput("TableOffsets" ) |
1057 | .addInput("Offsets" ) |
1058 | .addInput("Indices" ) |
1059 | .addResultFromCtorArg() |
1060 | .setDocstring("Sum weight embeddings according to offsets and indices" ); |
1061 | |
1062 | BB.newNode("IntNBitSplitEmbeddingBags" ) |
1063 | .addInput("DevWeights" ) |
1064 | .addInput("UvmWeights" ) |
1065 | .addInput("WeightsPlacements" ) |
1066 | .addInput("WeightsOffsets" ) |
1067 | .addInput("WeightsTys" ) |
1068 | .addInput("DimOffsets" ) |
1069 | .addInput("Indices" ) |
1070 | .addInput("Offsets" ) |
1071 | .addMember(MemberType::Int64, "TotalDims" ) |
1072 | .addMember(MEMBER_TYPE_INFO(glow::SplitEmbeddingPoolingMode), |
1073 | "PoolingMode" ) |
1074 | .addMember(MEMBER_TYPE_INFO(glow::SplitEmbeddingSparseType), |
1075 | "OutputDType" ) |
1076 | .addResultFromCtorArg() |
1077 | .setDocstring("Table based batched embeddingbags with quantization " |
1078 | "support. Experimental only and subject to change." ); |
1079 | |
1080 | BB.newNode("IntNBitSplitEmbeddingWeightedBags" ) |
1081 | .addInput("DevWeights" ) |
1082 | .addInput("UvmWeights" ) |
1083 | .addInput("WeightsPlacements" ) |
1084 | .addInput("WeightsOffsets" ) |
1085 | .addInput("WeightsTys" ) |
1086 | .addInput("DimOffsets" ) |
1087 | .addInput("Indices" ) |
1088 | .addInput("Offsets" ) |
1089 | .addInput("IndiceWeight" ) |
1090 | .addMember(MemberType::Int64, "TotalDims" ) |
1091 | .addMember(MEMBER_TYPE_INFO(glow::SplitEmbeddingPoolingMode), |
1092 | "PoolingMode" ) |
1093 | .addMember(MEMBER_TYPE_INFO(glow::SplitEmbeddingSparseType), |
1094 | "OutputDType" ) |
1095 | .addResultFromCtorArg() |
1096 | .setDocstring( |
1097 | "Table based batched embeddingbags with quantization support and " |
1098 | "indice weights. Experimental only and subject to change." ); |
1099 | |
1100 | //===--------------------------------------------------------------------===// |
1101 | // Fillers |
1102 | //===--------------------------------------------------------------------===// |
1103 | |
1104 | BB.newNode("GaussianFill" ) |
1105 | .addInput("Input" ) |
1106 | .addMember(MemberType::Float, "Mean" ) |
1107 | .addMember(MemberType::Float, "Scale" ) |
1108 | .addMember(MemberType::Float, "Seed" ) |
1109 | .addResultFromCtorArg() |
1110 | .setDocstring("Fills an output tensor with samples drawn from a normal " |
1111 | "distribution specified by the mean and standard deviation " |
1112 | "arguments. The output tensor shape is determined by the " |
1113 | "input shape if provided, and shape otherwise" ); |
1114 | |
1115 | //===--------------------------------------------------------------------===// |
1116 | // Non-linearities |
1117 | //===--------------------------------------------------------------------===// |
1118 | |
1119 | BB.newNode("Relu" ) |
1120 | .addInput("Input" ) |
1121 | .addResultFromCtorArg() |
1122 | .dataParallel() |
1123 | .addGradient() |
1124 | .setDocstring( |
1125 | "Applies ReLU, max(0, x), to each element in the Input tensor." ); |
1126 | |
1127 | BB.newNode("HardSwish" ) |
1128 | .addInput("Input" ) |
1129 | .addResultFromCtorArg() |
1130 | .dataParallel() |
1131 | .setDocstring("Applies HardSwish to each element in the Input tensor." ); |
1132 | |
1133 | BB.newNode("Gelu" ) |
1134 | .addInput("Input" ) |
1135 | .addResultFromCtorArg() |
1136 | .dataParallel() |
1137 | .setDocstring("Applies GeLU, to each element in the Input tensor." ); |
1138 | |
1139 | BB.newNode("Clip" ) |
1140 | .addInput("Input" ) |
1141 | .addMember(MemberType::Float, "Min" ) |
1142 | .addMember(MemberType::Float, "Max" ) |
1143 | .addResultFromCtorArg() |
1144 | .dataParallel() |
1145 | .setDocstring("Clip range of inputs to lie in [Min, Max]." ); |
1146 | |
1147 | BB.newNode("PRelu" ) |
1148 | .addInput("Input" ) |
1149 | .addInput("Slope" ) |
1150 | .addResultFromCtorArg() |
1151 | .dataParallel() |
1152 | .setDocstring("Applies PReLU, slope * min(0, x) + max(0, x), to each " |
1153 | "element in the Input tensor." ); |
1154 | |
1155 | BB.newNode("Sigmoid" ) |
1156 | .addInput("Input" ) |
1157 | .addResultFromCtorArg() |
1158 | .dataParallel() |
1159 | .addGradient() |
1160 | .setDocstring("Applies Sigmoid, 1 / (1 + exp(-x)), to each element in " |
1161 | "the Input tensor." ); |
1162 | |
1163 | BB.newNode("Swish" ) |
1164 | .addInput("Input" ) |
1165 | .addResultFromCtorArg() |
1166 | .dataParallel() |
1167 | .setDocstring("Applies Swish, X * Sigmoid(X), to each element in " |
1168 | "the Input tensor." ); |
1169 | |
1170 | BB.newNode("Tanh" ) |
1171 | .addInput("Input" ) |
1172 | .addResultFromCtorArg() |
1173 | .dataParallel() |
1174 | .addGradient() |
1175 | .setDocstring("Applies hyperbolic tangent to each element in the Input " |
1176 | "tensor." ); |
1177 | |
1178 | BB.newNode("LeakyRelu" ) |
1179 | .addInput("Input" ) |
1180 | .addMember(MemberType::Float, "Alpha" ) |
1181 | .addResultFromCtorArg() |
1182 | .dataParallel() |
1183 | .setDocstring( |
1184 | "Applies LeakyReLU = x for positive x and alpha * x for negative x " |
1185 | "to each element in the Input tensor." ); |
1186 | |
1187 | BB.newNode("SoftPlus" ) |
1188 | .addInput("Input" ) |
1189 | .addResultFromCtorArg() |
1190 | .dataParallel() |
1191 | .setDocstring("Performs SoftPlus, ln(exp(x) + 1), to each element in the " |
1192 | "Input tensor." ); |
1193 | |
1194 | //===--------------------------------------------------------------------===// |
1195 | // Shape transformations |
1196 | //===--------------------------------------------------------------------===// |
1197 | |
1198 | BB.newNode("Reshape" ) |
1199 | .addInput("Input" ) |
1200 | .addMember(MemberType::VectorDimT, "Dims" ) |
1201 | .addMember(MemberType::String, "Layout" ) |
1202 | .addResultFromCtorArg() |
1203 | .setDocstring("Reshape the Input tensor to shape Dims." ); |
1204 | |
1205 | BB.newNode("Transpose" ) |
1206 | .addInput("Input" ) |
1207 | .addMember(MemberType::VectorUnsigned, "Shuffle" ) |
1208 | .addMember(MemberType::String, "Layout" ) |
1209 | .addResultFromCtorArg() |
1210 | .setDocstring("Transpose the Input tensor based on the vector Shuffle, " |
1211 | "which assigns a new axis for each dimension in Input." ); |
1212 | |
1213 | BB.newNode("Concat" ) |
1214 | .addMember(MemberType::VectorNodeValue, "Inputs" ) |
1215 | .addMember(MemberType::Unsigned, "Dim" ) |
1216 | .addResultFromCtorArg() |
1217 | .setDocstring("The concat operator adds two tensors together.\nThe " |
1218 | "parameter 'dim' specifies the dimension to use when " |
1219 | "joining the tensors." ); |
1220 | |
1221 | BB.newNode("Slice" ) |
1222 | .addInput("Input" ) |
1223 | .addMember(MemberType::VectorDimT, "Start" ) |
1224 | .addResultFromCtorArg() |
1225 | .setDocstring("Produces a slice of the Input tensor. The Start vector " |
1226 | "defines the starting indices for each dimension from " |
1227 | "which the slice should be taken. The end index for each " |
1228 | "dimension is determined from the input type's shape." ); |
1229 | |
1230 | BB.newNode("InsertTensor" ) |
1231 | .addInput("Big" ) |
1232 | .addInput("Small" ) |
1233 | .addMember(MemberType::VectorDimT, "Start" ) |
1234 | .addMember(MemberType::Unsigned, "Count" ) |
1235 | .addMember(MemberType::Unsigned, "Axis" ) |
1236 | .addResult("Big.getType()" ) |
1237 | .setDocstring("Insert tensor Small into tensor Big given indices Start. " |
1238 | "Small is inserted Count times along Axis. The resulting " |
1239 | "Tensor will have the same type as the input Big tensor." ); |
1240 | |
1241 | // TODO: Rename "BatchDims" member to "Axis". This was attempted in #5565 but |
1242 | // some internal FB tests failed. The member needs to be renamed because that |
1243 | // is the true meaning of the member and that is what the implementation does |
1244 | // according to both Caffe2, ONNX and TFLite operator definitions. |
1245 | // https://github.com/onnx/onnx/blob/master/docs/Operators.md#gather |
1246 | // https://www.tensorflow.org/mlir/tfl_ops#tflgather_tflgatherop |
1247 | BB.newNode("Gather" ) |
1248 | .addInput("Data" ) |
1249 | .addInput("Indices" ) |
1250 | .addMember(MemberType::Unsigned, "BatchDims" ) |
1251 | .addResultFromCtorArg() |
1252 | .setDocstring("Gathers entries of the outer-most dimension of Data " |
1253 | "indexed by Indices, and concatenates them. Output tensor " |
1254 | "will have dimensions: {I_0, I_1, ... I_n, D_1, D_2, ... " |
1255 | "D_m}, where D_i and I_j denote Data and Indices " |
1256 | "dimensions respectively. If axis is not zero, the " |
1257 | "gather operator will treat the first axis as the " |
1258 | "batch and will concat the result of the gather operation " |
1259 | "on each sample in the batch." ); |
1260 | |
1261 | BB.newNode("GatherND" ) |
1262 | .addInput("Data" ) |
1263 | .addInput("Indices" ) |
1264 | .addMember(MemberType::Unsigned, "BatchDims" ) |
1265 | .addResultFromCtorArg() |
1266 | .setDocstring( |
1267 | "Given Data tensor of rank r >= 1, Indices tensor of rank q >= 1 " |
1268 | "This operator gathers slices of Data into " |
1269 | "an output tensor of rank q + r - Indices_shape[-1] - 1 ." ); |
1270 | |
1271 | BB.newNode("GatherElements" ) |
1272 | .addInput("Data" ) |
1273 | .addInput("Indices" ) |
1274 | .addMember(MemberType::Unsigned, "Dim" ) |
1275 | .addResultFromCtorArg() |
1276 | .setDocstring( |
1277 | "GatherElements takes inputs data and indices of the same rank r " |
1278 | ">= 1 and an attribute axis specified by dim. It is an indexing" |
1279 | "operation that produces its output by indexing into the " |
1280 | "input data tensor at index positions determined by elements of the " |
1281 | "indices tensor. Its output shape is the same as the shape of " |
1282 | "indices and consists of one value (gathered from the data) for each " |
1283 | "element in indices." ); |
1284 | |
1285 | BB.newNode("GatherRanges" ) |
1286 | .addInput("Data" ) |
1287 | .addInput("Ranges" ) |
1288 | .addResultFromCtorArg("Output" ) |
1289 | .addResultFromCtorArg("Lengths" ) |
1290 | .setDocstring("Gathers entries of Data into Output in groups specified " |
1291 | "by the elements of Ranges. Each element of Ranges " |
1292 | "contains a list of pairs of indices of the form (index, " |
1293 | "length) which specify which entries of data to gather. " |
1294 | "The ordering of elements in Ranges and of pairs within an " |
1295 | "element is preserved in Output. Lengths contains the " |
1296 | "lengths of the ranges gathered by each list of pairs in " |
1297 | "Ranges." ); |
1298 | |
1299 | BB.newNode("ScatterData" ) |
1300 | .addInput("Data" ) |
1301 | .addInput("Indices" ) |
1302 | .addInput("Slices" ) |
1303 | .addMember(MemberType::Boolean, "Cumulative" ) |
1304 | .addResult("Data.getType()" ) |
1305 | .setDocstring( |
1306 | "Copies each slice from Slices into Data at the " |
1307 | "corresponding index in Indices. For example, given input " |
1308 | "Data {{1,2},{3,4},{5,6}}, Slices {{-3,-4}}, and Indices " |
1309 | "{{1}}, the result is {{1,2},{-3,-4},{5,6}}. It also supports " |
1310 | "multi-dimensional indices. For example, given input Data " |
1311 | "{{1,2},{3,4},{5,6}}, Slices {-3,-4}, and Indices {{1,0},{1,1}} also " |
1312 | "produces {{1,2},{-3,-4},{5,6}}. If Cumulative is true, the node " |
1313 | "adds values from Slices to Data instead of copying. For example, " |
1314 | "given input Data {{1,2},{3,4},{5,6}}, Slices {{-3,-4}}, and Indices " |
1315 | "{1}, the result is {{1,2},{0,0},{5,6}}. If an index is specified " |
1316 | "several times, its updates will be added several times as well." ); |
1317 | |
1318 | BB.newNode("Tile" ) |
1319 | .addInput("Input" ) |
1320 | .addMember(MemberType::Unsigned, "Count" ) |
1321 | .addMember(MemberType::Unsigned, "Axis" ) |
1322 | .addResultFromCtorArg() |
1323 | .setDocstring("Tile an Input tensor Count times along Axis." ); |
1324 | |
1325 | BB.newNode("BatchOneHot" ) |
1326 | .addInput("Data" ) |
1327 | .addInput("Lengths" ) |
1328 | .addInput("Values" ) |
1329 | .addResultFromCtorArg() |
1330 | .setDocstring("Expands each row of the Data to a row of zeros and ones, " |
1331 | "according to One Hot Encoding. i-th element of Result's " |
1332 | "row is one iff Values[i] equals to the corresponding " |
1333 | "element of Data." ); |
1334 | |
1335 | BB.newNode("SpaceToDepth" ) |
1336 | .addInput("Input" ) |
1337 | .addMember(MemberType::Unsigned, "BlockSize" ) |
1338 | .addResultFromCtorArg() |
1339 | .setDocstring("Given Input tensor of [N,H,W,C], where N is the batch " |
1340 | "axis, C is the channel or depth, H is the height and W is " |
1341 | "the width. This produces Output tensor of [N, " |
1342 | "H/BlockSize, W/BlockSize, C * " |
1343 | "BlockSize * BlockSize]." ); |
1344 | |
1345 | BB.newNode("ResizeNearest" ) |
1346 | .addInput("Input" ) |
1347 | .addMember(MemberType::VectorFloat, "Scale" ) |
1348 | .addResultFromCtorArg() |
1349 | .setDocstring( |
1350 | "Given Input tensor of 3D, 4D, 5D or 6D, generates an " |
1351 | "Output tensor with resized spatial dimensions using nearest " |
1352 | "neighbor interpolation. The Output tensor is of shape " |
1353 | "floor(input_dimension * scale)" ); |
1354 | |
1355 | BB.newNode("ResizeBilinear" ) |
1356 | .addInput("Input" ) |
1357 | .addMember(MemberType::VectorFloat, "Scale" ) |
1358 | .addResultFromCtorArg() |
1359 | .setDocstring( |
1360 | "Given Input tensor of [N,H,W,C], where N is the batch, C is the " |
1361 | "channel or depth, H is the height and W is the width, Generates an " |
1362 | "Output tensor with resized spatial dimensions using bilinear " |
1363 | "neighbor interpolation. The Output tensor is of shape " |
1364 | "floor(input_dimension * scale)" ); |
1365 | |
1366 | BB.newNode("Broadcast" ) |
1367 | .addInput("Input" ) |
1368 | .addMember(MemberType::Unsigned, "Axis" ) |
1369 | .addMember(MemberType::VectorDimT, "TargetDim" ) |
1370 | .addResultFromCtorArg() |
1371 | .setDocstring( |
1372 | "Broadcast the Input tensor to TargetDim using Axis to indicate the " |
1373 | "offset between Input dimension and TargetDim" ); |
1374 | |
1375 | BB.newNode("SparseLabelSplit" ) |
1376 | .addInput("Lengths" ) |
1377 | .addInput("Indices" ) |
1378 | .addInput("Values" ) |
1379 | .addMember(MemberType::Unsigned, "NumLabels" ) |
1380 | .addResultFromCtorArg("LabelValues" ) |
1381 | .addResultFromCtorArg("ExampleIds" ) |
1382 | .addResultFromCtorArg("GradientOffsetMap" ) |
1383 | .setDocstring("TODO" ); |
1384 | |
1385 | //===--------------------------------------------------------------------===// |
1386 | // Reorder transformations |
1387 | //===--------------------------------------------------------------------===// |
1388 | |
1389 | BB.newNode("Flip" ) |
1390 | .addInput("Input" ) |
1391 | .addMember(MemberType::Unsigned, "Axis" ) |
1392 | .addResultFromCtorArg() |
1393 | .setDocstring( |
1394 | "Reverse the order of elements in a tensor along the given axis. The " |
1395 | "shape of the tensor is preserved, but the elements are reordered. " |
1396 | "The node is inspired from Python numpy." ); |
1397 | |
1398 | //===--------------------------------------------------------------------===// |
1399 | // Nodes used for network training |
1400 | //===--------------------------------------------------------------------===// |
1401 | |
1402 | BB.newNode("Splat" ) |
1403 | .addMember(MemberType::Float, "Value" ) |
1404 | .addResultFromCtorArg() |
1405 | .setDocstring("Generate a tensor of a specific type filled with 'Value'." |
1406 | "Splat always keep floating point value internally but can" |
1407 | "quantize it based on the output type." ); |
1408 | |
1409 | // clang-format off |
1410 | BB.newNode("Touch" ) |
1411 | .addResultFromCtorArg() |
1412 | .setDocstring( |
1413 | "Generate a tensor of a specific type without initializing " |
1414 | "it. This is useful when filling a big tensor entirely with " |
1415 | "multiple small slices using InsertTensor nodes such that " |
1416 | "the big tensor is not required to be initialized (filled) " |
1417 | "with some value prior to insertion. This node is intended " |
1418 | "to remove the overhead associated with the initialization " |
1419 | "in situations where it is not required." ); |
1420 | // clang-format on |
1421 | |
1422 | BB.newNode("SGD" ) |
1423 | .addInput("Gradient" ) |
1424 | .addInput("Weight" ) |
1425 | .addMember(MemberType::Float, "L1Decay" ) |
1426 | .addMember(MemberType::Float, "L2Decay" ) |
1427 | .addMember(MemberType::Float, "LearningRate" ) |
1428 | .addMember(MemberType::Float, "Momentum" ) |
1429 | .addMember(MemberType::Unsigned, "BatchSize" ) |
1430 | .addResult("Weight.getType()" , "UpdatedWeight" ) |
1431 | .setHasSideEffects(true) |
1432 | .setDocstring("Stochastic Gradient Descent node used during training. " |
1433 | "Produces the updated weight that needs to be used " |
1434 | "instead of Weight for the next iteration." ); |
1435 | |
1436 | //===--------------------------------------------------------------------===// |
1437 | // Nodes used for debugging/profiling/printing |
1438 | //===--------------------------------------------------------------------===// |
1439 | |
1440 | BB.newNode("TraceEvent" ) |
1441 | .addInput("Data" ) |
1442 | .addMember(MemberType::String, "EventName" ) |
1443 | .addMember(MemberType::String, "EventType" ) |
1444 | .addMember(MemberType::Unsigned, "Index" ) |
1445 | .setHasSideEffects(true) |
1446 | .setDocstring("Inserts a TraceEvent for profiling." ); |
1447 | |
1448 | //===--------------------------------------------------------------------===// |
1449 | // Nodes used by quantization. |
1450 | //===--------------------------------------------------------------------===// |
1451 | |
1452 | BB.newNode("QuantizationProfile" ) |
1453 | .addInput("Input" ) |
1454 | .addInput("Histogram" ) |
1455 | .addInput("ComputationInfo" ) |
1456 | .addMember(MemberType::String, "ProfiledNodeName" ) |
1457 | .addMember(MemberType::Unsigned, "ProfiledOutputNumber" ) |
1458 | .addExtraMethod( |
1459 | "Placeholder *getHistogramPlaceholder() const ;\n" , |
1460 | "Placeholder *QuantizationProfileNode::getHistogramPlaceholder() " |
1461 | "const { return " |
1462 | "llvm::cast<Placeholder>(Histogram_.getNode()); };\n" ) |
1463 | .addExtraMethod( |
1464 | "Placeholder *getComputationInfoPlaceholder() const;\n" , |
1465 | "Placeholder " |
1466 | "*QuantizationProfileNode::getComputationInfoPlaceholder() const " |
1467 | "{ " |
1468 | "return llvm::cast<Placeholder>(ComputationInfo_.getNode()); };\n" ) |
1469 | .addOverwrittenInput("ComputationInfo" ) |
1470 | .addOverwrittenInput("Histogram" ) |
1471 | .setHasSideEffects(true) |
1472 | .setDocstring( |
1473 | "Generate profile (distribution of values) of the Input " |
1474 | "tensor. This data is used for quantization of the tensor " |
1475 | "later on. ProfiledNodeName contains the name of the node " |
1476 | "which is profiled by the QuantizationProfile node. " |
1477 | "ProfiledNodeName is helpful as lowering might transform the " |
1478 | "original graph. " |
1479 | "ProfiledOutputNumber contains the position of the node's output " |
1480 | "which gets profiled." ); |
1481 | |
1482 | BB.newNode("IntLookupTable" ) |
1483 | .addInput("Input" ) |
1484 | .addInput("Mapping" ) |
1485 | .addResultFromCtorArg() |
1486 | .dataParallel() |
1487 | .setDocstring("Simple mapping between quantized numbers." |
1488 | "This can be used as quantized sigmoid or tanh functions." ); |
1489 | |
1490 | BB.newNode("Quantize" ) |
1491 | .addInput("Input" ) |
1492 | .addResultFromCtorArg() |
1493 | .dataParallel() |
1494 | .setDocstring("Quantize floating point tensor. This operation converts " |
1495 | "floating point numbers to integers based on the given " |
1496 | "Scale and Offset. Scale and Offset are deduced from the " |
1497 | "type of the output." |
1498 | "x_q = clip(round(x/Scale) + Offset, -128, 127)" ); |
1499 | |
1500 | BB.newNode("Dequantize" ) |
1501 | .addInput("Input" ) |
1502 | .addResultFromCtorArg() |
1503 | .dataParallel() |
1504 | .setDocstring("Convert quantized input tensor into the float " |
1505 | "representation. x = Scale * (x_q - Offset)." ); |
1506 | |
1507 | BB.newNode("RescaleQuantized" ) |
1508 | .addInput("Input" ) |
1509 | .addResultFromCtorArg() |
1510 | .dataParallel() |
1511 | .setDocstring("Rescale the input quantized tensor to a new Scale and " |
1512 | "Offset. The new Scale and Offset are specified by the " |
1513 | "output type passed to the constructor" ); |
1514 | |
1515 | //===--------------------------------------------------------------------===// |
1516 | // Nodes used by RNN |
1517 | //===--------------------------------------------------------------------===// |
1518 | |
1519 | BB.newNode("TopK" ) |
1520 | .addInput("Input" ) |
1521 | .addMember(MemberType::Unsigned, "K" ) |
1522 | .addResultFromCtorArg("Values" ) |
1523 | .addResultFromCtorArg("Indices" ) |
1524 | .setDocstring("Finds the top K maximal elements for each vector in the " |
1525 | "tensor. Vectors are defined as the last dimension in the " |
1526 | "tensor. The input shape {D_0, D_1, ... D_n} results in " |
1527 | "the outputs {D_0, D_1, ... D_n-1, K}, sorted in " |
1528 | "non-decreasing order." ); |
1529 | |
1530 | BB.newNode("LSTMUnit" ) |
1531 | .addInput("Input" ) |
1532 | .addInput("C" ) |
1533 | .addResult("C.getType()" , "newC" ) |
1534 | .addResult("C.getType()" , "newH" ) |
1535 | .setDocstring( |
1536 | "A LSTM unit node, take Input as I, F, G, O," |
1537 | "takes F from forget gate, I from input gate," |
1538 | "O from output gate, G from cell gate and C from cell state. " |
1539 | "Calulates newC = sigmoid(F) * C + sigmoid(I) * tanh(G), " |
1540 | "newH = tanh(newC) * sigmoid(O)." ); |
1541 | |
1542 | //===--------------------------------------------------------------------===// |
1543 | // Conversions |
1544 | //===--------------------------------------------------------------------===// |
1545 | |
1546 | BB.newNode("ConvertTo" ) |
1547 | .addInput("Input" ) |
1548 | .addResultFromCtorArg() |
1549 | .dataParallel() |
1550 | .setDocstring( |
1551 | "Convert the input from its current type to the destination " |
1552 | "type. The input and output types must have the same shapes. " |
1553 | "Moreover the input and output types must not be quantized types. " |
1554 | "Quantized types should use the appropriate Quantize, Dequantize, " |
1555 | "and Rescale nodes." ); |
1556 | |
1557 | //===--------------------------------------------------------------------===// |
1558 | // Custom kernels invocations |
1559 | //===--------------------------------------------------------------------===// |
1560 | BB.newNode("ExternalFunctionCall" ) |
1561 | .addMember(MemberType::VectorNodeValue, "Inputs" ) |
1562 | // For now use single output. |
1563 | .addResultFromCtorArg() |
1564 | .addMember(MemberType::String, "FunctionName" ) |
1565 | // Examples are function source code, binary, or as needed. |
1566 | // The use of the following two fields will vary depending |
1567 | // on which kind of external function is used. |
1568 | .addMember(MemberType::String, "FunctionImpl" ) |
1569 | // Function kind, e.g. CUDA, function pointer, binary, backend-specific |
1570 | // source code. |
1571 | .addMember(MemberType::String, "FunctionKind" ) |
1572 | .skipAutogenSerialization() |
1573 | .setHasSideEffects(true) |
1574 | .setDocstring("This is a node representing an external function call. " |
1575 | "One possible use of this capability is to pass a source " |
1576 | "code for a function/kernel. When processing this node, a " |
1577 | "backend can compile and execute the source code. This " |
1578 | "node can also be used to pass binary or pointers to " |
1579 | "executable code. The semantics and implementation of this " |
1580 | "node not standardized and is very backend-specific." ); |
1581 | |
1582 | //===--------------------------------------------------------------------===// |
1583 | // Pre Processing |
1584 | //===--------------------------------------------------------------------===// |
1585 | |
1586 | BB.newNode("AudioSpectrogram" ) |
1587 | .addInput("Input" ) |
1588 | .addInput("Window" ) |
1589 | .addInput("TwiddleFactors" ) |
1590 | .addInput("BitReverseIndices" ) |
1591 | .addInput("ComplexToRealWeights" ) |
1592 | .addMember(MemberType::Unsigned, "WindowSize" ) |
1593 | .addMember(MemberType::Unsigned, "WindowStride" ) |
1594 | .addMember(MemberType::Boolean, "MagnitudeSquared" ) |
1595 | .addResultFromCtorArg("Spectrogram" ) |
1596 | .setDocstring("Computes the spectrogram of a mono audio signal using " |
1597 | "given window size and stride. The FFT length used to " |
1598 | "compute the spectrogram is the next power of 2 (for a " |
1599 | "window size of 640 the FFT length is 1024). The length " |
1600 | "of each spectrogram window is FFT_length / 2 + 1. " |
1601 | "This node is inspired from TensorFlow." ); |
1602 | |
1603 | BB.newNode("MFCC" ) |
1604 | .addInput("Spectrogram" ) |
1605 | .addInput("MelWeights" ) |
1606 | .addInput("MelRanges" ) |
1607 | .addInput("DctMat" ) |
1608 | .addMember(MemberType::Float, "SampleRate" ) |
1609 | .addMember(MemberType::Float, "LowerFrequency" ) |
1610 | .addMember(MemberType::Float, "UpperFrequency" ) |
1611 | .addMember(MemberType::Unsigned, "FilterBankCount" ) |
1612 | .addMember(MemberType::Unsigned, "NumCoefficients" ) |
1613 | .addResultFromCtorArg("Coefficients" ) |
1614 | .setDocstring("Computes the MFCC (Mel Frequency Cepstral Coefficient) " |
1615 | "for the given spectrogram. This node is mostly used as " |
1616 | "feature extractor for voice/speech audio data in " |
1617 | "voice command or keyword spotting applications. The input " |
1618 | "is assumed to be a power spectrogram and not a magnitude." |
1619 | "This node is inspired from TensorFlow." ); |
1620 | |
1621 | //===--------------------------------------------------------------------===// |
1622 | // Post Processing |
1623 | //===--------------------------------------------------------------------===// |
1624 | |
1625 | BB.newNode("NonMaxSuppression" ) |
1626 | .addInput("Boxes" ) |
1627 | .addInput("Scores" ) |
1628 | .addMember(MemberType::Unsigned, "CenterPointBox" ) |
1629 | .addMember(MemberType::Unsigned, "MaxOutputBoxesPerClass" ) |
1630 | .addMember(MemberType::Float, "IouThreshold" ) |
1631 | .addMember(MemberType::Float, "ScoreThreshold" ) |
1632 | .addMember(MemberType::Boolean, "IsTFVersion4" ) |
1633 | .addResultFromCtorArg("Indices" ) |
1634 | .addResultFromCtorArg("NumberOfSelectedIndices" ) |
1635 | .setDocstring("This is a mix of ONNX and TF NMSv4. It supports multiple " |
1636 | "classes and does per class NMS. It also supports TF NMS " |
1637 | "V4 by outputting indices and scalar tensor with number of " |
1638 | "valid indices. It pads the rest with global MIN box." ); |
1639 | |
1640 | BB.newNode("TFLiteDetectionPostProcess" ) |
1641 | .addInput("Boxes" ) |
1642 | .addInput("Scores" ) |
1643 | .addInput("Anchors" ) |
1644 | .addMember(MemberType::Unsigned, "NumClasses" ) |
1645 | .addMember(MemberType::Unsigned, "MaxDetections" ) |
1646 | .addMember(MemberType::Unsigned, "MaxClassesPerDetection" ) |
1647 | .addMember(MemberType::Unsigned, "MaxDetectionsPerClass" ) |
1648 | .addMember(MemberType::Float, "IouThreshold" ) |
1649 | .addMember(MemberType::Float, "ScoreThreshold" ) |
1650 | .addMember(MemberType::Float, "XScale" ) |
1651 | .addMember(MemberType::Float, "YScale" ) |
1652 | .addMember(MemberType::Float, "HScale" ) |
1653 | .addMember(MemberType::Float, "WScale" ) |
1654 | .addMember(MemberType::Boolean, "RegularNMS" ) |
1655 | .addResultFromCtorArg("DetectionBoxes" ) |
1656 | .addResultFromCtorArg("DetectionClasses" ) |
1657 | .addResultFromCtorArg("DetectionScores" ) |
1658 | .addResultFromCtorArg("NumDetections" ) |
1659 | .setDocstring( |
1660 | "This node is a TensorFlowLite version of NonMaxSuppresion. The node " |
1661 | "has the following inputs: Boxes with size [N, B, 4], Scores with " |
1662 | "size [N, B, C] and Anchors with size [B, 4] where N is the batch " |
1663 | "size, B is the number of boxes and C is the number of classes. " |
1664 | "The node has the following attributes (parameters): " |
1665 | "NumClasses - Number of classes (without the background class). " |
1666 | "MaxDetections - The maximum number of detections. " |
1667 | "MaxClassesPerDetection - Maximum classes per detection (Fast NMS). " |
1668 | "MaxDetectionsPerClass - Maximum detections per class (Regular NMS). " |
1669 | "IouThreshold - Detection threshold for IoU metric. " |
1670 | "ScoreThreshold - Detection threshold for scores. " |
1671 | "XScale - X scale used for decoding the boxes. " |
1672 | "YScale - Y scale used for decoding the boxes. " |
1673 | "HScale - H scale used for decoding the boxes. " |
1674 | "WScale - W scale used for decoding the boxes. " |
1675 | "RegularNMS - Whether the NMS is 'Regular' or 'Fast'. " |
1676 | "The node will have the following outputs: " |
1677 | "DetectionBoxes - the chosen boxes (float). " |
1678 | "DetectionClasses - the classes of the chosen boxes (int32). " |
1679 | "DetectionScores - the scores of the chosen boxes (float). " |
1680 | "NumDetections - number of chose boxes (int32). " |
1681 | "The first three output tensors will be allocated using the maximum " |
1682 | "number of possible detections (worst case scenario) but the actual " |
1683 | "usage will be given by the 'NumDetections' output. " ); |
1684 | |
1685 | //===--------------------------------------------------------------------===// |
1686 | // Region of Interest nodes |
1687 | //===--------------------------------------------------------------------===// |
1688 | |
1689 | BB.newNode("ROIAlign" ) |
1690 | .addInput("FeatureMap" ) |
1691 | .addInput("Boxes" ) |
1692 | .addInput("BatchIndices" ) |
1693 | .addMember(MemberType::Enum, "Mode" ) |
1694 | .addMember(MemberType::Unsigned, "OutputHeight" ) |
1695 | .addMember(MemberType::Unsigned, "OutputWidth" ) |
1696 | .addMember(MemberType::Unsigned, "SamplingRatio" ) |
1697 | .addMember(MemberType::Float, "SpatialScale" ) |
1698 | .addMember(MemberType::Boolean, "Aligned" ) |
1699 | .addMember(MemberType::Boolean, "Rotated" ) |
1700 | .addResultFromCtorArg() |
1701 | .setDocstring( |
1702 | "Performs region of interest align (ROI) operator. " |
1703 | "FeatureMap - a tensor of [N,H,W,C]. N is the batch, C is the " |
1704 | "channel, H is the height, W is the width. " |
1705 | "Boxes - a tensor of [K,4] or [K,5] with format " |
1706 | "[[optinal_batch_index] x0, y0, x1, y1]. K is the number of boxes. " |
1707 | "BatchIndices - a tensor of [K,]. If N > 1 and Box shape is [K,4], " |
1708 | "BatchIndices must be valid. " |
1709 | "Output is a tensor with shape [K, OutputHeight, OutputWidth, C]. " |
1710 | "Aligned - if true, coordinates are aligned to a center of a pixel." ); |
1711 | |
1712 | BB.newNode("BBoxTransform" ) |
1713 | .addInput("Rois" ) |
1714 | .addInput("Deltas" ) |
1715 | .addInput("ImInfo" ) |
1716 | .addMember(MemberType::VectorFloat, "Weights" ) |
1717 | .addMember(MemberType::Boolean, "ApplyScale" ) |
1718 | .addMember(MemberType::Boolean, "Rotated" ) |
1719 | .addMember(MemberType::Boolean, "AngleBoundOn" ) |
1720 | .addMember(MemberType::Int64, "AngleBoundLo" ) |
1721 | .addMember(MemberType::Int64, "AngleBoundHi" ) |
1722 | .addMember(MemberType::Float, "ClipAngleThresh" ) |
1723 | .addMember(MemberType::Boolean, "LegacyPlusOne" ) |
1724 | .addResultFromCtorArg("BoxOut" ) |
1725 | .addResultFromCtorArg("RoiBatchSplits" ) |
1726 | .setDocstring( |
1727 | "Transform proposal bounding boxes to target bounding box using " |
1728 | "bounding box regression deltas. " |
1729 | "Rois tensor's format is: " |
1730 | "<[optional_batch_index], x1, y1, x2, y2>, shape (M, 4) or (M, 5) " |
1731 | "where M is the number of Rois. " |
1732 | "For rotated boxes, this would have an additional angle (in degrees) " |
1733 | "in the format <[optional_batch_id], ctr_x, ctr_y, w, h, angle> " |
1734 | "Deltas are of shape (M, K*4) with format <dx, dy, dw, dh>, " |
1735 | "where K is the number of classes. " |
1736 | "For rotated Rois: shape (M, K*5), format <dx, dy, dw, dh, da>. " |
1737 | "ImInfo is of shape <batch_size, 3> with format <img_height, " |
1738 | "img_width, img_scale>." |
1739 | "If proposals from multiple images in a batch are present, they " |
1740 | "should be grouped sequentially and in incremental order." ); |
1741 | |
1742 | BB.newNode("CollectRpnProposals" ) |
1743 | .addMember(MemberType::VectorNodeValue, "RoisIn" ) |
1744 | .addMember(MemberType::VectorNodeValue, "RoisProbsIn" ) |
1745 | .addMember(MemberType::Int64, "RpnMaxLevel" ) |
1746 | .addMember(MemberType::Int64, "RpnMinLevel" ) |
1747 | .addMember(MemberType::Unsigned, "RpnPostNmsTopN" ) |
1748 | .addResultFromCtorArg() |
1749 | .setDocstring( |
1750 | "Given RpnMinLevel, RpnMaxLevel and RpnPostNmsTopN " |
1751 | "CollectRpnProposals merges RoisIn based on " |
1752 | "RoisProbsIn and returns top proposals limited to " |
1753 | "RpnPostNmsTopN total, size (n x B), where B is " |
1754 | "box dimensions and based on dimension of input rois. " |
1755 | "Format for upright boxes is (image_index, x1, y1, x2, y2)." |
1756 | "Format for rotated boxes (image_index, ctr_x, ctr_y, w, h, angle)" |
1757 | "RpnPostNmsTopN should be greater than zero" ); |
1758 | |
1759 | //===--------------------------------------------------------------------===// |
1760 | // Lookup Table Operators |
1761 | //===--------------------------------------------------------------------===// |
1762 | |
1763 | BB.newNode("LookupTable" ) |
1764 | // Input to the function. |
1765 | .addInput("Input" ) |
1766 | // Table containing the coefficients for interpolation. |
1767 | .addInput("Table" ) |
1768 | // Table containing the index mapping to find the right entry in the main |
1769 | // table. |
1770 | .addInput("TableIdx" ) |
1771 | .addMember(MEMBER_TYPE_INFO(glow::LUTOperator), "Operator" ) |
1772 | .addMember(MemberType::VectorFloat, "OperatorArgs" ) |
1773 | .addResultFromCtorArg() |
1774 | .dataParallel() |
1775 | .setDocstring( |
1776 | "LookupTable based data-parallel operation." |
1777 | "Given an interpolation table and and index table, " |
1778 | "return interpolated approximations for arbitrary functions." ); |
1779 | |
1780 | //===--------------------------------------------------------------------===// |
1781 | // Backend-Specific Nodes |
1782 | //===--------------------------------------------------------------------===// |
1783 | |
1784 | #include "glow/NodeGenIncludes.h" |
1785 | |
1786 | return 0; |
1787 | } |
1788 | |