* 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>
// 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 <>
*/
#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)
{
}
}
+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
enum class DTYPE {
UNKNOWN,
FLOAT32,
+ FLOAT64,
INT32,
INT64
};
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)...};
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;
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());
}
#include <fstream>
#include <sstream>
#include <cassert>
+#include <cstring>
namespace nnc {
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) {
}
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>
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));
}
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:
// 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;
}
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;
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() {
#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());
}
};
}
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() {
// 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 {
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?
// 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) {
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)};
}
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)};
}
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() {
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)
* @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);
}
}
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);
}
}
}
-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);
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++;
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--;
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++;
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;
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;
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;
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;
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;
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;
}
/**
- * @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) {
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);
}