[exo-tflite] Update Reshape exporter (#7680)
author남궁석/On-Device Lab(SR)/Engineer/삼성전자 <sk.namkoong@samsung.com>
Mon, 23 Sep 2019 07:35:54 +0000 (16:35 +0900)
committer박종현/On-Device Lab(SR)/Staff Engineer/삼성전자 <jh1302.park@samsung.com>
Mon, 23 Sep 2019 07:35:54 +0000 (16:35 +0900)
* [exo-tflite] Update Reshape exporter

Until now, new shape is exported only by `new_shape` attribute.
However, runtime was receiving new shape by input.
This commit will update `Reshape` exporter to export new shape
not only as attribute but also as input.

Signed-off-by: Seok NamKoong <sk.namkoong@samsung.com>
* add comments

compiler/exo-tflite/src/OperationExporter.cpp

index 89bc9d0..1095884 100644 (file)
@@ -592,9 +592,36 @@ void OperationExporter::visit(loco::FilterEncode *node)
 void exportAsReshape(loco::Node *node, FlatBufferBuilder &builder,
                      std::vector<int32_t> &new_shape_vec, SerializedModelData &gd)
 {
+  // NOTE TFLite has two ways to get new shape paramter,
+  //      one is by attribute 'new_shape' and the other is by input 'shape'.
+  //      Therefore TFLite interpreter calculates Reshape operation correctly
+  //      if one of them is valid.
+  //      However, since NN runtime usually get new shape parameter by input 'shape',
+  //      passing new shape only by attribute can cause some problems.
+  //      Of course, the opposite situation can be occurred in the future.
+  //      To prevent those problems, we pass new shape parameter not only by attribute
+  //      but also by input.
+
+  auto input_shape_shape_vec_offset =
+      builder.CreateVector(std::vector<int32_t>{(int32_t)new_shape_vec.size()});
+
+  size_t input_shape_vec_size = new_shape_vec.size() * sizeof(int32_t);
+  auto input_shape_input_vec_offset =
+      builder.CreateVector(reinterpret_cast<uint8_t *>(new_shape_vec.data()), input_shape_vec_size);
+  auto input_shape_buffer_offset = CreateBuffer(builder, input_shape_input_vec_offset);
+
+  const auto input_shape_buffer_id = static_cast<uint32_t>(gd._buffers.size());
+  gd._buffers.push_back(input_shape_buffer_offset);
+
+  auto input_shape_tensor_id = static_cast<int32_t>(gd._tensors.size());
+  auto name_offset = builder.CreateString("t_" + std::to_string(input_shape_tensor_id));
+  auto input_shape_tensor_offset = CreateTensor(
+      builder, input_shape_shape_vec_offset, TensorType_INT32, input_shape_buffer_id, name_offset);
+  gd._tensors.push_back(input_shape_tensor_offset);
+
   uint32_t op_idx = gd.registerBuiltinOpcode(tflite::BuiltinOperator_RESHAPE);
 
-  std::vector<int32_t> inputs_vec{get_tensor_index(node->arg(0))};
+  std::vector<int32_t> inputs_vec{get_tensor_index(node->arg(0)), input_shape_tensor_id};
   std::vector<int32_t> outputs_vec{get_tensor_index(static_cast<loco::Node *>(node))};
   auto inputs = builder.CreateVector(inputs_vec);
   auto outputs = builder.CreateVector(outputs_vec);