2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "OperationDumper.h"
21 #include "util/logging.h"
28 using namespace operation;
32 void dumpUnaryInputOp(const Operation &node, const std::string &adding_input = "")
34 VERBOSE(LIR) << "* " << node.name() << std::endl;
35 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(0) << ") " << adding_input
37 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
40 void dumpBinaryInputOp(const Operation &node, const std::string &adding_input = "")
42 VERBOSE(LIR) << "* " << node.name() << std::endl;
43 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(0) << ", " << node.getInputs().at(1)
44 << ") " << adding_input << std::endl;
45 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
48 void dumpConvOp(const Operation &node, const std::string &padding_type)
50 VERBOSE(LIR) << "* " << node.name() << "(" << padding_type << ")" << std::endl;
51 VERBOSE(LIR) << " - Inputs : IFM(" << node.getInputs().at(Conv2D::Input::INPUT) << ") Kernel("
52 << node.getInputs().at(Conv2D::Input::KERNEL) << ") Bias("
53 << node.getInputs().at(Conv2D::Input::BIAS) << ")" << std::endl;
54 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
57 void dumpPackingOp(const Operation &node)
59 VERBOSE(LIR) << "* " << node.name() << std::endl;
61 for (auto i : node.getInputs())
63 inputs += std::to_string(i.value()) + ",";
65 VERBOSE(LIR) << " - Inputs : Inputs(" << inputs << ")" << std::endl;
66 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
70 OperationDumper::OperationDumper(const std::string &start_msg)
72 VERBOSE(LIR) << start_msg << std::endl;
75 void OperationDumper::visit(const ArgMinMax &node)
77 std::string min_max = node.param().is_arg_max ? "(Max)" : "(Min)";
78 VERBOSE(LIR) << "* " << node.name() << min_max << std::endl;
79 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(ArgMinMax::INPUT) << ") Axis("
80 << node.getInputs().at(ArgMinMax::AXIS) << ") " << std::endl;
81 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
84 void OperationDumper::visit(const BatchToSpaceND &node)
86 std::string block_size =
88 std::to_string(node.getInputs().at(BatchToSpaceND::Input::BLOCK_SIZE).value()) + ")";
89 dumpUnaryInputOp(node, block_size);
92 void OperationDumper::visit(const BCQFullyConnected &node)
94 VERBOSE(LIR) << "* " << node.name() << std::endl;
95 VERBOSE(LIR) << " - Inputs : IFM(" << node.getInputs().at(BCQFullyConnected::Input::INPUT)
97 << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_BINARY)
99 << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_SCALES)
100 << ") WeightsClusters("
101 << node.getInputs().at(BCQFullyConnected::Input::WEIGHTS_CLUSTERS) << ") Bias("
102 << node.getInputs().at(BCQFullyConnected::Input::BIAS) << ")" << std::endl;
103 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
106 void OperationDumper::visit(const BinaryArithmetic &node) { dumpBinaryInputOp(node); }
108 void OperationDumper::visit(const operation::BroadcastTo &node) { dumpBinaryInputOp(node); }
110 void OperationDumper::visit(const Comparison &node) { dumpBinaryInputOp(node); }
112 void OperationDumper::visit(const Concat &node) { dumpPackingOp(node); }
114 void OperationDumper::visit(const Conv2D &node)
116 std::string padding_type =
117 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
118 dumpConvOp(node, padding_type);
121 void OperationDumper::visit(const ConvertFp16ToFp32 &node) { dumpUnaryInputOp(node); }
123 void OperationDumper::visit(const ConvertFp32ToFp16 &node) { dumpUnaryInputOp(node); }
125 void OperationDumper::visit(const DepthToSpace &node) { dumpUnaryInputOp(node); }
127 void OperationDumper::visit(const DepthwiseConv2D &node)
129 std::string padding_type =
130 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
131 dumpConvOp(node, padding_type);
134 void OperationDumper::visit(const ElementwiseActivation &node)
137 if (node.param().op_type == ElementwiseActivation::Type::RELU)
139 params = " lower value(" + std::to_string(node.param().alpha) + ") upper value(" +
140 std::to_string(node.param().beta) + ")";
142 else if (node.param().op_type == ElementwiseActivation::Type::LEAKY_RELU)
144 params = " alpha value(" + std::to_string(node.param().alpha) + ")";
146 dumpUnaryInputOp(node, params);
149 void OperationDumper::visit(const ElementwiseBinary &node) { dumpBinaryInputOp(node); }
151 void OperationDumper::visit(const ElementwiseUnary &node) { dumpUnaryInputOp(node); }
153 void OperationDumper::visit(const EmbeddingLookup &node)
155 VERBOSE(LIR) << "* " << node.name() << std::endl;
156 VERBOSE(LIR) << " - Inputs : Lookups(" << node.getInputs().at(EmbeddingLookup::Input::LOOKUPS)
157 << ") VALUES(" << node.getInputs().at(EmbeddingLookup::Input::VALUES) << ")"
159 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
162 void OperationDumper::visit(const ExpandDims &node)
165 "AXIS(" + std::to_string(node.getInputs().at(ExpandDims::Input::AXIS).value()) + ")";
166 dumpUnaryInputOp(node, axis);
169 void OperationDumper::visit(const Fill &node)
171 VERBOSE(LIR) << "* " << node.name() << std::endl;
172 VERBOSE(LIR) << " - Inputs : Shape(" << node.getInputs().at(Fill::Input::SHAPE) << ") Value("
173 << node.getInputs().at(Fill::Input::VALUE) << ")" << std::endl;
174 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
177 void OperationDumper::visit(const FullyConnected &node)
180 "Weight(" + std::to_string(node.getInputs().at(FullyConnected::Input::WEIGHT).value()) +
181 ") Bias(" + std::to_string(node.getInputs().at(FullyConnected::Input::BIAS).value()) + ")";
182 dumpUnaryInputOp(node, inputs);
185 void OperationDumper::visit(const Gather &node)
187 std::string indices =
188 "Indices(" + std::to_string(node.getInputs().at(Gather::Input::INDICES).value()) + ")";
189 dumpUnaryInputOp(node, indices);
192 void OperationDumper::visit(const HashtableLookup &node)
194 VERBOSE(LIR) << "* HashTableLookup" << std::endl;
195 VERBOSE(LIR) << " - Inputs : Lookups(" << node.getInputs().at(HashtableLookup::Input::LOOKUPS)
196 << ") Keys(" << node.getInputs().at(HashtableLookup::Input::KEYS) << ") Values("
197 << node.getInputs().at(HashtableLookup::Input::VALUES) << ")" << std::endl;
198 VERBOSE(LIR) << " - Outputs : Output(" << node.getInputs().at(HashtableLookup::Output::OUTPUT)
199 << ") Hits(" << node.getInputs().at(HashtableLookup::Output::HITS) << ")"
203 void OperationDumper::visit(const InstanceNorm &node)
206 "Gamma(" + std::to_string(node.getInputs().at(InstanceNorm::Input::GAMMA).value()) +
207 ") Beta(" + std::to_string(node.getInputs().at(InstanceNorm::Input::BETA).value()) + ")";
208 dumpUnaryInputOp(node, inputs);
211 void OperationDumper::visit(const L2Normalization &node) { dumpUnaryInputOp(node); }
213 void OperationDumper::visit(const LocalResponseNormalization &node) { dumpUnaryInputOp(node); }
215 void OperationDumper::visit(const LSTM &node)
217 VERBOSE(LIR) << "* " << node.name() << std::endl;
219 << " - Inputs : Input(" << node.getInputs().at(LSTM::Input::INPUT)
220 << ") Input To Input Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_INPUT_WEIGHTS)
221 << ") Input To Forget Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_FORGET_WEIGHTS)
222 << ") Input To Cell Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_CELL_WEIGHTS)
223 << ") Input To Output Weights(" << node.getInputs().at(LSTM::Input::INPUT_TO_OUTPUT_WEIGHTS)
224 << ") Recurrent To Input Weights("
225 << node.getInputs().at(LSTM::Input::RECURRENT_TO_INPUT_WEIGHTS)
226 << ") Recurrent To Forget Weights("
227 << node.getInputs().at(LSTM::Input::RECURRENT_TO_FORGET_WEIGHTS)
228 << ") Recurrent To Cell Weights("
229 << node.getInputs().at(LSTM::Input::RECURRENT_TO_CELL_WEIGHTS)
230 << ") Recurrent To Output Weights("
231 << node.getInputs().at(LSTM::Input::RECURRENT_TO_OUTPUT_WEIGHTS) << ") Cell To Input Weights("
232 << node.getInputs().at(LSTM::Input::CELL_TO_INPUT_WEIGHTS) << ") Cell To Forget Weights("
233 << node.getInputs().at(LSTM::Input::CELL_TO_FORGET_WEIGHTS) << ") Cell To OUTPUT Weights("
234 << node.getInputs().at(LSTM::Input::CELL_TO_OUTPUT_WEIGHTS) << ") Input Gate Bias("
235 << node.getInputs().at(LSTM::Input::INPUT_GATE_BIAS) << ") Forget Gate Bias("
236 << node.getInputs().at(LSTM::Input::FORGET_GATE_BIAS) << ") Cell Bias("
237 << node.getInputs().at(LSTM::Input::CELL_BIAS) << ") Output Gate Bias("
238 << node.getInputs().at(LSTM::Input::OUTPUT_GATE_BIAS) << ") Projection Weights("
239 << node.getInputs().at(LSTM::Input::PROJECTION_WEIGHTS) << ") Projection Bias("
240 << node.getInputs().at(LSTM::Input::PROJECTION_BIAS) << ") Output State In("
241 << node.getInputs().at(LSTM::Input::OUTPUT_STATE_IN) << ") Cell State In("
242 << node.getInputs().at(LSTM::Input::CELL_STATE_IN);
243 if (node.getInputs().size() == 24)
245 VERBOSE(LIR) << ") Input Layer Normalization Weights("
246 << node.getInputs().at(LSTM::Input::INPUT_LAYER_NORMALIZATION_WEIGHTS)
247 << ") Forget Layer Normalization Weights("
248 << node.getInputs().at(LSTM::Input::FORGET_LAYER_NORMALIZATION_WEIGHTS)
249 << ") Cell Layer Normalization Weights("
250 << node.getInputs().at(LSTM::Input::CELL_LAYER_NORMALIZATION_WEIGHTS)
251 << ") Ouput Layer Normalization Weights("
252 << node.getInputs().at(LSTM::Input::OUTPUT_LAYER_NORMALIZATION_WEIGHTS);
254 VERBOSE(LIR) << ")" << std::endl;
255 VERBOSE(LIR) << " - Output : Scratch Buffer("
256 << node.getOutputs().at(LSTM::Output::SCRATCH_BUFFER) << ") Output State Out("
257 << node.getOutputs().at(LSTM::Output::OUTPUT_STATE_OUT) << ") Cell State Out("
258 << node.getOutputs().at(LSTM::Output::CELL_STATE_OUT) << ") Output("
259 << node.getOutputs().at(LSTM::Output::OUTPUT) << ")" << std::endl;
262 void OperationDumper::visit(const Pack &node) { dumpPackingOp(node); }
264 void OperationDumper::visit(const Pad &node)
266 std::string pad = "Pad(" + std::to_string(node.getInputs().at(Pad::Input::PAD).value()) + ")";
267 dumpUnaryInputOp(node, pad);
270 void OperationDumper::visit(const Permute &node)
272 std::string permute_type = "Unknown";
273 switch (node.getPermuteType())
275 case Permute::Type::COPY:
276 permute_type = "Copy";
278 case Permute::Type::NHWC_TO_NCHW:
279 permute_type = "NHWC to NCHW";
281 case Permute::Type::NCHW_TO_NHWC:
282 permute_type = "NCHW to NHWC";
286 VERBOSE(LIR) << "* Permute(" + permute_type + ")" << std::endl;
287 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(0) << ")" << std::endl;
288 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
291 void OperationDumper::visit(const Pool2D &node)
293 std::string padding_type =
294 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
295 VERBOSE(LIR) << "* " << node.name() << "(" << padding_type << ")" << std::endl;
296 VERBOSE(LIR) << " - Inputs : IFM(" << node.getInputs().at(Pool2D::Input::INPUT) << ")"
298 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
301 void OperationDumper::visit(const Pow &node) { dumpBinaryInputOp(node); }
303 void OperationDumper::visit(const PReLU &node)
306 "Alpha(" + std::to_string(node.getInputs().at(PReLU::Input::ALPHA).value()) + ")";
307 dumpUnaryInputOp(node, alpha);
310 void OperationDumper::visit(const Rank &node) { dumpUnaryInputOp(node); }
312 void OperationDumper::visit(const Reduce &node) { dumpUnaryInputOp(node); }
314 void OperationDumper::visit(const Reshape &node)
318 node.getInputs().size() == 2
319 ? "Shape(" + std::to_string(node.getInputs().at(Reshape::Input::SHAPE).value()) + ")"
320 : "Shape(not provided)";
321 dumpUnaryInputOp(node, shape);
324 void OperationDumper::visit(const ResizeBilinear &node)
326 if (node.getInputs().size() == 1)
328 dumpUnaryInputOp(node);
330 else if (node.getInputs().size() == 2)
332 dumpBinaryInputOp(node);
336 VERBOSE(LIR) << "* " << node.name() << " is set wrong" << std::endl;
340 void OperationDumper::visit(const ResizeNearestNeighbor &node)
342 if (node.getInputs().size() == 1)
344 dumpUnaryInputOp(node);
346 else if (node.getInputs().size() == 2)
348 dumpBinaryInputOp(node);
352 VERBOSE(LIR) << "* " << node.name() << " is set wrong" << std::endl;
356 void OperationDumper::visit(const Reverse &node)
359 "Axis(" + std::to_string(node.getInputs().at(Reverse::Input::AXIS).value()) + ")";
360 dumpUnaryInputOp(node, axis);
363 void OperationDumper::visit(const RNN &node)
365 VERBOSE(LIR) << "* RNN" << std::endl;
366 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(RNN::Input::INPUT) << ") Weights("
367 << node.getInputs().at(RNN::Input::WEIGHTS) << ") Recurrent Weights("
368 << node.getInputs().at(RNN::Input::RECURRENT_WEIGHTS) << ") Bias("
369 << node.getInputs().at(RNN::Input::BIAS) << ") Hidden State("
370 << node.getInputs().at(RNN::Input::HIDDEN_STATE_IN) << ")" << std::endl;
371 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(RNN::Output::OUTPUT)
372 << ") Hidden State(" << node.getInputs().at(RNN::Output::HIDDEN_STATE_OUT) << ")"
376 void OperationDumper::visit(const Range &node)
378 VERBOSE(LIR) << "* Range" << std::endl;
379 VERBOSE(LIR) << " - Inputs : Start(" << node.getInputs().at(Range::Input::START) << ")"
380 << " Limit(" << node.getInputs().at(Range::Input::LIMIT) << ")"
381 << " Delta(" << node.getInputs().at(Range::Input::DELTA) << ")" << std::endl;
382 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
385 void OperationDumper::visit(const Select &node)
387 VERBOSE(LIR) << "* Select" << std::endl;
388 VERBOSE(LIR) << " - Inputs : Condition(" << node.getInputs().at(Select::Input::CONDITION) << ")"
389 << " Input_X(" << node.getInputs().at(Select::Input::INPUT_TRUE) << ")"
390 << " Input_Y(" << node.getInputs().at(Select::Input::INPUT_FALSE) << ")"
392 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
395 void OperationDumper::visit(const ir::operation::Shape &node) { dumpUnaryInputOp(node); }
397 void OperationDumper::visit(const Softmax &node) { dumpUnaryInputOp(node); }
399 void OperationDumper::visit(const SpaceToBatchND &node)
403 std::to_string(node.getInputs().at(SpaceToBatchND::Input::BLOCK_SIZE).value()) +
404 ") Paddings(" + std::to_string(node.getInputs().at(SpaceToBatchND::Input::PADDINGS).value()) +
406 dumpUnaryInputOp(node, inputs);
409 void OperationDumper::visit(const SpaceToDepth &node) { dumpUnaryInputOp(node); }
411 void OperationDumper::visit(const Split &node) { dumpBinaryInputOp(node); }
413 void OperationDumper::visit(const SquaredDifference &node) { dumpBinaryInputOp(node); }
415 void OperationDumper::visit(const StatelessRandomUniform &node)
417 VERBOSE(LIR) << "* StatelessRandomUniform" << std::endl;
418 VERBOSE(LIR) << " - Inputs : Shape(" << node.getInputs().at(StatelessRandomUniform::Input::SHAPE)
419 << " Seed(" << node.getInputs().at(StatelessRandomUniform::Input::SEED) << ")"
421 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
424 void OperationDumper::visit(const Squeeze &node) { dumpUnaryInputOp(node); }
426 void OperationDumper::visit(const Slice &node) { dumpUnaryInputOp(node); }
428 void OperationDumper::visit(const StridedSlice &node) { dumpUnaryInputOp(node); }
430 void OperationDumper::visit(const Tile &node)
432 std::string multiples =
433 "Multiples(" + std::to_string(node.getInputs().at(Tile::Input::MULTIPLES).value()) + ")";
434 dumpUnaryInputOp(node, multiples);
437 void OperationDumper::visit(const TopKV2 &node)
439 VERBOSE(LIR) << "* TopKV2" << std::endl;
440 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(TopKV2::Input::INPUT) << ")"
442 VERBOSE(LIR) << " - Outputs : Values(" << node.getOutputs().at(TopKV2::Output::OUTPUT_VALUES)
443 << ") Indices(" << node.getOutputs().at(TopKV2::Output::OUTPUT_INDICES) << ")"
447 void OperationDumper::visit(const TransposeConv &node)
449 std::string padding_type =
450 node.param().padding.type == PaddingType::EXPLICIT ? "Explicit" : "Implicit";
451 VERBOSE(LIR) << "* TransposeConv(" << padding_type << ")" << std::endl;
452 VERBOSE(LIR) << " - Inputs : Output Shape("
453 << node.getInputs().at(TransposeConv::Input::OUTPUT_SHAPE) << ") KERNEL("
454 << node.getInputs().at(TransposeConv::Input::KERNEL) << ") IFM("
455 << node.getInputs().at(TransposeConv::Input::INPUT) << ")" << std::endl;
456 VERBOSE(LIR) << " - Output : OFM(" << node.getOutputs().at(0) << ")" << std::endl;
459 void OperationDumper::visit(const Transpose &node) { dumpBinaryInputOp(node); }
461 void OperationDumper::visit(const Unpack &node)
463 VERBOSE(LIR) << "* " << node.name() << std::endl;
464 VERBOSE(LIR) << " - Inputs : Input(" << node.getInputs().at(Unpack::Input::INPUT) << ")"
467 const auto &output_indices = node.getOutputs();
468 for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
470 outputs += std::to_string(it->value());
471 if (std::next(it) != std::end(output_indices))
474 VERBOSE(LIR) << " - Outputs : Outputs(" << outputs << ")" << std::endl;
477 void OperationDumper::visit(const OneHot &node)
479 VERBOSE(LIR) << "* " << node.name() << std::endl;
480 VERBOSE(LIR) << " - Inputs : "
481 << "Indices(" << node.getInputs().at(OneHot::Input::INDICES) << ") " << std::endl;
482 VERBOSE(LIR) << " - Output : Output(" << node.getOutputs().at(0) << ")" << std::endl;
485 void OperationDumper::visit(const If &node)
487 VERBOSE(LIR) << "* " << node.name() << std::endl;
489 const auto &input_indices = node.getInputs();
490 for (auto it = std::begin(input_indices); it != std::end(input_indices); ++it)
492 inputs += std::to_string(it->value());
493 if (std::next(it) != std::end(input_indices))
496 VERBOSE(LIR) << " - Inputs : "
497 << "Then subgraph (" << node.param().then_subg_index << ") Else subgraph ("
498 << node.param().else_subg_index << ") Inputs(" << inputs << ")" << std::endl;
500 const auto &output_indices = node.getOutputs();
501 for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
503 outputs += std::to_string(it->value());
504 if (std::next(it) != std::end(output_indices))
507 VERBOSE(LIR) << " - Output : Outputs(" << outputs << ")" << std::endl;
510 void OperationDumper::visit(const While &node)
512 VERBOSE(LIR) << "* " << node.name() << std::endl;
514 const auto &input_indices = node.getInputs();
515 for (auto it = std::begin(input_indices); it != std::end(input_indices); ++it)
517 inputs += std::to_string(it->value());
518 if (std::next(it) != std::end(input_indices))
521 VERBOSE(LIR) << " - Inputs : "
522 << "Cond subgraph (" << node.param().cond_subg_index << ") Body subgraph ("
523 << node.param().body_subg_index << ") Inputs(" << inputs << ")" << std::endl;
525 const auto &output_indices = node.getOutputs();
526 for (auto it = std::begin(output_indices); it != std::end(output_indices); ++it)
528 outputs += std::to_string(it->value());
529 if (std::next(it) != std::end(output_indices))
532 VERBOSE(LIR) << " - Output : Outputs(" << outputs << ")" << std::endl;