auto raw_data = new char[raw_data_size];
tensor_content.copy(raw_data, raw_data_size);
- TensorVariant::DTYPE tv_dtype;
+ DTYPE tv_dtype;
size_t element_size;
switch (dt)
{
case proto::DataType::DT_INT32:
element_size = sizeof(int32_t);
- tv_dtype = TensorVariant::DTYPE::INT;
+ tv_dtype = DTYPE::INT32;
break;
case proto::DataType::DT_FLOAT:
element_size = sizeof(float);
- tv_dtype = TensorVariant::DTYPE::FLOAT;
+ tv_dtype = DTYPE::FLOAT32;
break;
case proto::DataType::DT_DOUBLE :
element_size = sizeof(double);
- tv_dtype = TensorVariant::DTYPE::FLOAT;
+ tv_dtype = DTYPE::FLOAT32;
break;
default:
throw std::logic_error("Deserializer<TensorVariant>: received unsupported data type");
namespace mir
{
-Index::Index(std::initializer_list<int32_t> &&l) : _indices{l}
-{
- // DO NOTHING
-}
+Index::Index(std::initializer_list<int32_t>&& l) : _indices{l} {}
+
+Index::Index(std::vector<int32_t>&& vec) : _indices(vec) {}
int32_t Index::rank(void) const { return _indices.size(); }
Index &Index::resize(int32_t size)
namespace mir
{
-TensorVariant::TensorVariant(const Shape& shape, const std::shared_ptr<char>& data, TensorVariant::DTYPE dtype, size_t element_size)
- : _dtype(dtype), _data(data), _strides{0}, _rank(shape.rank()), _shape(shape), _element_size(element_size)
+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), _element_size(element_size)
{
int stride = 1;
for (int d = _rank - 1; d >= 0; --d)
--- /dev/null
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _NCC_CORE_DATA_TYPE_H_
+#define _NCC_CORE_DATA_TYPE_H_
+
+namespace nnc {
+namespace mir {
+
+enum class DTYPE {
+ UNKNOWN,
+ FLOAT32,
+ INT32
+};
+
+} // namespace mir
+} // namespace nnc
+
+#endif //_NCC_CORE_DATA_TYPE_H_
{
public:
Index() = default;
- Index(std::initializer_list<int32_t> &&l);
+ Index(std::initializer_list<int32_t>&& l);
+ Index(std::vector<int32_t>&& vec);
int32_t rank(void) const;
--- /dev/null
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _NNC_CORE_SCALAR_H_
+#define _NNC_CORE_SCALAR_H_
+
+#include <memory>
+#include <cassert>
+#include <cstring>
+
+#include "core/modelIR/DataType.h"
+
+namespace nnc {
+namespace mir {
+
+/**
+ * @brief Scalar class
+ */
+class Scalar {
+public:
+ /**
+ * @brief Class for Scalar values in modelIR
+ * @param data Data pointer
+ * @param dtype Data type
+ * @param data_size Data size
+ */
+ explicit Scalar(const char* data, DTYPE dtype, unsigned data_size) {
+ assert(data_size <= maxScalarLength);
+ _dataType = dtype;
+ memcpy(_data, data, data_size);
+ }
+
+ /**
+ * @return Pointer on data
+ */
+ char* getRawData() { return _data; }
+
+ /**
+ * @return Data type
+ */
+ DTYPE getDataType() { return _dataType; }
+
+ /**
+ * @return Data size
+ */
+ int getDataSize() const {
+ switch (_dataType) {
+ case DTYPE::UNKNOWN:
+ return -1;
+ case DTYPE::FLOAT32:
+ case DTYPE::INT32:
+ return 4;
+ }
+ }
+ /**
+ * @tparam T Class of returned object
+ * @return Object of T type
+ */
+ template<typename T>
+ T get() const {
+ assert(sizeof(T) <= getDataSize());
+ T result;
+ memcpy(&result, _data, sizeof(T));
+ return result;
+ }
+
+private:
+ static const unsigned int maxScalarLength = 8;
+ DTYPE _dataType;
+ char _data[maxScalarLength];
+};
+
+} // namespace mir
+} // namespace nnc
+
+#endif //_NNC_CORE_SCALAR_H_
#include "core/modelIR/Index.h"
#include "core/modelIR/Shape.h"
+#include "core/modelIR/DataType.h"
namespace nnc
{
class TensorVariant {
public:
- enum class DTYPE {
- UNKNOWN,
- FLOAT,
- INT
- };
explicit TensorVariant(const Shape& shape, const std::shared_ptr<char>& data, DTYPE dtype, size_t element_size);
#define _NCC_CORE_IR_MODEL_PAD_H_
#include "core/modelIR/Operation.h"
-#include "core/modelIR/TensorVariant.h"
-#include <vector>
+
+#include "core/modelIR/Scalar.h"
namespace nnc {
namespace mir {
namespace ops {
+/**
+ * @brief Pad operation class
+ */
class PadOp : public Operation {
public:
- enum class PaddingMode {
- CONST,
- REFLECT,
- SYMMETRIC
- };
-
- PadOp(const IODescriptor& arg, PaddingMode paddingMode, int numDims,
- const TensorVariant& constant_value)
- : Operation(Type::pad, {arg}), _paddingMode(paddingMode), _numDims(numDims),
- _constant_value(constant_value) {
- _paddings.resize(_numDims);
- }
+ /**
+ * @brief Class for Pad operation in modelIR
+ * @param arg IODescriptor
+ * @param numDims Number of dimensions
+ * @param paddings Vector with pairs of paddings (left, right)
+ * @param scalar_value Constant value filling padded region
+ */
+ PadOp(const IODescriptor& arg, int32_t numDims,
+ const std::vector<std::pair<int32_t, int32_t>>& paddings,
+ const Scalar& scalar_value)
+ : Operation(Type::pad, {arg}), _numDims(numDims),
+ _paddings(paddings), _scalarValue(scalar_value) {}
- PaddingMode getPaddingMode() const { return _paddingMode; }
-
- void setPadding(int dim, int32_t front_pad, int32_t back_pad) {
- assert(dim < _numDims);
- _paddings[dim].first = front_pad;
- _paddings[dim].second = back_pad;
- }
-
- std::pair<int32_t, int32_t> getPaddingForDim(int dim) { return _paddings[dim]; }
+ /**
+ * @param dim Dimension number
+ * @return Pair of paddings for dimension
+ */
+ std::pair<int32_t, int32_t> getPaddingForDim(int dim) const { return _paddings[dim]; }
+ /**
+ * @return Number of dimensions
+ */
int getNumDim() const { return _numDims; }
+ /**
+ * @return Scalar value
+ */
+ Scalar getScalar() const { return _scalarValue; }
+
private:
- PaddingMode _paddingMode;
std::vector<std::pair<int32_t, int32_t>> _paddings;
- int _numDims;
- TensorVariant _constant_value;
+ int32_t _numDims;
+ Scalar _scalarValue;
};
} // namespace ops
}
std::shared_ptr<IrTensor> CaffeImporter::createTensor(const BlobProto& bp) {
- auto type = IrTensor::DTYPE::FLOAT;
+ auto type = DTYPE::FLOAT32;
size_t element_size;
const char* src_data;
unfold_kernel->at(idx));
} else {
// fill element of output kernel with zero element
- assert(folded_kernel->getDataType() == IrTensor::DTYPE::FLOAT &&
+ assert(folded_kernel->getDataType() == DTYPE::FLOAT32 &&
"unsupported data type, add appropriate zero element creation");
float* elem = reinterpret_cast<float*>(unfold_kernel->at(idx));
*elem = 0.0f;
#include "core/modelIR/operations/TanhOp.h"
#include "core/modelIR/operations/ElementwiseOp.h"
#include "core/modelIR/operations/SqueezeOp.h"
+#include "core/modelIR/operations/PadOp.h"
#include "ops/Bias.h"
#include "ops/Concat.h"
#include "ops/Scale.h"
#include "ops/Dropout.h"
#include "ops/BatchNorm.h"
+#include "ops/Pad.h"
namespace nnc {
}
void NNInterpreter::visit(ops::PadOp& op) {
- throw PassException("Not implemented yet");
+ mapByName(&op);
+ auto operand = op.getPrevNodes()[0];
+ auto& input = var(operand.op->getId())[operand.index];
+ var(op.getId()) = Pad(input, op)();
}
} // namespace nnc
assert(is_error != EOF && "Can not close file!");
(void)is_error;
- return TensorVariant(shape, std::shared_ptr<char>(data, [](const char* d) { delete[] d; }), TensorVariant::DTYPE::FLOAT, sizeof(float));
+ return TensorVariant(shape, std::shared_ptr<char>(data, std::default_delete<char[]>()),
+ DTYPE::FLOAT32, sizeof(float));
}
InterpreterPass::~InterpreterPass()
std::shared_ptr<T> data(od, [](const T* d) { delete[] d; });
// Use hardcoded DTYPE for now, since theres no support for operations on types other than
// floats
- mir::TensorVariant t(shape, data, mir::TensorVariant::DTYPE::FLOAT);
+ mir::TensorVariant t(shape, data, mir::DTYPE::FLOAT32);
return t;
}
--- /dev/null
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "core/modelIR/ShapeRange.h"
+
+#include "Pad.h"
+
+namespace nnc {
+
+using namespace mir;
+
+std::vector<TensorVariant> Pad::operator()() {
+ auto result = allocate_tensor(_op.getOutputShape(0));
+ Tensor<float> result_accessor(result);
+
+ Shape out_shape = result_accessor.getShape();
+
+ ShapeRange out_range(out_shape);
+ int32_t rank = _op.getNumDim();
+
+ Index temp_index;
+ temp_index.resize(rank);
+
+ bool index_on_padding(false);
+ for (const Index& ind : out_range) {
+ index_on_padding = false;
+
+ for (int32_t i = 0; i < rank; i++) {
+ // index on input values
+ if (ind.at(i) >= _op.getPaddingForDim(i).first &&
+ ind.at(i) < out_shape.dim(i) - _op.getPaddingForDim(i).second) {
+ temp_index.at(i) = ind.at(i) - _op.getPaddingForDim(i).first;
+ } else { // not in input
+ index_on_padding = true;
+ break;
+ }
+ }
+ if (index_on_padding) {
+ result_accessor.at(ind) = _op.getScalar().get<float>();
+ } else {
+ result_accessor.at(ind) = _input.at(temp_index);
+ }
+ }
+
+ return {result};
+}
+
+} // namespace nnc
--- /dev/null
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _NNC_CORE_BACKEND_INTERPRETER_PAD_IMPL_
+#define _NNC_CORE_BACKEND_INTERPRETER_PAD_IMPL_
+
+#include "OperationImpl.h"
+#include "core/modelIR/operations/PadOp.h"
+
+namespace nnc {
+/**
+ * @brief Implements PadOp for interpreter backend
+ *
+ * This operation pads a tensor according to the paddings
+ * you specify. For each dimension of input add values
+ * before and after of contents.
+ */
+class Pad : public OperationImpl<float> {
+public:
+ /**
+ * @param input The Input tensor
+ * @param op The Pad operation object
+ */
+ Pad(const mir::TensorVariant& input, const mir::ops::PadOp& op)
+ : _input(input), _op(op) {
+ assert(_input.getShape().rank() == _op.getNumDim());
+ }
+
+ /**
+ * @brief Computes operation aplication result
+ * @return Vector of all outputs from this node
+ */
+ std::vector<mir::TensorVariant> operator()() override;
+
+private:
+ const mir::Tensor<float> _input;
+ const mir::ops::PadOp& _op;
+};
+
+} // namespace nnc
+
+#endif // _NNC_CORE_BACKEND_INTERPRETER_PAD_IMPL_
case BuiltinOperator_SOFTMAX:
case BuiltinOperator_RESHAPE:
case BuiltinOperator_SQUEEZE:
+ case BuiltinOperator_PAD:
case BuiltinOperator_ADD:
case BuiltinOperator_MUL:
case BuiltinOperator_MAXIMUM:
outputs = _opCreator->createTransposeConv(
inputs, params,op->builtin_options_as<TransposeConvOptions>());
break;
+ case BuiltinOperator_PAD:
+ outputs = _opCreator->createPad(inputs, params, op->builtin_options_as<PadOptions>());
+ break;
default:
assert(false && "All unsupported types should have been found before this pass.");
}
std::copy(b->data()->begin(), b->data()->end(), tensor_buffer_copy.get());
size_t elementSize;
- IrTensor::DTYPE type;
+ mir::DTYPE type;
switch (t->type()) {
case TensorType_UINT8:
elementSize = sizeof(uint8_t);
- type = IrTensor::DTYPE::INT;
+ type = mir::DTYPE::INT32; // TODO
break;
case TensorType_FLOAT16:
elementSize = sizeof(uint16_t);
- type = IrTensor::DTYPE::FLOAT;
+ type = mir::DTYPE::FLOAT32; // TODO
break;
case TensorType_INT32:
elementSize = sizeof(uint32_t);
- type = IrTensor::DTYPE::INT;
+ type = mir::DTYPE::INT32;
break;
case TensorType_FLOAT32:
elementSize = sizeof(uint32_t);
- type = IrTensor::DTYPE::FLOAT;
+ type = mir::DTYPE::FLOAT32;
break;
case TensorType_INT64:
elementSize = sizeof(uint64_t);
- type = IrTensor::DTYPE::INT;
+ type = mir::DTYPE::INT32; // TODO
break;
default:
throw PassException(
#include "core/modelIR/operations/BiasAddOp.h"
#include "core/modelIR/operations/ReshapeOp.h"
#include "core/modelIR/operations/SqueezeOp.h"
+#include "core/modelIR/operations/PadOp.h"
+#include "core/modelIR/Tensor.h"
#include "pass/PassException.h"
using namespace nnc::mir;
squeeze_dims);
}
+std::vector<mir::Operation*> TFLiteOpCreator::createPad(InputOps inputs, InputParams params,
+ const ::tflite::PadOptions *opts) {
+ assert(params.size() == 1); // support pad with one param
+ std::vector<std::pair<int32_t, int32_t>> paddings;
+
+ auto paddings_tensor = mir::Tensor<int32_t>(*params[0].get());
+ // check right paddings structure
+ assert(paddings_tensor.getShape().dim(1) == 2);
+
+ int32_t num_dims = paddings_tensor.getShape().dim(0);
+ // create strucuture with paddings
+ for (int i = 0; i < num_dims; i++)
+ paddings.emplace_back(paddings_tensor.at(Index({i, 0})), paddings_tensor.at(Index({i, 1})));
+ // create const value, it's float because we can't see input type
+ float const_value = 0.0; // not support different constant value
+ // create scalar with constant value
+ Scalar constant_value(reinterpret_cast<char*>(&const_value), DTYPE::FLOAT32, sizeof(float));
+
+ return createOp<ops::PadOp>(ActivationFunctionType_NONE, inputs[0]->getOutput(0),
+ num_dims, paddings, constant_value);
+}
+
} // namespace nnc
#include "core/modelIR/Graph.h"
#include "core/modelIR/TensorVariant.h"
+#include "core/modelIR/Scalar.h"
#include "core/modelIR/Shape.h"
#include "core/modelIR/operations/common.h"
InputOps&, InputParams&,
const ::tflite::TransposeConvOptions*);
+ /**
+ * @brief Create a Pad operation
+ * @param inputs Operations vector
+ * @param params Tensor with paddings for each dimension
+ * @param opts TFLite PadOptions
+ * @return Operations vector
+ */
+ std::vector<mir::Operation*> createPad(InputOps& inputs, InputParams& params,
+ const ::tflite::PadOptions* opts);
+
void checkPool2D(const ::tflite::Pool2DOptions*, std::set<std::string>&);
void checkConcatenation(const ::tflite::ConcatenationOptions*, std::set<std::string>&);
std::copy(t->data()->begin(), t->data()->end(), reinterpret_cast<float*>(tensorBufferCopy.get()));
size_t elementSize = sizeof(float);
- TensorVariant::DTYPE type = TensorVariant::DTYPE::FLOAT;
+ DTYPE type = DTYPE::FLOAT32;
Shape tensorShape = ShapeHelper::createShape(*t->shape()->dims(), t->shape()->dims()->size());
char* ptr = (char*)(new float[4]);
std::shared_ptr<char> mem(ptr, [](char* d){ delete[] (float*)d; } );
- TensorVariant t(shape, mem, TensorVariant::DTYPE::FLOAT, sizeof(float));
+ TensorVariant t(shape, mem, DTYPE::FLOAT32, sizeof(float));
ASSERT_EQ(t.getShape(), shape);
ASSERT_EQ(t.getOffset({0,0}), 0u);
std::shared_ptr<float> mem(new float[8], [](float* f){ delete[] f; });
- TensorVariant t(shape, mem, TensorVariant::DTYPE::FLOAT);
+ TensorVariant t(shape, mem, DTYPE::FLOAT32);
ASSERT_EQ(t.getElementSize(), sizeof(float));
ASSERT_EQ((float*)t.at({1,1,1}), mem.get() + 7);
{
Shape shape{1,1};
auto mem = std::shared_ptr<Indicator>(raw_indicator, [](Indicator*& p){ p[0].reset(); });
- t = new TensorVariant(shape, mem, TensorVariant::DTYPE::UNKNOWN);
+ t = new TensorVariant(shape, mem, DTYPE::UNKNOWN);
//mem gets destroyed here
}
static TensorVariant allocateIntTensor(const Shape &shape)
{
std::shared_ptr<int> data = allocateTensorContent<int>(shape);
- return TensorVariant(shape, data, TensorVariant::DTYPE::INT);
+ return TensorVariant(shape, data, DTYPE::INT32);
}
static void checkIntTensor(const Tensor<int>& tensor, const proto::TensorProto& proto_tensor)
static TensorVariant allocateFloatTensor(const Shape &shape)
{
std::shared_ptr<float> data = allocateTensorContent<float>(shape);
- return TensorVariant(shape, data, TensorVariant::DTYPE::FLOAT);
+ return TensorVariant(shape, data, DTYPE::FLOAT32);
}
static void checkFloatTensor(const Tensor<float>& tensor, const proto::TensorProto& proto_tensor)
static TensorVariant allocateDoubleTensor(const Shape &shape)
{
std::shared_ptr<double> data = allocateTensorContent<double>(shape);
- return TensorVariant(shape, data, TensorVariant::DTYPE::FLOAT);
+ return TensorVariant(shape, data, DTYPE::FLOAT32);
}
static void checkDoubleTensor(const Tensor<double>& tensor, const proto::TensorProto& proto_tensor)
{
shared_ptr<char> dataBuf(
new char[sizeof(float) * shape.numElements()], default_delete<char[]>());
- mir::TensorVariant tensor(shape, dataBuf, mir::TensorVariant::DTYPE::FLOAT, sizeof(float));
+ mir::TensorVariant tensor(shape, dataBuf, mir::DTYPE::FLOAT32, sizeof(float));
fillNTensor(tensor, start);
return tensor;
}
aTensor.reShape(aShape);
shared_ptr<char> dataBuf(
new char[sizeof(float) * nShape.numElements()], default_delete<char[]>());
- nTensor.reset(new mir::TensorVariant(nShape, dataBuf, mir::TensorVariant::DTYPE::FLOAT, sizeof(float)));
+ nTensor.reset(new mir::TensorVariant(nShape, dataBuf, mir::DTYPE::FLOAT32, sizeof(float)));
fillNTensor(*nTensor, start);
copyATensorFromNTensor(aTensor, *nTensor);
}
artifact_idx[i] = nnc_idx.at(i);
}
assert(ref_nnc_tensor.getElementSize() == 4L &&
- ref_nnc_tensor.getDataType() == mir::TensorVariant::DTYPE::FLOAT);
+ ref_nnc_tensor.getDataType() == mir::DTYPE::FLOAT32);
// Input and output data lies in range of [-10, 10],
// chosen epsilon lies near the edge of float type computational precision
float ref_data = mir::Tensor<float>(ref_nnc_tensor).at(nnc_idx);