[nnc] Remove shared_ptr from TensorVariant's constructor (#2907)
authorСергей Баранников/AI Tools Lab /SRR/Engineer/삼성전자 <s.barannikov@samsung.com>
Wed, 23 Jan 2019 11:41:09 +0000 (14:41 +0300)
committerEfimov Alexander/AI Tools Lab/./Samsung Electronics <a.efimov@samsung.com>
Wed, 23 Jan 2019 11:41:09 +0000 (14:41 +0300)
* Change the signatures of TensorVariant consturctors to accept a plain pointer to data instead of shared_ptr.
* Refactor uses of the constructors.

Signed-off-by: Sergei Barannikov <s.barannikov@samsung.com>
19 files changed:
contrib/nnc/core/modelIR/Deserializer.cpp
contrib/nnc/core/modelIR/TensorVariant.cpp
contrib/nnc/include/core/modelIR/DataType.h
contrib/nnc/include/core/modelIR/TensorUtil.h
contrib/nnc/include/core/modelIR/TensorVariant.h
contrib/nnc/include/core/modelIR/operations/ConstantOp.h
contrib/nnc/passes/caffe2_frontend/caffe2_importer.cpp
contrib/nnc/passes/caffe_frontend/caffe_op_creator.cpp
contrib/nnc/passes/common_frontend/op_creator_helper.cpp
contrib/nnc/passes/interpreter/interpreter_pass.cpp
contrib/nnc/passes/interpreter/ops/OperationImpl.h
contrib/nnc/passes/onnx_frontend/ONNXImporterImpl.cpp
contrib/nnc/passes/onnx_frontend/ONNXOpCreator.cpp
contrib/nnc/passes/tflite_frontend/tflite_importer.cpp
contrib/nnc/tests/interpreter/op_info_util.cpp
contrib/nnc/unittests/acl_backend/MIRToDOM.cpp
contrib/nnc/unittests/core/TensorVariant.cpp
contrib/nnc/unittests/core/serializer.cpp
contrib/nnc/unittests/soft_backend/CPPOperations.cpp

index 12e96ac..5fd0e96 100644 (file)
@@ -61,40 +61,25 @@ Shape Deserializer<Shape>::deserializeFromString (const std::string& bytes)
 // Tensor Deserialization
 //
 
-static TensorVariant deserializeFromMessage(const proto::TensorProto& object_as_message)
-{
-  Shape shape = deserializeFromMessage(object_as_message.shape());
-
-  proto::DataType dt = object_as_message.dtype();
+static TensorVariant deserializeFromMessage(const proto::TensorProto& object_as_message) {
+  DTYPE dtype;
+  switch (object_as_message.dtype()) {
+    case proto::DataType::DT_INT32:
+      dtype = DTYPE::INT32;
+      break;
+    case proto::DataType::DT_FLOAT:
+      dtype = DTYPE::FLOAT32;
+      break;
+    case proto::DataType::DT_DOUBLE:
+      dtype = DTYPE::FLOAT64;
+      break;
+    default:
+      throw std::logic_error("Deserializer<TensorVariant>: received unsupported data type");
+  }
 
   const std::string& tensor_content = object_as_message.tensor_content();
-  size_t raw_data_size = tensor_content.size();
-  auto raw_data = new char[raw_data_size];
-  tensor_content.copy(raw_data, raw_data_size);
-
-  DTYPE tv_dtype;
-  size_t element_size;
-
-  switch (dt)
-  {
-  case proto::DataType::DT_INT32:
-    element_size = sizeof(int32_t);
-    tv_dtype = DTYPE::INT32;
-    break;
-  case proto::DataType::DT_FLOAT:
-    element_size = sizeof(float);
-    tv_dtype = DTYPE::FLOAT32;
-    break;
-  case proto::DataType::DT_DOUBLE :
-    element_size = sizeof(double);
-    tv_dtype = DTYPE::FLOAT32;
-    break;
-  default:
-    throw std::logic_error("Deserializer<TensorVariant>: received unsupported data type");
-  }
-  assert(raw_data_size / element_size == static_cast<size_t>(shape.numElements()));
-  std::shared_ptr<char> data(raw_data, std::default_delete<char[]>());
-  return TensorVariant(shape, data, tv_dtype, element_size);
+  Shape shape = deserializeFromMessage(object_as_message.shape());
+  return TensorVariant(dtype, shape, tensor_content.data());
 }
 
 template <>
index 94c9c18..f0dbb53 100644 (file)
  */
 
 #include "core/modelIR/TensorVariant.h"
+#include <cstring>
 
 namespace nnc
 {
 namespace mir
 {
 
-TensorVariant::TensorVariant(const Shape& shape, const std::shared_ptr<char>& data,
-                             DTYPE dtype, size_t element_size) :
-  _dtype(dtype), _data(data), _strides{0}, _rank(shape.rank()),
-  _shape(shape), _elementSize(element_size)
-{
+TensorVariant::TensorVariant(DTYPE dtype, const Shape& shape)
+    : _dtype(dtype), _strides{0}, _rank(shape.rank()), _shape(shape) {
+  switch (dtype) {
+    case DTYPE::FLOAT32:
+      _elementSize = sizeof(float);
+      break;
+    case DTYPE::FLOAT64:
+      _elementSize = sizeof(double);
+      break;
+    case DTYPE::INT32:
+      _elementSize = sizeof(int32_t);
+      break;
+    case DTYPE::INT64:
+      _elementSize = sizeof(int64_t);
+      break;
+    default:
+      assert(false);
+  }
+  std::size_t data_size = _shape.numElements() * _elementSize;
+  _data.reset(new char[data_size], std::default_delete<char[]>());
+
   int stride = 1;
   for (int d = _rank - 1; d >= 0; --d)
   {
@@ -34,6 +51,12 @@ TensorVariant::TensorVariant(const Shape& shape, const std::shared_ptr<char>& da
   }
 }
 
+TensorVariant::TensorVariant(DTYPE dtype, const Shape& shape, const void* data)
+    : TensorVariant(dtype, shape) {
+  std::size_t data_size = _shape.numElements() * _elementSize;
+  std::memcpy(_data.get(), data, data_size);
+}
+
 /**
  * @brief Construct a TensorVariant from t_old that has strides with 0 where dim = 1
  * Used for broadcasting
index d7c79c4..3d4358f 100644 (file)
@@ -23,6 +23,7 @@ namespace mir {
 enum class DTYPE {
   UNKNOWN,
   FLOAT32,
+  FLOAT64,
   INT32,
   INT64
 };
index 7a1a5fb..0239c7a 100644 (file)
@@ -41,10 +41,8 @@ TensorVariant transposeTensor(const TensorVariant& tensor) {
 
   auto elem_type = tensor.getDataType();
   auto elem_size = tensor.getElementSize();
-  auto num_elems = shape.numElements();
 
-  std::shared_ptr<char> data(new char[num_elems * elem_size], std::default_delete<char[]>());
-  TensorVariant transposed_tensor(transposed_shape, data, elem_type, elem_size);
+  TensorVariant transposed_tensor(elem_type, transposed_shape);
 
   for (const auto& index : ShapeRange(shape)) {
     Index transposed_index{index.at(Ints)...};
index 0ccd826..8544c1f 100644 (file)
@@ -34,20 +34,12 @@ constexpr int MAX_DIMENSIONS = 32;
 
 class TensorVariant {
 public:
+  TensorVariant(DTYPE dtype, const Shape& shape);
 
-  explicit TensorVariant(const Shape& shape, const std::shared_ptr<char>& data, DTYPE dtype, size_t element_size);
+  TensorVariant(DTYPE dtype, const Shape& shape, const void *data);
 
-  explicit TensorVariant(const TensorVariant& t_old, const Shape& shape);
+  TensorVariant(const TensorVariant& t_old, const Shape& shape);
 
-  template<typename T>
-  explicit TensorVariant(const Shape& shape, const std::shared_ptr<T>& data, DTYPE dtype) :
-    TensorVariant(
-        shape,
-        std::shared_ptr<char>(data, (char*)data.get()),
-        dtype,
-        sizeof(typename std::remove_extent<T>::type))
-  {
-  }
   virtual ~TensorVariant() = default;
 
   char* at(const Index& idx) const;
index 075ccad..727325b 100644 (file)
@@ -25,7 +25,7 @@ namespace ops {
 
 class ConstantOp : public Operation {
 public:
-  ConstantOp(const TensorVariant& value) : Operation(Type::constant, {}), _value(value) {
+  explicit ConstantOp(const TensorVariant& value) : Operation(Type::constant, {}), _value(value) {
     setOutputShape(0, _value.getShape());
   }
 
index e1fc5f2..c606fd1 100644 (file)
@@ -31,6 +31,7 @@
 #include <fstream>
 #include <sstream>
 #include <cassert>
+#include <cstring>
 
 namespace nnc {
 
@@ -234,39 +235,27 @@ mir::TensorVariant Caffe2Importer::createTensor(const OperatorDef& op) {
   const auto& shape = findArgumentByName(op.arg(), "shape");
   const auto& values = findArgumentByName(op.arg(), "values");
 
-  // Create untyped tensor. Note, tensor contents will be *copied* here.
-  mir::DTYPE element_type(mir::DTYPE::UNKNOWN);
-  const auto opType(_operatorTypes.at(op.type()));
-  size_t element_size = 0;
-  size_t data_size = 0;
-  char* data_ptr = nullptr;
+  mir::DTYPE element_type;
+  const SupportedCaffe2OpType op_type = _operatorTypes.at(op.type());
+  const void* src_data;
   // if values on floats
   if (values.floats().size() > 0) {
     element_type = mir::DTYPE::FLOAT32;
-    element_size = sizeof(float);
-    data_size = values.floats().size() * element_size;
-    data_ptr = new char[data_size];
-    memcpy(data_ptr, values.floats().data(), data_size);
-  }
-  // if values on ints
-  if (values.ints().size() > 0) {
-    if (opType == SupportedCaffe2OpType::givenTensorInt64Fill) {
-      element_size = sizeof(int64_t);
+    src_data = values.floats().data();
+  } else {
+    assert(values.ints().size() > 0);
+    if (op_type == SupportedCaffe2OpType::givenTensorInt64Fill) {
       element_type = mir::DTYPE::INT64;
     } else {
-      element_size = sizeof(int32_t);
       element_type = mir::DTYPE::INT32;
     }
-
-    data_size = values.ints().size() * element_size;
-    data_ptr = new char[data_size];
-    memcpy(data_ptr, values.ints().data(), data_size);
+    src_data = values.ints().data();
   }
-  std::shared_ptr<char> data(data_ptr, std::default_delete<char[]>());
+
   Shape tensor_shape = ShapeHelper::createShape(
       shape.ints(), static_cast<size_t>(shape.ints().size()));
 
-  return mir::TensorVariant(tensor_shape, data, element_type, element_size);
+  return mir::TensorVariant(element_type, tensor_shape, src_data);
 }
 
 std::vector<mir::IODescriptor> Caffe2Importer::getInputMIROps(const OperatorDef& op) {
index d8323ea..561261a 100644 (file)
@@ -133,28 +133,23 @@ CaffeOpCreator::createFullyConnected(const mir::IODescriptor& input,
 }
 
 TensorVariant CaffeOpCreator::convertBlob(const BlobProto& blob) {
-  size_t element_size;
-  const char* src_data;
-  size_t buffer_size;
+  const void* src_data;
 
+  DTYPE dtype;
   if (blob.data_size() != 0) {
     assert(blob.double_data_size() == 0);
-    element_size = sizeof(float);
-    buffer_size = blob.data_size() * element_size;
-    src_data = reinterpret_cast<const char*>(blob.data().data());
+    dtype = DTYPE::FLOAT32;
+    src_data = blob.data().data();
   } else if (blob.double_data_size() != 0) {
-    element_size = sizeof(double);
-    buffer_size = blob.double_data_size() * element_size;
-    src_data = reinterpret_cast<const char*>(blob.double_data().data());
+    dtype = DTYPE::FLOAT64;
+    src_data = blob.double_data().data();
   } else {
     throw PassException("No data in Caffe BlobProto, investigate");
   }
 
   Shape shape = ShapeHelper::createShape(blob.shape().dim(),
                                          static_cast<size_t>(blob.shape().dim_size()));
-  std::shared_ptr<char> data(new char[buffer_size], std::default_delete<char[]>());
-  std::memcpy(data.get(), src_data, buffer_size);
-  return TensorVariant(shape, data, DTYPE::FLOAT32, element_size);
+  return TensorVariant(dtype, shape, src_data);
 }
 
 std::vector<mir::IODescriptor>
@@ -622,11 +617,7 @@ CaffeOpCreator::convertEltwise(const caffe::LayerParameter& layer,
         assert(opts.coeff().size() == inputs.size());
         for (int i = 0; i < opts.coeff().size(); i++) {
           if (opts.coeff().Get(i) != 1.0f) {
-            auto coeff = new char[sizeof(float)];
-            memcpy(coeff, &opts.coeff().Get(i), sizeof(float));
-            auto coeff_tensor = TensorVariant(Shape{1},
-              std::shared_ptr<char>(reinterpret_cast<char*>(coeff), std::default_delete<char[]>()),
-              DTYPE::FLOAT32, sizeof(float));
+            TensorVariant coeff_tensor(DTYPE::FLOAT32, Shape{1}, &opts.coeff().Get(i));
             auto coeff_const = createOp<ops::ConstantOp>(layer.name() + "_const", coeff_tensor);
             std::vector<mir::IODescriptor> mul_inputs;
             mul_inputs.push_back(coeff_const->getOutput(0));
@@ -669,13 +660,10 @@ void CaffeOpCreator::checkLSTM(const caffe::LayerParameter& layer,
 }
 
 static TensorVariant createZeroedTensor(const mir::Shape& shape) {
-  // For now it is hardcoded float32.
+  // TODO For now it is hardcoded float32.
   auto elem_type = mir::DTYPE::FLOAT32;
-  auto elem_size = sizeof(float);
-  auto num_elems = static_cast<std::size_t>(shape.numElements());
-  std::shared_ptr<char> data(new char[num_elems * elem_size], std::default_delete<char[]>());
-  std::memset(data.get(), 0, num_elems * elem_size);
-  return TensorVariant(shape, data, elem_type, elem_size);
+  std::vector<float> zeros(static_cast<std::size_t>(shape.numElements()), 0.0f);
+  return TensorVariant(elem_type, shape, zeros.data());
 }
 
 /* See the following links for details on implementation:
index a07a5d6..85477b5 100644 (file)
@@ -41,10 +41,8 @@ fixGroupedKernel(int groups, const TensorVariant& folded_kernel) {
   // here creates unfolded kernel with shape [H, W, inputChannels, outputChannels]
   Shape unfold_kernel_shape(kernel_shape);
   unfold_kernel_shape.dim(kernel_in_chan_num) = in_channels;
-  auto buffer_size = unfold_kernel_shape.numElements() * folded_kernel.getElementSize();
-  std::shared_ptr<char> buffer(new char[buffer_size], std::default_delete<char[]>());
   size_t data_size = folded_kernel.getElementSize();
-  TensorVariant unfold_kernel(unfold_kernel_shape, buffer, folded_kernel.getDataType(), data_size);
+  TensorVariant unfold_kernel(folded_kernel.getDataType(), unfold_kernel_shape);
 
   int in_group_size = kernel_in_channels;
   int out_group_size = kernel_out_channels / groups;
index 84decd9..6acf095 100644 (file)
@@ -159,8 +159,9 @@ TensorVariant InterpreterPass::loadInput(const Shape& shape) {
   }
 
   rewind(f);
-  auto data = new float[shape.numElements()];
-  auto rlen = fread(data, data_size, 1, f);
+
+  std::unique_ptr<char[]> data(new char[data_size]);
+  auto rlen = fread(data.get(), data_size, 1, f);
   assert(rlen == 1);
   (void) rlen;
 
@@ -168,8 +169,7 @@ TensorVariant InterpreterPass::loadInput(const Shape& shape) {
   assert(is_error != EOF && "Can not close file!");
   (void) is_error;
 
-  std::shared_ptr<float> buffer_sp(data, std::default_delete<float[]>());
-  return TensorVariant(shape, buffer_sp, DTYPE::FLOAT32);
+  return TensorVariant(DTYPE::FLOAT32, shape, data.get());
 }
 
 InterpreterPass::~InterpreterPass() {
index 7846dbb..3aa44ef 100644 (file)
 #ifndef _NNC_CORE_BACKEND_INTERPRETER_OPERATION_IMPL_
 #define _NNC_CORE_BACKEND_INTERPRETER_OPERATION_IMPL_
 
-#include <vector>
-
 #include "core/modelIR/Tensor.h"
 #include "core/modelIR/TensorVariant.h"
-
 #include "core/modelIR/Shape.h"
+#include <vector>
 
-namespace nnc
-{
+namespace nnc {
 
-template <typename T> class OperationImpl
-{
+template<typename T>
+class OperationImpl {
 public:
   virtual std::vector<mir::TensorVariant> operator()() = 0;
 
 protected:
-  mir::TensorVariant allocate_tensor(const mir::Shape &shape)
-  {
-    size_t data_size = 1;
-    for (int32_t i = 0; i < shape.rank(); ++i)
-    {
-      data_size *= shape.dim(i);
-    }
-
-    auto od = new T[data_size]();
-
-    std::shared_ptr<T> data(od, [](const T* d) { delete[] d; });
+  mir::TensorVariant allocate_tensor(const mir::Shape& shape) {
     // Use hardcoded DTYPE for now, since theres no support for operations on types other than
     // floats
-    mir::TensorVariant t(shape, data, mir::DTYPE::FLOAT32);
-
-    return t;
+    std::vector<float> zeros(static_cast<std::size_t>(shape.numElements()), 0.0f);
+    return mir::TensorVariant(mir::DTYPE::FLOAT32, shape, zeros.data());
   }
 };
 
index b78de2f..a4dd51e 100644 (file)
@@ -90,76 +90,43 @@ static void collectUnsupportedOps(std::unique_ptr<onnx::ModelProto>& model) {
 }
 
 mir::TensorVariant ONNXImporterImpl::createTensor(const onnx::TensorProto* tensor) {
-  mir::DTYPE type = mir::DTYPE::FLOAT32;
-  size_t element_size;
-  size_t buffer_size;
-  const char* src_data;
+  mir::DTYPE type;
+  const void* src_data;
   auto shape = ShapeHelper::createShape(tensor->dims(), static_cast<size_t>(tensor->dims_size()));
 
   if (tensor->float_data_size() != 0) {
-    element_size = sizeof(float);
-    buffer_size = tensor->float_data_size() * element_size;
-    src_data = reinterpret_cast<const char*>(tensor->float_data().data());
+    assert(tensor->data_type() == onnx::TensorProto::FLOAT);
+    type = mir::DTYPE::FLOAT32;
+    src_data = tensor->float_data().data();
   } else if (tensor->double_data_size() != 0) {
-    // TODO: we should copy element by element to convert the items
-    element_size = sizeof(double);
-    buffer_size = tensor->double_data_size() * element_size;
-    src_data = reinterpret_cast<const char*>(tensor->double_data().data());
-    throw PassException("WARNING: We don't support double tensors yet, investigate\n");
+    assert(tensor->data_type() == onnx::TensorProto::DOUBLE);
+    type = mir::DTYPE::FLOAT64;
+    src_data = tensor->double_data().data();
   } else if (tensor->int32_data_size() != 0) {
-    element_size = sizeof(int32_t);
-    buffer_size = tensor->int32_data_size() * element_size;
-    src_data = reinterpret_cast<const char*>(tensor->int32_data().data());
-    mir::DTYPE type = mir::DTYPE::INT32;
+    assert(tensor->data_type() == onnx::TensorProto::INT32);
+    type = mir::DTYPE::INT32;
+    src_data = tensor->int32_data().data();
   } else if (tensor->int64_data_size() != 0) {
-//    // FIXME: we could lose the data here
-//    type = mir::DTYPE::INT32;
-//    element_size = sizeof(int32_t);
-//    buffer_size = tensor->int64_data_size() * element_size;
-//
-//    auto src_data64 = reinterpret_cast<const int64_t *>(tensor->int64_data().data());
-//    std::shared_ptr<char> shared_buffer (new char[buffer_size], std::default_delete<char[]>());
-//    auto dst_data = reinterpret_cast<int32_t *>(shared_buffer.get());
-//    for (int i = 0; i < tensor->int64_data_size(); i++) {
-//      dst_data[i] = (int32_t)src_data64 [i];
-//    }
-//    return mir::TensorVariant(shape, shared_buffer, type, element_size);
-    // FIXME: it's a hack to support mobilenet in soft backend
-    // (the above code works under interpreter but does not work in softbackend)
-    element_size = sizeof(float);
-    buffer_size = tensor->int64_data_size() * element_size;
-    auto src_data64 = reinterpret_cast<const int64_t *>(tensor->int64_data().data());
-    std::shared_ptr<char> shared_buffer (new char[buffer_size], std::default_delete<char[]>());
-    auto dst_data = reinterpret_cast<float*>(shared_buffer.get());
-    for (int i = 0; i < tensor->int64_data_size(); i++) {
-      dst_data[i] = static_cast<float>(src_data64[i]);
-    }
-    return mir::TensorVariant(shape, shared_buffer, type, element_size);
-  } else if (tensor->raw_data().size() != 0) {
-    switch ((tensor->data_type())) {
-      case onnx::TensorProto_DataType_FLOAT:
-        element_size = sizeof(float);
-        buffer_size = tensor->raw_data().size();
-        src_data = reinterpret_cast<const char*>(tensor->raw_data().data());
+    assert(tensor->data_type() == onnx::TensorProto::INT64);
+    type = mir::DTYPE::INT64;
+    src_data = tensor->int64_data().data();
+  } else if (tensor->has_raw_data()) {
+    switch (tensor->data_type()) {
+      case onnx::TensorProto::FLOAT:
+        type = mir::DTYPE::FLOAT32;
         break;
-      case onnx::TensorProto_DataType_INT64: {
-        element_size = sizeof(int64_t);
-        buffer_size = tensor->raw_data().size();
-        src_data = reinterpret_cast<const char*>(tensor->raw_data().data());
+      case onnx::TensorProto::INT64:
         type = mir::DTYPE::INT64;
         break;
-      }
       default:
-        throw PassException("Don't support this tensor type yet, investigate");
+        throw PassException("Unsupported data type");
     }
+    src_data = tensor->raw_data().data();
   } else {
     throw PassException("Invalid data in Proto file, investigate");
   }
 
-  std::shared_ptr<char> data(new char[buffer_size], std::default_delete<char[]>());
-  memcpy(data.get(), src_data, buffer_size);
-
-  return mir::TensorVariant(shape, data, type, element_size);
+  return mir::TensorVariant(type, shape, src_data);
 }
 
 void ONNXImporterImpl::createGraphInputs() {
index fbc7e0b..4721796 100644 (file)
@@ -97,27 +97,8 @@ static std::pair<bool, float> getFloatAttribute(const onnx::NodeProto& onnx_node
 // Create vector tensor filled with the given value
 // TODO: it should be template
 static TensorVariant createTensor(float value, const mir::Shape& shape) {
-  mir::DTYPE element_type = mir::DTYPE::FLOAT32;
-  size_t element_size = sizeof(value);
-
-  float* dst_ptr = new float[shape.numElements()];
-  for (int i = 0; i < shape.numElements(); i++) {
-    dst_ptr[i] = value;
-  }
-  std::shared_ptr<char> data((char*)dst_ptr, std::default_delete<char[]>());
-  return mir::TensorVariant({shape.numElements()}, data, element_type, element_size);
-}
-
-// Create vector tensor filled with the given shape and values
-// TODO: it should be template
-static TensorVariant createTensor(const float* values, const mir::Shape& shape) {
-  mir::DTYPE element_type = mir::DTYPE::FLOAT32;
-  size_t element_size = sizeof(float);
-
-  float* dst_ptr = new float[shape.numElements()];
-  memcpy(dst_ptr, values, element_size * shape.numElements());
-  std::shared_ptr<char> data(reinterpret_cast<char*>(dst_ptr), std::default_delete<char[]>());
-  return mir::TensorVariant(shape, data, element_type, element_size);
+  std::vector<float> values(static_cast<std::size_t>(shape.numElements()), value);
+  return mir::TensorVariant(mir::DTYPE::FLOAT32, {shape.numElements()}, values.data());
 }
 
 struct KernelStridesPadding {
@@ -298,7 +279,7 @@ ONNXOpCreator::convertSoftmax(const std::vector<mir::IODescriptor>& inputs,
 std::vector<IODescriptor>
 ONNXOpCreator::convertReshape(const std::vector<mir::IODescriptor>& inputs) {
   // The original shape
-  auto in_shape = inputs[0].op->getOutputShape(inputs[0].index);
+  auto in_shape = inputs[0].getShape();
 
   // Input tensor describing the new shape
   // TODO: could it be not a constant?
@@ -312,8 +293,7 @@ ONNXOpCreator::convertReshape(const std::vector<mir::IODescriptor>& inputs) {
   // The vector to build the new shape from
   std::vector<int32_t > shape_vector(cnt);
   ShapeRange out_range(shape_tensor_shape);
-  // FIXME: real type should be int64_t
-  Tensor<float> tensor_accessor(shape_tensor);
+  Tensor<int64_t> tensor_accessor(shape_tensor);
 
   int i = 0;
   for (auto idx : out_range) {
@@ -472,12 +452,13 @@ std::vector<IODescriptor>
 ONNXOpCreator::convertShape(const std::vector<mir::IODescriptor>& inputs) {
   const auto& input_shape = inputs[0].op->getOutputShape(inputs[0].index);
   int size = input_shape.rank();
-  Shape output_shape({size});
-  std::vector<float> data(size);
+  Shape output_shape{size};
+  std::vector<float> data(static_cast<std::size_t>(size));
   for (int i; i < size; i++) {
     data[i] = input_shape.dim(i);
   }
-  auto result = createOp<ops::ConstantOp>(createTensor(data.data(), output_shape));
+  TensorVariant tensor(DTYPE::FLOAT32, output_shape, data.data());
+  auto result = createOp<ops::ConstantOp>(tensor);
   return {result->getOutput(0)};
 }
 
@@ -491,7 +472,7 @@ ONNXOpCreator::convertGivenTensorFill(const onnx::NodeProto& onnx_node,
   Shape shape(shape_att->ints_size());
   for (int i = 0; i < shape_att->ints_size(); i++)
     shape.dim(i) = shape_att->ints(i);
-  auto tensor = createTensor(values_att->floats().data(), shape);
+  TensorVariant tensor(DTYPE::FLOAT32, shape, values_att->floats().data());
   input_tensors.insert(std::make_pair(onnx_node.output(0), tensor));
   auto result = createOp<ops::ConstantOp>(tensor);
   return {result->getOutput(0)};
index d837548..75ba611 100644 (file)
@@ -307,43 +307,25 @@ std::vector<mir::IODescriptor> TfliteImporter::getMIRInputsForOperator(const Ope
 }
 
 mir::TensorVariant TfliteImporter::createTensor(const Tensor* t, const Buffer* b) {
-  // Create TensorVariant by copying the tensor buffer contents.
-  // Another option is to copy the data in a TensorVariant constructor.
   assert(b->data() != nullptr);
-  std::shared_ptr<char> data(new char[b->data()->size()], std::default_delete<char[]>());
-  std::copy(b->data()->begin(), b->data()->end(), data.get());
 
-  size_t elementSize;
   mir::DTYPE type;
   switch (t->type()) {
-    case TensorType_UINT8:
-      elementSize = sizeof(uint8_t);
-      type = mir::DTYPE::INT32; // TODO
-      break;
-    case TensorType_FLOAT16:
-      elementSize = sizeof(uint16_t);
-      type = mir::DTYPE::FLOAT32; // TODO
-      break;
     case TensorType_INT32:
-      elementSize = sizeof(uint32_t);
       type = mir::DTYPE::INT32;
       break;
     case TensorType_FLOAT32:
-      elementSize = sizeof(uint32_t);
       type = mir::DTYPE::FLOAT32;
       break;
     case TensorType_INT64:
-      elementSize = sizeof(uint64_t);
-      type = mir::DTYPE::INT32; // TODO
+      type = mir::DTYPE::INT64;
       break;
     default:
-      throw PassException(
-              std::string("Encountered unsupported tensor type ") +
-              EnumNamesTensorType()[t->type()]);
+      throw PassException(std::string("Unsupported tensor type: ") + EnumNameTensorType(t->type()));
   }
 
   auto shape = ShapeHelper::createShape(*t->shape(), t->shape()->size());
-  return mir::TensorVariant(shape, data, type, elementSize);
+  return mir::TensorVariant(type, shape, b->data()->Data());
 }
 
 void TfliteImporter::setGraphOutputs() {
index 2774437..0de6d45 100644 (file)
 using namespace nnc;
 using namespace nnc::mir;
 
-std::shared_ptr<TensorVariant> getTensor(const opinfo::Tensor* t)
-{
-  std::shared_ptr<char> tensorBufferCopy(
-          new char[t->data()->size() * sizeof(float)], [](char *d) { delete[] d; });
-  std::copy(t->data()->begin(), t->data()->end(), reinterpret_cast<float*>(tensorBufferCopy.get()));
-
-  size_t elementSize = sizeof(float);
-  DTYPE type = DTYPE::FLOAT32;
-
-  Shape tensorShape = ShapeHelper::createShape(*t->shape()->dims(), t->shape()->dims()->size());
-
-  return std::make_shared<TensorVariant>(tensorShape, tensorBufferCopy, type, elementSize);
+std::shared_ptr<TensorVariant> getTensor(const opinfo::Tensor* t) {
+  Shape shape = ShapeHelper::createShape(*t->shape()->dims(), t->shape()->dims()->size());
+  return std::make_shared<TensorVariant>(DTYPE::FLOAT32, shape, t->data()->Data());
 }
 
 ops::PoolOp::PoolingType getPoolingType(const opinfo::OperatorInfo* opInfo)
index 3161cdf..ed72d03 100644 (file)
@@ -193,13 +193,13 @@ void checkDomStructure(const ArtifactModule& m,
  * @return TensorVariant with specified shape
  */
 TensorVariant createTensorVariant(const Shape& shape) {
-  size_t data_size = shape.numElements();
-  float* data = new float[data_size];
-  for (int32_t i = 0; i < shape.numElements(); ++i)
-    data[i] = i;
+  auto num_elems = shape.numElements();
 
-  shared_ptr<float> ptr(data, default_delete<float[]>());
-  return TensorVariant(shape, ptr, DTYPE::FLOAT32);
+  unique_ptr<float[]> data(new float[num_elems]);
+  float* data_ptr = data.get();
+  for (int32_t i = 0; i < num_elems; ++i)
+    data_ptr[i] = i;
+  return TensorVariant(DTYPE::FLOAT32, shape, data_ptr);
 }
 
 }
index 1bf2555..0c9fb40 100644 (file)
 using namespace nnc::mir;
 
 TEST(TensorVariant, BasicTest) {
-  Shape shape{2,2};
-  char* ptr = (char*)(new float[4]);
-  std::shared_ptr<char> mem(ptr, [](char* d){ delete[] (float*)d; } );
-  TensorVariant t(shape, mem, DTYPE::FLOAT32, sizeof(float));
+  Shape shape{2, 2};
+  TensorVariant t(DTYPE::FLOAT32, shape);
 
   ASSERT_EQ(t.getShape(), shape);
-  ASSERT_EQ(t.getOffset({0,0}), 0u);
+  ASSERT_EQ(t.getOffset({0, 0}), 0u);
 }
 
 TEST(TensorVariant, ElementSizeDeductionTest) {
   Shape shape{2, 2, 2};
-
-  std::shared_ptr<float> mem(new float[8], [](float* f){ delete[] f; });
-  TensorVariant t(shape, mem, DTYPE::FLOAT32);
+  TensorVariant t(DTYPE::FLOAT32, shape);
 
   ASSERT_EQ(t.getElementSize(), sizeof(float));
-  ASSERT_EQ((float*)t.at({1,1,1}), mem.get() + 7);
-}
-
-TEST(TensorVariant, DeletionTest) {
-  struct Indicator {
-    Indicator() : val(true) {
-    }
-
-    void reset() {
-      val = false;
-    }
-
-    bool val;
-  };
-
-  TensorVariant* t;
-  auto raw_indicator = new Indicator[1];
-  {
-    Shape shape{1,1};
-    auto mem = std::shared_ptr<Indicator>(raw_indicator, [](Indicator*& p){ p[0].reset(); });
-    t = new TensorVariant(shape, mem, DTYPE::UNKNOWN);
-    //mem gets destroyed here
-  }
-
-  ASSERT_EQ(raw_indicator->val, true);
-  delete t;
-  ASSERT_EQ(raw_indicator->val, false);
-  delete[] raw_indicator;
+  ASSERT_EQ((float*)t.at({1, 1, 1}), (float*)t.at({0, 0, 0}) + 7);
 }
index cd5058c..e51758c 100644 (file)
@@ -43,52 +43,18 @@ static void checkTensorContent(const Tensor<T>& tensor, const proto::TensorProto
   }
 }
 
-template <typename T>
-static std::shared_ptr<T> allocateTensorContent(const Shape &shape)
-{
-  size_t data_size = 1;
-  for (int32_t i = 0; i < shape.rank(); ++i)
-  {
-    data_size *= shape.dim(i);
-  }
-
-  auto od = new T[data_size];
-
-  std::shared_ptr<T> data(od, std::default_delete<T[]>());
-
-  return data;
-}
-
-static TensorVariant allocateIntTensor(const Shape &shape)
-{
-  std::shared_ptr<int> data = allocateTensorContent<int>(shape);
-  return TensorVariant(shape, data, DTYPE::INT32);
-}
-
 static void checkIntTensor(const Tensor<int>& tensor, const proto::TensorProto& proto_tensor)
 {
   ASSERT_EQ(proto_tensor.dtype(), proto::DataType::DT_INT32);
   checkTensorContent<int>(tensor, proto_tensor);
 }
 
-static TensorVariant allocateFloatTensor(const Shape &shape)
-{
-  std::shared_ptr<float> data = allocateTensorContent<float>(shape);
-  return TensorVariant(shape, data, DTYPE::FLOAT32);
-}
-
 static void checkFloatTensor(const Tensor<float>& tensor, const proto::TensorProto& proto_tensor)
 {
   ASSERT_EQ(proto_tensor.dtype(), proto::DataType::DT_FLOAT);
   checkTensorContent<float>(tensor, proto_tensor);
 }
 
-static TensorVariant allocateDoubleTensor(const Shape &shape)
-{
-  std::shared_ptr<double> data = allocateTensorContent<double>(shape);
-  return TensorVariant(shape, data, DTYPE::FLOAT32);
-}
-
 static void checkDoubleTensor(const Tensor<double>& tensor, const proto::TensorProto& proto_tensor)
 {
   ASSERT_EQ(proto_tensor.dtype(), proto::DataType::DT_DOUBLE);
@@ -141,7 +107,7 @@ TEST(Serializer, IntTensorSerializationTest) {
   int tmp = 0;
 
   Shape shape_1{3};
-  TensorVariant tv_1(allocateIntTensor(shape_1));
+  TensorVariant tv_1(DTYPE::INT32, shape_1);
   Tensor<int> tensor_1(tv_1);
   for (auto& idx : ShapeRange(shape_1)) {
     tensor_1.at(idx) = tmp++;
@@ -153,7 +119,7 @@ TEST(Serializer, IntTensorSerializationTest) {
   checkIntTensor(tensor_1, proto_tensor_1);
 
   Shape shape_2{3, 4, 5};
-  TensorVariant tv_2(allocateIntTensor(shape_2));
+  TensorVariant tv_2(DTYPE::INT32, shape_2);
   Tensor<int> tensor_2(tv_2);
   for (auto& idx : ShapeRange(tensor_2.getShape())) {
     tensor_2.at(idx) = tmp--;
@@ -165,7 +131,7 @@ TEST(Serializer, IntTensorSerializationTest) {
   checkIntTensor(tensor_2, proto_tensor_2);
 
   Shape shape_3{1, 1, 1, 1, 1};
-  TensorVariant tv_3(allocateIntTensor(shape_3));
+  TensorVariant tv_3(DTYPE::INT32, shape_3);
   Tensor<int> tensor_3(tv_3);
   for (auto& idx : ShapeRange(tensor_3.getShape())) {
     tensor_3.at(idx) = tmp++;
@@ -182,7 +148,7 @@ TEST(Serializer, FloatTensorSerializationTest) {
   float tmp = 1.0f;
 
   Shape shape_1{3};
-  TensorVariant tv_1(allocateFloatTensor(shape_1));
+  TensorVariant tv_1(DTYPE::FLOAT32, shape_1);
   Tensor<float> tensor_1(tv_1);
   for (auto& idx : ShapeRange(tensor_1.getShape())) {
     tensor_1.at(idx) = tmp;
@@ -195,7 +161,7 @@ TEST(Serializer, FloatTensorSerializationTest) {
   checkFloatTensor(tensor_1, proto_tensor_1);
 
   Shape shape_2{3, 4, 5};
-  TensorVariant tv_2(allocateFloatTensor(shape_2));
+  TensorVariant tv_2(DTYPE::FLOAT32, shape_2);
   Tensor<float> tensor_2(tv_2);
   for (auto& idx : ShapeRange(tensor_2.getShape())) {
     tensor_2.at(idx) = tmp;
@@ -208,7 +174,7 @@ TEST(Serializer, FloatTensorSerializationTest) {
   checkFloatTensor(tensor_2, proto_tensor_2);
 
   Shape shape_3{1, 1, 1, 1, 1};
-  TensorVariant tv_3(allocateFloatTensor(shape_3));
+  TensorVariant tv_3(DTYPE::FLOAT32, shape_3);
   Tensor<float> tensor_3(tv_3);
   for (auto& idx : ShapeRange(tensor_3.getShape())) {
     tmp -= 6.66f;
@@ -226,7 +192,7 @@ TEST(Serializer, DoubleTensorSerializationTest) {
   double tmp = 1.0f;
 
   Shape shape_1{3};
-  TensorVariant tv_1(allocateDoubleTensor(shape_1));
+  TensorVariant tv_1(DTYPE::FLOAT64, shape_1);
   Tensor<double> tensor_1(tv_1);
   for (auto& idx : ShapeRange(tensor_1.getShape())) {
     tensor_1.at(idx) = tmp;
@@ -239,7 +205,7 @@ TEST(Serializer, DoubleTensorSerializationTest) {
   checkDoubleTensor(tensor_1, proto_tensor_1);
 
   Shape shape_2{3, 4, 5};
-  TensorVariant tv_2(allocateDoubleTensor(shape_2));
+  TensorVariant tv_2(DTYPE::FLOAT64, shape_2);
   Tensor<double> tensor_2(tv_2);
   for (auto& idx : ShapeRange(tensor_2.getShape())) {
     tensor_2.at(idx) = tmp;
@@ -252,7 +218,7 @@ TEST(Serializer, DoubleTensorSerializationTest) {
   checkDoubleTensor(tensor_2, proto_tensor_2);
 
   Shape shape_3{1, 1, 1, 1, 1};
-  TensorVariant tv_3(allocateDoubleTensor(shape_3));
+  TensorVariant tv_3(DTYPE::FLOAT64, shape_3);
   Tensor<double> tensor_3(tv_3);
   for (auto& idx : ShapeRange(tensor_3.getShape())) {
     tmp -= 6.66f;
index 4c6fcb8..0d21ea4 100644 (file)
@@ -180,20 +180,6 @@ void fillNTensor(mir::TensorVariant &dst, float start) {
 }
 
 /**
- * @brief Creates and fills TensorVariant
- * @param shape Shape of desired tensor
- * @param start Seed for tensor filler
- * @return Created object
- */
-mir::TensorVariant createNTensor(mir::Shape &shape, float start) {
-  shared_ptr<char> dataBuf(
-    new char[sizeof(float) * shape.numElements()], default_delete<char[]>());
-  mir::TensorVariant tensor(shape, dataBuf, mir::DTYPE::FLOAT32, sizeof(float));
-  fillNTensor(tensor, start);
-  return tensor;
-}
-
-/**
  * @brief Converts NNC mir::TensorVariant to artifact Tensor object
  */
 void copyATensorFromNTensor(Tensor &dst, mir::TensorVariant &src) {
@@ -219,9 +205,7 @@ void fillTensors(unique_ptr<mir::TensorVariant> &ntensor,
   mir::Shape nshape;
   fillShapes(nshape, ashape, shape);
   atensor.reShape(ashape);
-  shared_ptr<char> dataBuf(
-          new char[sizeof(float) * nshape.numElements()], default_delete<char[]>());
-  ntensor.reset(new mir::TensorVariant(nshape, dataBuf, mir::DTYPE::FLOAT32, sizeof(float)));
+  ntensor.reset(new mir::TensorVariant(mir::DTYPE::FLOAT32, nshape));
   fillNTensor(*ntensor, start);
   copyATensorFromNTensor(atensor, *ntensor);
 }