From: Efimov Alexander/AI Tools Lab/./Samsung Electronics Date: Tue, 9 Oct 2018 11:15:55 +0000 (+0300) Subject: [nnc] Refactor nnc Shape and related classes (#1645) X-Git-Tag: nncc_backup~1598 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=adb8af8b915a532a95264a6aba67dbee4847f751;p=platform%2Fcore%2Fml%2Fnnfw.git [nnc] Refactor nnc Shape and related classes (#1645) Number of warnings minimized, Replace unsigned ints with signed in Model IR Move num_elements and AUTO_DIM into Shape class Signed-off-by: Efimov Alexander --- diff --git a/contrib/nnc/core/modelIR/Deserializer.cpp b/contrib/nnc/core/modelIR/Deserializer.cpp index b91efef..2a99c90 100644 --- a/contrib/nnc/core/modelIR/Deserializer.cpp +++ b/contrib/nnc/core/modelIR/Deserializer.cpp @@ -96,7 +96,7 @@ static TensorVariant deserializeFromMessage(const proto::TensorProto& object_as_ default: throw std::logic_error("Deserializer: received unsupported data type"); } - assert(raw_data_size / element_size == num_elements(shape)); + assert(raw_data_size / element_size == static_cast(shape.numElements())); std::shared_ptr data(raw_data, std::default_delete()); return TensorVariant(shape, data, tv_dtype, element_size); } diff --git a/contrib/nnc/core/modelIR/Index.cpp b/contrib/nnc/core/modelIR/Index.cpp index 6efb9dd..78f2ae2 100644 --- a/contrib/nnc/core/modelIR/Index.cpp +++ b/contrib/nnc/core/modelIR/Index.cpp @@ -23,31 +23,31 @@ namespace nnc namespace mir { -Index::Index(std::initializer_list &&l) : _indices{l} +Index::Index(std::initializer_list &&l) : _indices{l} { // DO NOTHING } -uint32_t Index::rank(void) const { return _indices.size(); } -Index &Index::resize(uint32_t size) +int32_t Index::rank(void) const { return _indices.size(); } +Index &Index::resize(int32_t size) { _indices.resize(size); return *this; } -Index &Index::fill(uint32_t index) +Index &Index::fill(int32_t index) { std::fill(_indices.begin(), _indices.end(), index); return (*this); } -uint32_t &Index::at(uint32_t axis) { return _indices.at(axis); } -uint32_t Index::at(uint32_t axis) const { return _indices.at(axis); } +int32_t &Index::at(int32_t axis) { return _indices[(axis < 0) ? (_indices.size() + axis) : axis]; } +int32_t Index::at(int32_t axis) const { return _indices[(axis < 0) ? (_indices.size() + axis) : axis]; } std::ostream &operator<<(std::ostream &s, const Index &sh) { s << "[ "; - for (uint32_t i = 0; i < sh.rank(); ++i) + for (int32_t i = 0; i < sh.rank(); ++i) { if (i != 0 ) s << ", "; diff --git a/contrib/nnc/core/modelIR/Serializer.cpp b/contrib/nnc/core/modelIR/Serializer.cpp index b61b95c..a7da433 100644 --- a/contrib/nnc/core/modelIR/Serializer.cpp +++ b/contrib/nnc/core/modelIR/Serializer.cpp @@ -36,8 +36,8 @@ std::string Serializer::getSerializedObject (const Shape& shape) { proto::TensorShapeProto shapeProto; - uint32_t rank = shape.rank(); - for (uint32_t i = 0; i < rank; i++) { + int32_t rank = shape.rank(); + for (int32_t i = 0; i < rank; i++) { shapeProto.add_dims(shape.dim(i)); } @@ -58,7 +58,7 @@ static proto::TensorProto serializeTensorContent(const Tensor& tensor) tp.set_dtype(dtype); - size_t data_size = num_elements(tensor.getShape()); + size_t data_size = tensor.getShape().numElements(); auto tensor_data = new T[data_size]; size_t i = 0; ShapeRange shapeRange(tensor.getShape()); diff --git a/contrib/nnc/core/modelIR/Shape.cpp b/contrib/nnc/core/modelIR/Shape.cpp index fdac281..8867e6b 100644 --- a/contrib/nnc/core/modelIR/Shape.cpp +++ b/contrib/nnc/core/modelIR/Shape.cpp @@ -17,67 +17,64 @@ #include "core/modelIR/Shape.h" #include +#include namespace nnc { namespace mir { -Shape::Shape(std::initializer_list &&l) : _dims{l} +Shape::Shape(std::initializer_list &&l) : _dims{l} { // DO NOTHING } -uint32_t Shape::rank(void) const { return _dims.size(); } -Shape &Shape::resize(uint32_t size) +int32_t Shape::rank() const { return _dims.size(); } +Shape &Shape::resize(int32_t size) { _dims.resize(size); return *this; } -uint32_t &Shape::dim(uint32_t axis) { return _dims.at(axis); } -uint32_t Shape::dim(uint32_t axis) const { return _dims.at(axis); } +int32_t &Shape::dim(int32_t axis) +{ + return _dims.at((axis < 0) ? (_dims.size() + axis) : axis); +} -Shape &Shape::squeeze(void) +int32_t Shape::dim(int32_t axis) const { - _dims.erase(std::remove(_dims.begin(), _dims.end(), 1), _dims.end()); - return *this; + return _dims.at((axis < 0) ? (_dims.size() + axis) : axis); } -uint64_t num_elements(const Shape &shape) +int32_t Shape::numElements() const { - if (shape.rank() == 0) + if (rank() == 0) { return 0; } - uint64_t res = 1; + int32_t res = 1; - for (uint32_t axis = 0; axis < shape.rank(); ++axis) + for (int32_t axis = 0; axis < rank(); ++axis) { - res *= shape.dim(axis); + assert(dim(axis) != Shape::AUTO_DIM); + res *= dim(axis); } return res; } -Shape squeeze(const Shape &shape) -{ - Shape res{shape}; - res.squeeze(); - return res; -} - -bool operator==(const Shape &lhs, const Shape &rhs) +bool Shape::equal(const Shape &rhs) const { - if (lhs.rank() != rhs.rank()) + if (rank() != rhs.rank()) { return false; } - for (uint32_t axis = 0; axis < lhs.rank(); ++axis) + int32_t r = rank(); + for (int32_t axis = 0; axis < r; ++axis) { - if (lhs.dim(axis) != rhs.dim(axis)) + if (dim(axis) != rhs.dim(axis)) { return false; } @@ -88,14 +85,17 @@ bool operator==(const Shape &lhs, const Shape &rhs) std::ostream &operator<<(std::ostream &s, const Shape &sh) { - uint32_t rank = sh.rank(); + int32_t rank = sh.rank(); s << "["; - for (uint32_t axis = 0; axis < rank; ++axis) + for (int32_t axis = 0; axis < rank; ++axis) { if (axis != 0) s << ", "; - s << sh.dim(axis); + if (sh.dim(axis) == Shape::AUTO_DIM) + s << "AUTO"; + else + s << sh.dim(axis); } s << "]"; return s; diff --git a/contrib/nnc/core/modelIR/ShapeInference.cpp b/contrib/nnc/core/modelIR/ShapeInference.cpp index a3e29ae..ef6add9 100644 --- a/contrib/nnc/core/modelIR/ShapeInference.cpp +++ b/contrib/nnc/core/modelIR/ShapeInference.cpp @@ -52,7 +52,7 @@ void fillHWShapesForPaddedOperations(Op &op, const Shape &windowShape, Shape &ou switch (pType) { case ops::PaddingType::Same: - for (uint32_t d = 0; d < inRank - 1; ++d) + for (int32_t d = 0; d < inRank - 1; ++d) { outShape.dim(d) = (inShape.dim(d) - 1) / strides.dim(d) + 1; int pad_along_axis; @@ -70,13 +70,13 @@ void fillHWShapesForPaddedOperations(Op &op, const Shape &windowShape, Shape &ou } break; case ops::PaddingType::Valid: - for (uint32_t d = 0; d < inRank - 1; ++d) + for (int32_t d = 0; d < inRank - 1; ++d) { op.setPadding(d, 0); } // FALLTHROUGH case ops::PaddingType::Custom: - for (uint32_t d = 0; d < inRank - 1; ++d) + for (int32_t d = 0; d < inRank - 1; ++d) { outShape.dim(d) = (inShape.dim(d) + 2*op.getPadding(d) - windowShape.dim(d)) / strides.dim(d) + 1; } @@ -93,17 +93,17 @@ void ShapeInference::visit(INode::Ref node, ops::ConcatOp &op) { fillInputShapes(node, op); - uint32_t axis = op.getAxis(); + int32_t axis = op.getAxis(); Shape outShape; outShape.resize(op.getInputShape(0).rank()); - for (uint32_t d = 0; d < outShape.rank(); ++d) + for (int32_t d = 0; d < outShape.rank(); ++d) { outShape.dim(d) = op.getInputShape(0).dim(d); } outShape.dim(axis) = 0; - for (uint32_t i = 0; i < op.getNumInputs(); ++i) + for (size_t i = 0; i < op.getNumInputs(); ++i) { outShape.dim(axis) += op.getInputShape(i).dim(axis); } @@ -134,7 +134,7 @@ void ShapeInference::visit(INode::Ref node, ops::VariableOp &op) void ShapeInference::fillInputShapes(INode::Ref node, OpDescription &op) { - uint32_t i = 0; + size_t i = 0; for (auto &in : node->getPrevNodes()) { const Shape &inShape = in.node->getOperation()->getOutputShape(in.index); @@ -161,7 +161,7 @@ void ShapeInference::visit(INode::Ref node, ops::PoolOp &op) Shape outShape; auto &windowShape = op.getWindowShape(); auto &inShape = op.getInputShape(0); - const uint32_t inRank = inShape.rank(); + const int32_t inRank = inShape.rank(); // Assuming input tensor is 3-dimensional. Will support more general cases when needed. assert(inRank == 3); @@ -176,13 +176,14 @@ void ShapeInference::visit(INode::Ref node, ops::FullyConnectedOp &op) fillInputShapes(node, op); const Shape &inShape = op.getInputShape(0); const Shape &wShape = op.getWeights().getShape(); - const uint32_t weightsRank = wShape.rank(); - const uint32_t inRank = inShape.rank(); + const int32_t weightsRank = wShape.rank(); + const int32_t inRank = inShape.rank(); assert(weightsRank >= 2); assert(inRank == weightsRank); assert(inShape.dim(inRank - 1) == wShape.dim(weightsRank - 2)); - for (uint32_t i = 0; i < weightsRank - 2; ++i) + (void)inRank; + for (int32_t i = 0; i < weightsRank - 2; ++i) { assert(wShape.dim(i) == inShape.dim(i)); } @@ -232,20 +233,20 @@ void ShapeInference::visit(INode::Ref node, ops::ReshapeOp &op) auto& inShape = op.getInputShape(0); auto outShape = op.getOutputShape(0); - auto inElementsNum = num_elements(inShape); - uint32_t outElementsNum = 1; + auto inElementsNum = inShape.numElements(); + int32_t outElementsNum = 1; //can't use num_elements due to -1 in input shape and Shape using unsigned ints for dimensions - for( uint32_t d = 0; d < outShape.rank(); ++d ) { + for( int32_t d = 0; d < outShape.rank(); ++d ) { auto dim = outShape.dim(d); - if( dim != AUTO_DIM) { + if( dim != Shape::AUTO_DIM) { outElementsNum *= dim; } } - for( uint32_t d = 0; d < outShape.rank(); ++d ) { + for( int32_t d = 0; d < outShape.rank(); ++d ) { auto& dim = outShape.dim(d); - if( dim == AUTO_DIM ) { - dim = static_cast(inElementsNum / outElementsNum); + if( dim == Shape::AUTO_DIM ) { + dim = static_cast(inElementsNum / outElementsNum); } } diff --git a/contrib/nnc/include/core/modelIR/ExternalRegion.h b/contrib/nnc/include/core/modelIR/ExternalRegion.h index a5d94ec..f0c2252 100644 --- a/contrib/nnc/include/core/modelIR/ExternalRegion.h +++ b/contrib/nnc/include/core/modelIR/ExternalRegion.h @@ -27,18 +27,18 @@ namespace mir template class ExternalRegion final : public Region { public: - ExternalRegion(T *base, uint32_t size) : _base{base}, _size{size} + ExternalRegion(T *base, int32_t size) : _base{base}, _size{size} { // DO NOTHING } public: - T *base(void) override { return _base; } - uint32_t size(void) const override { return _size; } + T *base() override { return _base; } + int32_t size() const override { return _size; } private: T *const _base; - uint32_t const _size; + int32_t const _size; }; } // namespace mir diff --git a/contrib/nnc/include/core/modelIR/Index.h b/contrib/nnc/include/core/modelIR/Index.h index 4319858..cf39585 100644 --- a/contrib/nnc/include/core/modelIR/Index.h +++ b/contrib/nnc/include/core/modelIR/Index.h @@ -31,23 +31,19 @@ class Index { public: Index() = default; - Index(std::initializer_list &&l); + Index(std::initializer_list &&l); -public: - uint32_t rank(void) const; + int32_t rank(void) const; -public: - Index &resize(uint32_t size); + Index &resize(int32_t size); -public: - Index &fill(uint32_t index); + Index &fill(int32_t index); -public: - uint32_t &at(uint32_t axis); - uint32_t at(uint32_t axis) const; + int32_t &at(int32_t axis); + int32_t at(int32_t axis) const; private: - std::vector _indices; + std::vector _indices; }; std::ostream &operator<<(std::ostream &s, const Index &sh); diff --git a/contrib/nnc/include/core/modelIR/Region.h b/contrib/nnc/include/core/modelIR/Region.h index 96978bc..af3fd43 100644 --- a/contrib/nnc/include/core/modelIR/Region.h +++ b/contrib/nnc/include/core/modelIR/Region.h @@ -18,6 +18,7 @@ #define _NNC_CORE_LINALG_REGION_H_ #include +#include "Shape.h" namespace nnc { @@ -29,9 +30,9 @@ struct Region { virtual ~Region() = default; - virtual T *base(void) = 0; + virtual T *base() = 0; - virtual uint32_t size(void) const = 0; + virtual int32_t size() const = 0; }; } // namespace mir diff --git a/contrib/nnc/include/core/modelIR/Shape.h b/contrib/nnc/include/core/modelIR/Shape.h index 5839e78..fe40b3c 100644 --- a/contrib/nnc/include/core/modelIR/Shape.h +++ b/contrib/nnc/include/core/modelIR/Shape.h @@ -30,31 +30,37 @@ namespace mir class Shape { public: + static const auto AUTO_DIM = static_cast(-1); + Shape() = default; - Shape(std::initializer_list &&l); + Shape(std::initializer_list &&l); -public: - uint32_t rank(void) const; + int32_t rank() const; -public: - Shape &resize(uint32_t size); + Shape &resize(int32_t size); -public: - uint32_t &dim(uint32_t axis); - uint32_t dim(uint32_t axis) const; + int32_t &dim(int32_t axis); + int32_t dim(int32_t axis) const; -public: - Shape &squeeze(void); + int32_t numElements() const; + + bool operator==(const Shape& rhs) const + { + return equal(rhs); + } + + bool operator!=(const Shape& rhs) const + { + return !equal(rhs); + } private: - std::vector _dims; -}; -uint64_t num_elements(const Shape &); + bool equal(const Shape& rhs) const; -Shape squeeze(const Shape &); + std::vector _dims; +}; -bool operator==(const Shape &, const Shape &); std::ostream &operator<<(std::ostream &s, const Shape &sh); } // namespace mir diff --git a/contrib/nnc/include/core/modelIR/ShapeInference.h b/contrib/nnc/include/core/modelIR/ShapeInference.h index 7e37f07..e50752c 100644 --- a/contrib/nnc/include/core/modelIR/ShapeInference.h +++ b/contrib/nnc/include/core/modelIR/ShapeInference.h @@ -28,8 +28,6 @@ namespace mir class ShapeInference : public IVisitor { public: - static const auto AUTO_DIM = std::numeric_limits::max(); - void visit(INode::Ref node, ops::ConcatOp &op) override; void visit(INode::Ref node, ops::Conv2DOp &op) override; void visit(INode::Ref node, ops::DepthwiseConv2DOp &op) override; diff --git a/contrib/nnc/include/core/modelIR/ShapeRange.h b/contrib/nnc/include/core/modelIR/ShapeRange.h index 882fb25..fb7f05e 100644 --- a/contrib/nnc/include/core/modelIR/ShapeRange.h +++ b/contrib/nnc/include/core/modelIR/ShapeRange.h @@ -33,8 +33,8 @@ class ShapeIter : ShapeIter& operator++() { auto* pidx = &_index.at(0); auto* pshape = &_shape.dim(0); - auto rank = _shape.rank(); - int c = rank - 1; + int32_t rank = _shape.rank(); + int32_t c = rank - 1; pidx[c]++; while( (pidx[c] > pshape[c] - 1) && (c > 0) ) { pidx[c] = 0; @@ -61,12 +61,12 @@ class ShapeIter : } private: - explicit ShapeIter(Shape &_shape, uint32_t pos) : _pos(pos), _shape(_shape) { + explicit ShapeIter(Shape &_shape, int32_t pos) : _pos(pos), _shape(_shape) { _index.resize(_shape.rank()); _index.fill(0); } - uint32_t _pos; + int32_t _pos; Index _index; Shape& _shape; @@ -83,18 +83,16 @@ class ShapeRange { } ShapeIter end() { - uint32_t _end = 1; - for( uint32_t d = 0; d < _shape.rank(); ++d ) _end *= _shape.dim(d); - return ShapeIter(_shape, _end); + return ShapeIter(_shape, _shape.numElements()); } bool contains(const Index& idx) { assert(idx.rank() == _shape.rank()); - bool res = true; - for(uint32_t d = 0; d < idx.rank(); ++d ) { - res &= idx.at(d) < _shape.dim(d); + for(int32_t d = 0; d < idx.rank(); ++d ) { + if ((idx.at(d) >= _shape.dim(d)) || (idx.at(d) < 0)) + return false; } - return res; + return true; } private: diff --git a/contrib/nnc/include/core/modelIR/TensorUtil.h b/contrib/nnc/include/core/modelIR/TensorUtil.h index 0037229..14d7831 100644 --- a/contrib/nnc/include/core/modelIR/TensorUtil.h +++ b/contrib/nnc/include/core/modelIR/TensorUtil.h @@ -37,7 +37,7 @@ transposeTensor(std::shared_ptr tensor) const Shape &inShape = tensor->getShape(); Shape targetShape{inShape.dim(Ints)...}; - uint64_t size = num_elements(targetShape); + auto size = targetShape.numElements(); std::shared_ptr convertedTensorData(new char[size * tensor->getElementSize()], [](char *d) { delete[] d; }); diff --git a/contrib/nnc/include/core/modelIR/TensorVariant.h b/contrib/nnc/include/core/modelIR/TensorVariant.h index 3c6d510..b53431c 100644 --- a/contrib/nnc/include/core/modelIR/TensorVariant.h +++ b/contrib/nnc/include/core/modelIR/TensorVariant.h @@ -62,7 +62,7 @@ public: private: DTYPE _dtype; std::shared_ptr _data; - uint_fast32_t _strides[MAX_DIMENSIONS]; + int_fast32_t _strides[MAX_DIMENSIONS]; size_t _rank; Shape _shape; diff --git a/contrib/nnc/include/core/modelIR/operations/concat_op.h b/contrib/nnc/include/core/modelIR/operations/concat_op.h index 22b3ab5..3ad4c55 100644 --- a/contrib/nnc/include/core/modelIR/operations/concat_op.h +++ b/contrib/nnc/include/core/modelIR/operations/concat_op.h @@ -17,7 +17,10 @@ #ifndef _NNC_CORE_IR_MODEL_CONCAT_OP_H_ #define _NNC_CORE_IR_MODEL_CONCAT_OP_H_ +#include + #include "core/modelIR/operations/operation.h" +#include "core/modelIR/Shape.h" namespace nnc { @@ -26,18 +29,21 @@ namespace mir namespace ops { +/** + * @brief Description of tensor concatenation operation. + */ class ConcatOp : public OpDescription { public: - ConcatOp(int num_inputs, int axis) : OpDescription(num_inputs, 1), _axis(axis) {} + ConcatOp(int num_inputs, int32_t axis) : OpDescription(num_inputs, 1), _axis(axis) {} - unsigned int getAxis() const + int32_t getAxis() const { if (_axis < 0) { // Negative axis is used to index starting from the last element of the shape // -1 means last element, -2 means second from end, like in python - int res = _axis + getInputShape(0).rank(); + int32_t res = _axis + getInputShape(0).rank(); assert(res >= 0); return res; } @@ -45,7 +51,8 @@ public: } private: - int _axis; + /// @brief The axis along which to concatenate, may be negative to index from the end + int32_t _axis; }; } // namespace ops diff --git a/contrib/nnc/include/core/modelIR/operations/conv_2d_op.h b/contrib/nnc/include/core/modelIR/operations/conv_2d_op.h index c80c718..b99de46 100644 --- a/contrib/nnc/include/core/modelIR/operations/conv_2d_op.h +++ b/contrib/nnc/include/core/modelIR/operations/conv_2d_op.h @@ -48,15 +48,15 @@ public: PaddingType getPaddingType() const { return _padding; } - int getPadding(int dim) const { return _pads[dim]; } + int32_t getPadding(int32_t dim) const { return _pads[dim]; } - void setPadding(int dim, int pad) { _pads[dim] = pad; } + void setPadding(int32_t dim, int32_t pad) { _pads[dim] = pad; } private: const TensorVariant _kernel; Shape _strides; PaddingType _padding; - std::vector _pads; + std::vector _pads; }; } // namespace ops diff --git a/contrib/nnc/include/core/modelIR/operations/depthwise_conv2d_op.h b/contrib/nnc/include/core/modelIR/operations/depthwise_conv2d_op.h index 2c63cf5..04d00d3 100644 --- a/contrib/nnc/include/core/modelIR/operations/depthwise_conv2d_op.h +++ b/contrib/nnc/include/core/modelIR/operations/depthwise_conv2d_op.h @@ -47,15 +47,15 @@ public: PaddingType getPaddingType() const { return _padding; } - int getPadding(int dim) const { return _pads[dim]; } + int32_t getPadding(int32_t dim) const { return _pads[dim]; } - void setPadding(int dim, int pad) { _pads[dim] = pad; } + void setPadding(int32_t dim, int32_t pad) { _pads[dim] = pad; } private: const TensorVariant _kernel; Shape _strides; PaddingType _padding; - std::vector _pads; + std::vector _pads; }; } // namespace ops diff --git a/contrib/nnc/include/core/modelIR/operations/pool_op.h b/contrib/nnc/include/core/modelIR/operations/pool_op.h index adc0d53..8dda6cb 100644 --- a/contrib/nnc/include/core/modelIR/operations/pool_op.h +++ b/contrib/nnc/include/core/modelIR/operations/pool_op.h @@ -65,9 +65,9 @@ public: const Shape &getStrides() const { return _strides; } - int getPadding(int dim) const { return _pads[dim]; } + int32_t getPadding(int32_t dim) const { return _pads[dim]; } - void setPadding(int dim, int pad) { _pads[dim] = pad; } + void setPadding(int32_t dim, int32_t pad) { _pads[dim] = pad; } private: PaddingType _padding; @@ -75,7 +75,7 @@ private: BorderType _borderType; Shape _windowShape; Shape _strides; - std::vector _pads; + std::vector _pads; }; } // namespace ops diff --git a/contrib/nnc/include/core/modelIR/operations/softmax_op.h b/contrib/nnc/include/core/modelIR/operations/softmax_op.h index 9334692..934e445 100644 --- a/contrib/nnc/include/core/modelIR/operations/softmax_op.h +++ b/contrib/nnc/include/core/modelIR/operations/softmax_op.h @@ -18,6 +18,7 @@ #define _NNC_CORE_IR_MODEL_SOFTMAX_H_ #include "core/modelIR/operations/operation.h" +#include "core/modelIR/Shape.h" namespace nnc { @@ -26,18 +27,21 @@ namespace mir namespace ops { +/** + * @brief description of softmax operation. + */ class SoftmaxOp : public OpDescription { public: - explicit SoftmaxOp(int axis) : OpDescription(1, 1), _axis(axis) {} + explicit SoftmaxOp(int32_t axis) : OpDescription(1, 1), _axis(axis) {} - int getAxis() const + int32_t getAxis() const { if (_axis < 0) { // Negative axis is used to index starting from the last element of the shape // -1 means last element, -2 means second from end, like in python - int res = _axis + getInputShape(0).rank(); + int32_t res = _axis + getInputShape(0).rank(); assert(res >= 0); return res; } @@ -45,7 +49,8 @@ public: } private: - int _axis; + /// @brief The axis along which to concatenate, may be negative to index from the end + int32_t _axis; }; } // namespace ops diff --git a/contrib/nnc/include/pass/PassException.h b/contrib/nnc/include/pass/PassException.h index 4c56083..54a99ab 100644 --- a/contrib/nnc/include/pass/PassException.h +++ b/contrib/nnc/include/pass/PassException.h @@ -30,10 +30,10 @@ class PassException : public std::exception { public: PassException() = default; - PassException(const PassException &) noexcept {}; + PassException(const PassException &) = default; - PassException(const std::string &msg) : _msg(msg) {}; - PassException(const char *msg) : _msg(msg) {}; + explicit PassException(const std::string &msg) : _msg(msg) {}; + explicit PassException(const char *msg) : _msg(msg) {}; /** * @brief get message describes reason why exception was thrown diff --git a/contrib/nnc/include/passes/common_frontend/shape_helper.h b/contrib/nnc/include/passes/common_frontend/shape_helper.h index 8250ee0..e7d6f84 100644 --- a/contrib/nnc/include/passes/common_frontend/shape_helper.h +++ b/contrib/nnc/include/passes/common_frontend/shape_helper.h @@ -35,7 +35,7 @@ template mir::Shape ShapeHelper::createShape(const Iterable &iter, std::size_t size) { mir::Shape sh; - sh.resize(static_cast(size)); + sh.resize(static_cast(size)); unsigned int i = 0; for (auto dim : iter) diff --git a/contrib/nnc/include/support/CommandLine.h b/contrib/nnc/include/support/CommandLine.h index 9672501..45a233c 100644 --- a/contrib/nnc/include/support/CommandLine.h +++ b/contrib/nnc/include/support/CommandLine.h @@ -493,11 +493,13 @@ Option::Option(const std::vector &optnames, this->setRawValue(default_val); +#ifndef NDEBUG // check that separators are valid symbols for ( const auto &s : _seps ) { assert((s == '=' || s == ':') && "invalid option separators"); } +#endif // NDEBUG // save checker _checker = checker; diff --git a/contrib/nnc/passes/caffe_frontend/caffe_op_creator.cpp b/contrib/nnc/passes/caffe_frontend/caffe_op_creator.cpp index 2bba6d2..a5ee162 100644 --- a/contrib/nnc/passes/caffe_frontend/caffe_op_creator.cpp +++ b/contrib/nnc/passes/caffe_frontend/caffe_op_creator.cpp @@ -58,11 +58,11 @@ static inline bool has2DStride(const OptsType& opts) return opts.has_stride_h(); } -static inline Shape getStrideFromOneValue(bool hasStride, unsigned int stride) +static inline Shape getStrideFromOneValue(bool hasStride, uint32_t stride) { if (hasStride) { - return Shape{stride, stride, 1}; + return Shape{static_cast(stride), static_cast(stride), 1}; } else { @@ -70,9 +70,9 @@ static inline Shape getStrideFromOneValue(bool hasStride, unsigned int stride) } } -static inline Shape getStrideFromTwoValues(unsigned int stride1, unsigned int stride2) +static inline Shape getStrideFromTwoValues(uint32_t stride1, uint32_t stride2) { - return Shape{stride1, stride2, 1}; + return Shape{static_cast(stride1), static_cast(stride2), 1}; } template @@ -124,11 +124,11 @@ __attribute__ ((unused)) static Shape getPoolWindowShape(const PoolingParameter if (opts.has_kernel_h()) { - return Shape{opts.kernel_h(), opts.kernel_w(), 1}; + return Shape{static_cast(opts.kernel_h()), static_cast(opts.kernel_w()), 1}; } else if (opts.has_kernel_size()) { - return Shape{opts.kernel_size(), opts.kernel_size(), 1}; + return Shape{static_cast(opts.kernel_size()), static_cast(opts.kernel_size()), 1}; } else { @@ -207,7 +207,7 @@ static std::shared_ptr fixGroupedKernel(int groups, std::shared_ptrgetElementSize(); + auto bufferSize = unfoldKernelShape.numElements() * foldedKernel->getElementSize(); std::shared_ptr buffer(new char[bufferSize], std::default_delete()); size_t dataSize = foldedKernel->getElementSize(); std::shared_ptr unfoldKernel = @@ -314,8 +314,8 @@ std::vector OpCreator::createFullyConnected(InputOps &inputs, InputP // Add Reshape operation to make sure the input for FC operation has shape [1, fcInputSize] // It is needed because Caffe InnerProduct layer takes NCHW input and flattens the CHW part. auto outputs = createOp(inputs); - uint32_t fcInputSize = static_cast( - num_elements(params[0]->getShape())) / opts.num_output(); + int32_t fcInputSize = static_cast( + params[0]->getShape().numElements()) / opts.num_output(); outputs[0]->getOperation()->setOutputShape(0, {1, fcInputSize}); auto fcOutputs = createOp(outputs, std::move(*params[0])); @@ -415,7 +415,7 @@ std::vector OpCreator::createReshape(InputOps inputs, InputParams pa Shape newShape = ShapeHelper::createShape(opts.shape().dim(), opts.shape().dim_size()); - for (unsigned int i = 0; i < newShape.rank(); ++i) + for (int32_t i = 0; i < newShape.rank(); ++i) { if (newShape.dim(i) == 0) throw PassException("Reshape layer zero shape values are not supported yet"); diff --git a/contrib/nnc/passes/common_frontend/shape_helper.cpp b/contrib/nnc/passes/common_frontend/shape_helper.cpp index d3d2c25..69605ff 100644 --- a/contrib/nnc/passes/common_frontend/shape_helper.cpp +++ b/contrib/nnc/passes/common_frontend/shape_helper.cpp @@ -33,7 +33,7 @@ mir::Shape &ShapeHelper::cutOffBatchDim(mir::Shape &shape) "code needs some restructuring"}; } - for (unsigned int i = 0; i < shape.rank() - 1; ++i) + for (int32_t i = 0; i < shape.rank() - 1; ++i) { shape.dim(i) = shape.dim(i + 1); } diff --git a/contrib/nnc/passes/interpreter/interpreter_pass.cpp b/contrib/nnc/passes/interpreter/interpreter_pass.cpp index b2cf753..358c112 100644 --- a/contrib/nnc/passes/interpreter/interpreter_pass.cpp +++ b/contrib/nnc/passes/interpreter/interpreter_pass.cpp @@ -64,10 +64,10 @@ static void writeTensorToHDF5File(TensorVariant *tensor, std::string tensorName, { // Prepare shape, rank, dims, numElems Shape shape = tensor->getShape(); - const auto rank = shape.rank(); + const int32_t rank = shape.rank(); hsize_t dims[rank]; - uint64_t numElems = 1; - for (uint32_t axis = 0; axis < rank; ++axis) { + size_t numElems = 1; + for (int32_t axis = 0; axis < rank; ++axis) { dims[axis] = shape.dim(axis); numElems *= shape.dim(axis); } @@ -153,8 +153,8 @@ TensorVariant InterpreterPass::loadInput(const Shape &shape) int is_error = fseek(f, 0L, SEEK_END); assert(!is_error); - auto len = ftell(f); - auto tensorSize = num_elements(shape) * sizeof(float); + auto len = static_cast(ftell(f)); + auto tensorSize = static_cast(shape.numElements() * sizeof(float)); // Check size if (len != tensorSize) { @@ -167,6 +167,7 @@ TensorVariant InterpreterPass::loadInput(const Shape &shape) auto data = new char[len]; auto rlen = fread(data, len, 1, f); assert(rlen == 1); + (void)rlen; is_error = fclose(f); assert(is_error != EOF && "Can not close file!"); (void)is_error; diff --git a/contrib/nnc/passes/interpreter/ops/Concat.h b/contrib/nnc/passes/interpreter/ops/Concat.h index 518b040..998d363 100644 --- a/contrib/nnc/passes/interpreter/ops/Concat.h +++ b/contrib/nnc/passes/interpreter/ops/Concat.h @@ -26,14 +26,14 @@ template class Concat : public Fill { public: explicit Concat(const std::vector &inputs, const mir::Shape &outputShape, - unsigned int axis) + int32_t axis) : Fill(outputShape, getSingleFunction(inputs, axis)) { } private: const std::function getSingleFunction(const std::vector &inputs, - unsigned int axis) + int32_t axis) { std::vector> inputAccessors; for (auto &in : inputs) @@ -43,7 +43,7 @@ private: return std::function([inputAccessors, axis](const mir::Index &id) -> T { unsigned int mi = 0; - uint32_t along_axis = id.at(axis); + int32_t along_axis = id.at(axis); while (along_axis >= inputAccessors.at(mi).getShape().dim(axis)) { diff --git a/contrib/nnc/passes/interpreter/ops/Depthwise_conv_2D.cpp b/contrib/nnc/passes/interpreter/ops/Depthwise_conv_2D.cpp index cb77bff..a712fae 100644 --- a/contrib/nnc/passes/interpreter/ops/Depthwise_conv_2D.cpp +++ b/contrib/nnc/passes/interpreter/ops/Depthwise_conv_2D.cpp @@ -31,7 +31,7 @@ std::vector DepthwiseConv2D::operator()() Tensor resAccessor(res); Shape strides({_strides.dim(0), _strides.dim(1), _strides.dim(2)}); - Index pads({(uint32_t)_op.getPadding(0), (uint32_t)_op.getPadding(1), 0u}); + Index pads({_op.getPadding(0), _op.getPadding(1), 0u}); Shape outShape = res.getShape(); outShape.dim(2) = 1; @@ -43,7 +43,7 @@ std::vector DepthwiseConv2D::operator()() inIdx.resize(outShape.rank()); auto kernelShape = _kernel.getShape(); - uint32_t channelMultiplierDim = kernelShape.rank() - 1; + int32_t channelMultiplierDim = kernelShape.rank() - 1; int channelMultiplier = kernelShape.dim(channelMultiplierDim); for (auto &outIdx : outRange) diff --git a/contrib/nnc/passes/interpreter/ops/FullyConnected.h b/contrib/nnc/passes/interpreter/ops/FullyConnected.h index 2cf882e..0ff905e 100644 --- a/contrib/nnc/passes/interpreter/ops/FullyConnected.h +++ b/contrib/nnc/passes/interpreter/ops/FullyConnected.h @@ -39,24 +39,25 @@ public: mir::Tensor weights(_op.getWeights()); const mir::Shape &wShape = weights.getShape(); - uint32_t wRank = wShape.rank(); + int32_t wRank = wShape.rank(); const mir::Shape &inShape = _input.getShape(); - uint32_t inRank = inShape.rank(); + int32_t inRank = inShape.rank(); assert(inShape.dim(inRank - 1) == wShape.dim(wRank - 2)); + (void)inRank; - const uint32_t len = wShape.dim(wRank - 2); + const auto len = wShape.dim(wRank - 2); - uint32_t row; - uint32_t col; + int32_t row; + int32_t col; for (auto &outIdx : outRange) { mir::Index tIdx = outIdx; T& outputElement = accessor.at(outIdx); col = tIdx.at(wRank - 1); row = tIdx.at(wRank - 2); - for (uint32_t i = 0u; i < len; ++i) + for (int32_t i = 0; i < len; ++i) { tIdx.at(wRank - 1) = i; const T& in = _input.at(tIdx); diff --git a/contrib/nnc/passes/interpreter/ops/OperationImpl.h b/contrib/nnc/passes/interpreter/ops/OperationImpl.h index 9ab4753..bf91d2f 100644 --- a/contrib/nnc/passes/interpreter/ops/OperationImpl.h +++ b/contrib/nnc/passes/interpreter/ops/OperationImpl.h @@ -36,7 +36,7 @@ protected: mir::TensorVariant allocate_tensor(const mir::Shape &shape) { size_t data_size = 1; - for (uint32_t i = 0; i < shape.rank(); ++i) + for (int32_t i = 0; i < shape.rank(); ++i) { data_size *= shape.dim(i); } diff --git a/contrib/nnc/passes/interpreter/ops/Pool.cpp b/contrib/nnc/passes/interpreter/ops/Pool.cpp index 35fa789..7e2adee 100644 --- a/contrib/nnc/passes/interpreter/ops/Pool.cpp +++ b/contrib/nnc/passes/interpreter/ops/Pool.cpp @@ -39,14 +39,14 @@ std::vector Pool::operator()() Tensor resAccessor(res); Shape strides({_op.getStrides().dim(0), _op.getStrides().dim(1), 1u}); - Index pads({(uint32_t)_op.getPadding(0), (uint32_t)_op.getPadding(1), 0u}); + Index pads({_op.getPadding(0), _op.getPadding(1), 0u}); const Shape &outShape = resAccessor.getShape(); ShapeRange outRange(outShape); ShapeRange inRange(_input.getShape()); - float initialValue; + float initialValue = 0.0f; switch (_op.getPoolingType()) { case PoolOp::PoolingType::MAX: @@ -69,7 +69,7 @@ std::vector Pool::operator()() { translate(inIdx, outIdx, kIdx, strides, pads); - float in; + float in = 0.0f; if(inRange.contains(inIdx)) { avgDenominator++; in = _input.at(inIdx); @@ -110,7 +110,12 @@ float Pool::poolingFunc(float prev, float val) return prev + val; case PoolOp::PoolingType::MIN: return (val < prev) ? val : prev; + default: + assert(false && "Unsupported pooling type"); } + // This should not happen + // Should throw, but it is too expensive + return 0.0f; } } // namespace nnc diff --git a/contrib/nnc/passes/interpreter/ops/Reduce.h b/contrib/nnc/passes/interpreter/ops/Reduce.h index 18900de..d5485f9 100644 --- a/contrib/nnc/passes/interpreter/ops/Reduce.h +++ b/contrib/nnc/passes/interpreter/ops/Reduce.h @@ -32,7 +32,7 @@ namespace nnc template class Reduce : public OperationImpl { public: - Reduce(const mir::Shape &inputShape, const mir::Shape &outputShape, const mir::TensorVariant &input, uint32_t axis, + Reduce(const mir::Shape &inputShape, const mir::Shape &outputShape, const mir::TensorVariant &input, int32_t axis, std::function reduceFunc) : _inShape(inputShape), _outputShape(outputShape), _input(input), _axis(axis), _reduceFunc(reduceFunc) @@ -45,8 +45,8 @@ public: return Fill(_outputShape, [this](const mir::Index &id) { T element = T(); mir::Index inputId = id; - uint32_t end = _inShape.dim(_axis); - for (uint32_t i = 0; i < end; ++i) + int32_t end = _inShape.dim(_axis); + for (int32_t i = 0; i < end; ++i) { inputId.at(_axis) = i; element = _reduceFunc(element, _input.at(inputId)); @@ -59,7 +59,7 @@ private: const mir::Shape &_inShape; const mir::Shape &_outputShape; const mir::Tensor _input; - const uint32_t _axis; + const int32_t _axis; const std::function _reduceFunc; }; diff --git a/contrib/nnc/passes/interpreter/ops/Reshape.h b/contrib/nnc/passes/interpreter/ops/Reshape.h index bba1d8a..87515f8 100644 --- a/contrib/nnc/passes/interpreter/ops/Reshape.h +++ b/contrib/nnc/passes/interpreter/ops/Reshape.h @@ -30,7 +30,7 @@ template class Reshape : public OperationImpl public: Reshape(const mir::TensorVariant &input, const mir::ops::ReshapeOp &op) : _input(input), _op(op) { - assert(num_elements(_op.getInputShape(0)) == num_elements(_op.getOutputShape(0))); + assert(_op.getInputShape(0).numElements() == _op.getOutputShape(0).numElements()); } std::vector operator()() override diff --git a/contrib/nnc/passes/interpreter/ops/Softmax.h b/contrib/nnc/passes/interpreter/ops/Softmax.h index 0a52d6d..42545e0 100644 --- a/contrib/nnc/passes/interpreter/ops/Softmax.h +++ b/contrib/nnc/passes/interpreter/ops/Softmax.h @@ -32,7 +32,7 @@ namespace nnc class Softmax : public OperationImpl { public: - Softmax(const mir::Shape &inputShape, const mir::TensorVariant &input, uint32_t axis) + Softmax(const mir::Shape &inputShape, const mir::TensorVariant &input, int32_t axis) : _inShape(inputShape), _axis(axis), _input(input) { } @@ -58,7 +58,7 @@ public: private: const mir::Shape &_inShape; - const uint32_t _axis; + const int32_t _axis; const mir::TensorVariant _input; }; diff --git a/contrib/nnc/passes/interpreter/ops/common.cpp b/contrib/nnc/passes/interpreter/ops/common.cpp index b9b9f17..76d0af0 100644 --- a/contrib/nnc/passes/interpreter/ops/common.cpp +++ b/contrib/nnc/passes/interpreter/ops/common.cpp @@ -28,7 +28,7 @@ void translate(Index &translatedIndex, const Index &sourceIndex, const Index &ke { assert(translatedIndex.rank() == sourceIndex.rank()); - for (uint32_t d = 0; d < translatedIndex.rank(); ++d) + for (int32_t d = 0; d < translatedIndex.rank(); ++d) { translatedIndex.at(d) = sourceIndex.at(d) * strides.dim(d) + kernelIndex.at(d) - paddings.at(d); } diff --git a/contrib/nnc/passes/interpreter/ops/conv_2D.cpp b/contrib/nnc/passes/interpreter/ops/conv_2D.cpp index dfc9a5a..8d74e89 100644 --- a/contrib/nnc/passes/interpreter/ops/conv_2D.cpp +++ b/contrib/nnc/passes/interpreter/ops/conv_2D.cpp @@ -42,7 +42,7 @@ std::vector Conv2D::operator()() { auto res = allocate_tensor(_out_shape); Tensor resAccesor(res); - Index pads({(uint32_t)_op.getPadding(0), (uint32_t)_op.getPadding(1), 0u}); + Index pads({_op.getPadding(0), _op.getPadding(1), 0u}); Shape outShape = resAccesor.getShape(); outShape.dim(2) = 1; @@ -52,7 +52,7 @@ std::vector Conv2D::operator()() ShapeRange inRange(_input.getShape()); Shape kShape = _kernel.getShape(); - uint32_t numKernels = kShape.dim(3); + int32_t numKernels = kShape.dim(3); kShape.dim(3) = 1; ShapeRange kernelRange(kShape); @@ -75,7 +75,7 @@ std::vector Conv2D::operator()() auto in = _input.at(inputIdx); - for (uint32_t kernelIndex = 0; kernelIndex < numKernels; ++kernelIndex) + for (int32_t kernelIndex = 0; kernelIndex < numKernels; ++kernelIndex) { outRegion.base()[kernelIndex] += in * kernelRegion.base()[kernelIndex]; } diff --git a/contrib/nnc/passes/interpreter/ops/conv_FFT.cpp b/contrib/nnc/passes/interpreter/ops/conv_FFT.cpp index f07f02a..2effd08 100644 --- a/contrib/nnc/passes/interpreter/ops/conv_FFT.cpp +++ b/contrib/nnc/passes/interpreter/ops/conv_FFT.cpp @@ -33,7 +33,7 @@ using namespace mir::ops; // Refer to https://www.tensorflow.org/api_docs/python/tf/nn/conv2d for info std::vector Conv2D_FFT::operator()() { - Index pads({(uint32_t)_op.getPadding(0), (uint32_t)_op.getPadding(1), 0u}); + Index pads({_op.getPadding(0), _op.getPadding(1), 0u}); // // 1. Pad input (currently only with clamp to zero, maybe clamp to edge and wrap later) auto inputPadded = pad_input(pads); @@ -92,8 +92,8 @@ Conv2D_FFT::Conv2D_FFT(const TensorVariant &input, const Conv2DOp &op) std::vector Conv2D_FFT::pad_input(const Index &pads) { // Calculate new shape: just add paddings - uint32_t height = _input.getShape().dim(0), - width = _input.getShape().dim(1); + int32_t height = _input.getShape().dim(0), + width = _input.getShape().dim(1); Shape newShape = _input.getShape(); int rank = newShape.rank(); @@ -144,11 +144,11 @@ std::vector Conv2D_FFT::pad_input(const Index &pads) std::vector> Conv2D_FFT::unpack_and_pad_kernels(const Shape &paddedInputShape, const uint64_t spectreSize) { const Shape &kShape = _kernel.getShape(); - uint32_t numKernels = kShape.dim(3); + int32_t numKernels = kShape.dim(3); // Vector to store results to std::vector> paddedKernels; - for (uint32_t n = 0; n < numKernels; n++) { + for (int32_t n = 0; n < numKernels; n++) { std::vector one_kernel(spectreSize, FFT_complex(0.0f, 0.0f)); paddedKernels.push_back(one_kernel); } @@ -181,10 +181,10 @@ std::vector> Conv2D_FFT::unpack_and_pad_kernels(const S void Conv2D_FFT::elementwise_product(const std::vector &input, std::vector> &kernels) { - uint32_t size = input.size(); + size_t size = input.size(); for (auto &kernel : kernels) { - for (uint32_t i = 0; i < size; i++) + for (size_t i = 0; i < size; i++) { kernel[i] *= input[i]; } @@ -212,12 +212,12 @@ TensorVariant Conv2D_FFT::ifft(std::vector> &spectres, // Move our results to it ShapeRange outRange(outShape); - uint32_t width = inShape.dim(1); + int32_t width = inShape.dim(1); // We have to multiply by number of channels, because // only every first of three elements corresponds to // correct convolution by channels, the rest are // results of shifted convolution - uint32_t inChannels = inShape.dim(2); + int32_t inChannels = inShape.dim(2); for (auto &outIdx : outRange) { resAccessor.at(outIdx) = spectres[outIdx.at(2)][inChannels * ((outIdx.at(0) * strides.dim(0) + paddings.at(0)) * width + @@ -257,7 +257,7 @@ void Conv2D_FFT::fft_CT(FFT_complex* array, separate(array, elements); fft_CT(array, elements / 2); fft_CT(array + elements / 2, elements / 2); - for(int i = 0; i < elements / 2; i++) { + for(size_t i = 0; i < elements / 2; i++) { FFT_complex even = array[i]; FFT_complex odd = array[i + elements / 2]; FFT_complex twiddle = exp(FFT_complex(0, -2. * M_PI * i / elements)); @@ -276,7 +276,7 @@ void Conv2D_FFT::ifft_CT(FFT_complex* array, separate(array, elements); ifft_CT(array, elements / 2); ifft_CT(array + elements / 2, elements / 2); - for(int i = 0; i < elements / 2; i++) { + for(size_t i = 0; i < elements / 2; i++) { FFT_complex even = array[i]; FFT_complex odd = array[i + elements / 2]; FFT_complex twiddle = exp(FFT_complex(0, 2. * M_PI * i / elements)); diff --git a/contrib/nnc/passes/soft_backend/SBSerializer.cpp b/contrib/nnc/passes/soft_backend/SBSerializer.cpp index 85fad32..2ddb8ce 100644 --- a/contrib/nnc/passes/soft_backend/SBSerializer.cpp +++ b/contrib/nnc/passes/soft_backend/SBSerializer.cpp @@ -99,7 +99,7 @@ void Serializer::serializeShape(const Shape &s) for (int32_t i = 0; i < rank; ++i) { int32_t dim = s.dim(i); - serializeT(dim); + serializeT(dim); } } @@ -116,7 +116,7 @@ void Serializer::serializeTensor(const TensorVariant &t) const Shape &shape = t.getShape(); serializeShape(shape); // serialize actual data - size_t tSize = eSize * num_elements(shape); + size_t tSize = eSize * shape.numElements(); size_t oldSize = _buffer.size(); _buffer.reserve(oldSize + tSize); @@ -165,7 +165,7 @@ void Serializer::visit(INode *node, ops::Conv2DOp &op) // serialize strides serializeShape(op.getStrides()); // serialize pads - uint32_t padsRank = op.getInputShape(0).rank(); + int32_t padsRank = op.getInputShape(0).rank(); serializePads(op, padsRank); // serialize output shape serializeShape(op.getOutputShape(0)); @@ -180,7 +180,7 @@ void Serializer::visit(INode *node, ops::DepthwiseConv2DOp &op) // serialize strides serializeShape(op.getStrides()); // serialize pads - uint32_t padsRank = kernel.getShape().rank(); + int32_t padsRank = kernel.getShape().rank(); serializePads(op, padsRank); // serialize output shape serializeShape(op.getOutputShape(0)); @@ -203,7 +203,7 @@ void Serializer::visit(INode *node, ops::PoolOp &op) // serialize strindes serializeShape(op.getStrides()); // serialize pads - uint32_t padsRank = windowShape.rank(); + int32_t padsRank = windowShape.rank(); serializePads(op, padsRank); // serialize border type PoolBorderType borderType; diff --git a/contrib/nnc/passes/soft_backend/code_snippets/cpp_operations.def b/contrib/nnc/passes/soft_backend/code_snippets/cpp_operations.def index a1bc110..b65ff0d 100644 --- a/contrib/nnc/passes/soft_backend/code_snippets/cpp_operations.def +++ b/contrib/nnc/passes/soft_backend/code_snippets/cpp_operations.def @@ -142,6 +142,7 @@ struct Kernel Dims<4> dims; }; +__attribute__((unused)) static bool isAddrAligned(const void *data, int alignment) { return (reinterpret_cast(data) % alignment) == 0; diff --git a/contrib/nnc/passes/tflite_frontend/tflite_dump_visitor.cpp b/contrib/nnc/passes/tflite_frontend/tflite_dump_visitor.cpp index 27d1f84..853d538 100644 --- a/contrib/nnc/passes/tflite_frontend/tflite_dump_visitor.cpp +++ b/contrib/nnc/passes/tflite_frontend/tflite_dump_visitor.cpp @@ -105,7 +105,7 @@ void DumpVisitor::visit(const OperatorCode *oc) static std::ostream &operator<<(std::ostream &os, const flatbuffers::Vector *v) { - for (int i = 0; i < v->size(); ++i) + for (size_t i = 0; i < v->size(); ++i) { if (i != 0) os << ", "; diff --git a/contrib/nnc/passes/tflite_frontend/tflite_ir_visitor.cpp b/contrib/nnc/passes/tflite_frontend/tflite_ir_visitor.cpp index be891ed..a752765 100644 --- a/contrib/nnc/passes/tflite_frontend/tflite_ir_visitor.cpp +++ b/contrib/nnc/passes/tflite_frontend/tflite_ir_visitor.cpp @@ -117,7 +117,7 @@ void IrVisitor::visit(const Operator *op) EnumNamesBuiltinOperator()[opcode]); } - for (int i = 0; i < op->outputs()->size(); ++i) + for (size_t i = 0; i < op->outputs()->size(); ++i) { opsForTensorsTheyOutput[(*(op->outputs()))[i]] = outputs[i]; } diff --git a/contrib/nnc/passes/tflite_frontend/tflite_ir_visitor.h b/contrib/nnc/passes/tflite_frontend/tflite_ir_visitor.h index 2eb3565..e46df17 100644 --- a/contrib/nnc/passes/tflite_frontend/tflite_ir_visitor.h +++ b/contrib/nnc/passes/tflite_frontend/tflite_ir_visitor.h @@ -66,8 +66,8 @@ private: const flatbuffers::Vector> *tensors = nullptr; const flatbuffers::Vector> *buffers = nullptr; - std::vector graphInputs; - std::vector graphOutputs; + std::vector graphInputs; + std::vector graphOutputs; // This map maps indices of the tensors in TFLite to operations/nodes in the IR graph // that correspond to operations having these tensors as output. diff --git a/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp b/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp index 34728b0..97507a4 100644 --- a/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp +++ b/contrib/nnc/passes/tflite_frontend/tflite_op_creator.cpp @@ -28,6 +28,7 @@ #include "core/modelIR/operations/reshape_op.h" #include "pass/PassException.h" +using namespace nnc::mir; namespace nnc { @@ -38,8 +39,8 @@ std::vector OpCreator::createConv2D(InputOps inputs, InputParams par const Conv2DOptions *opts) { auto outputs = createOp(inputs, ActivationFunctionType_NONE, std::move(*params[0]), - Shape{static_cast(opts->stride_h()), - static_cast(opts->stride_w()), 1}, + Shape{static_cast(opts->stride_h()), + static_cast(opts->stride_w()), 1}, paddingMap[opts->padding()]); return createOp(outputs, opts->fused_activation_function(), std::move(*params[1])); @@ -50,8 +51,8 @@ std::vector OpCreator::createDepthConv2D(InputOps inputs, InputParam { auto outputs = createOp( inputs, ActivationFunctionType_NONE, std::move(*params[0]), - Shape{static_cast(opts->stride_h()), - static_cast(opts->stride_w()), 1}, + Shape{static_cast(opts->stride_h()), + static_cast(opts->stride_w()), 1}, paddingMap[opts->padding()]); return createOp(outputs, opts->fused_activation_function(), std::move(*params[1])); @@ -69,10 +70,10 @@ std::vector OpCreator::createMaxPool(InputOps inputs, InputParams pa const Pool2DOptions *opts) { return createOp(inputs, opts->fused_activation_function(), - Shape{static_cast(opts->filter_height()), - static_cast(opts->filter_width()), 1}, - Shape{static_cast(opts->stride_h()), - static_cast(opts->stride_w()), 1}, + Shape{static_cast(opts->filter_height()), + static_cast(opts->filter_width()), 1}, + Shape{static_cast(opts->stride_h()), + static_cast(opts->stride_w()), 1}, ops::PoolOp::PoolingType::MAX, paddingMap[opts->padding()], ops::PoolOp::BorderType::EMPTY); } @@ -81,10 +82,10 @@ std::vector OpCreator::createAvgPool(InputOps inputs, InputParams pa const Pool2DOptions *opts) { return createOp(inputs, opts->fused_activation_function(), - Shape{static_cast(opts->filter_height()), - static_cast(opts->filter_width()), 1}, - Shape{static_cast(opts->stride_h()), - static_cast(opts->stride_w()), 1}, + Shape{static_cast(opts->filter_height()), + static_cast(opts->filter_width()), 1}, + Shape{static_cast(opts->stride_h()), + static_cast(opts->stride_w()), 1}, ops::PoolOp::PoolingType::AVG, paddingMap[opts->padding()], ops::PoolOp::BorderType::EMPTY); } @@ -114,7 +115,7 @@ std::vector OpCreator::createFullyConnected(InputOps &inputs, InputP { // Add Reshape operation to make sure the input for FC operation has shape [1, fcInputSize] auto outputs = createOp(inputs, ActivationFunctionType_NONE); - uint32_t fcInputSize = params[0]->getShape().dim(0); + int32_t fcInputSize = params[0]->getShape().dim(0); outputs[0]->getOperation()->setOutputShape(0, {1, fcInputSize}); auto fcOutputs = createOp(outputs, ActivationFunctionType_NONE, std::move(*params[0])); diff --git a/contrib/nnc/tests/interpreter/op_info_util.cpp b/contrib/nnc/tests/interpreter/op_info_util.cpp index 3bfd54d..7c49d83 100644 --- a/contrib/nnc/tests/interpreter/op_info_util.cpp +++ b/contrib/nnc/tests/interpreter/op_info_util.cpp @@ -156,7 +156,7 @@ namespace tensor std::ostream &operator<<(std::ostream &os, const Shape &sh) { os << "Shape("; - for (uint32_t i = 0; i < sh.rank(); ++i) + for (int32_t i = 0; i < sh.rank(); ++i) { if (i != 0) os << ", "; diff --git a/contrib/nnc/unittests/core/ShapeIndex.cpp b/contrib/nnc/unittests/core/ShapeIndex.cpp new file mode 100644 index 0000000..d2cf484 --- /dev/null +++ b/contrib/nnc/unittests/core/ShapeIndex.cpp @@ -0,0 +1,63 @@ +/* + * 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 + +#include "core/modelIR/Shape.h" +#include "core/modelIR/Index.h" + +using namespace nnc::mir; + +TEST(Shape, Base) +{ + Shape s1{3, 2}; + ASSERT_EQ(s1.rank(), 2); + ASSERT_EQ(s1.dim(0), 3); + ASSERT_EQ(s1.dim(1), 2); + ASSERT_EQ(s1.dim(-1), 2); + ASSERT_EQ(s1.dim(-2), 3); + ASSERT_EQ(s1.numElements(), 6); + + s1.dim(1) = 4; + ASSERT_EQ(s1.dim(1), 4); + ASSERT_EQ(s1.numElements(), 12); + + Shape s2 = s1; + ASSERT_EQ(s1, s2); + + s2.resize(1); + ASSERT_NE(s1, s2); + + s2.resize(2); + s2.dim(1) = s1.dim(1); + ASSERT_EQ(s1, s2); +} + +TEST(Index, Base) +{ + Index idx{3, 2}; + ASSERT_EQ(idx.rank(), 2); + ASSERT_EQ(idx.at(0), 3); + ASSERT_EQ(idx.at(1), 2); + ASSERT_EQ(idx.at(-1), 2); + ASSERT_EQ(idx.at(-2), 3); + + idx.at(1) = 4; + ASSERT_EQ(idx.at(1), 4); + + idx.resize(1); + ASSERT_EQ(idx.rank(), 1); +} diff --git a/contrib/nnc/unittests/core/ShapeInference.cpp b/contrib/nnc/unittests/core/ShapeInference.cpp index 47f9dc8..2d68b0a 100644 --- a/contrib/nnc/unittests/core/ShapeInference.cpp +++ b/contrib/nnc/unittests/core/ShapeInference.cpp @@ -34,7 +34,7 @@ TEST(ShapeInferenceTest, ReshapeAutoDimension) { auto n = g.create("reshape"); n->getOperation()->setInputShape( 0, Shape{10, 2, 5} ); - n->getOperation()->setOutputShape(0, Shape{10, 1, ShapeInference::AUTO_DIM} ); + n->getOperation()->setOutputShape(0, Shape{10, 1, Shape::AUTO_DIM} ); n->connectInputTo(0, input->getOutput(0)); si.visit(n, *static_cast(n->getOperation())); @@ -59,12 +59,12 @@ TEST(ShapeInferenceTest, ReshapeAutoDimensionVaryRank) { n->connectInputTo(0, input->getOutput(0)); // test shrink - n->getOperation()->setOutputShape(0, Shape{10, ShapeInference::AUTO_DIM}); + n->getOperation()->setOutputShape(0, Shape{10, Shape::AUTO_DIM}); si.visit(n, *static_cast(n->getOperation())); ASSERT_EQ(resultShapeShrink, n->getOperation()->getOutputShape(0)); // test expansion - n->getOperation()->setOutputShape(0, Shape{5, ShapeInference::AUTO_DIM, 2, 2}); + n->getOperation()->setOutputShape(0, Shape{5, Shape::AUTO_DIM, 2, 2}); si.visit(n, *static_cast(n->getOperation())); ASSERT_EQ(resultShapeExpand, n->getOperation()->getOutputShape(0)); } diff --git a/contrib/nnc/unittests/core/ShapeRange.cpp b/contrib/nnc/unittests/core/ShapeRange.cpp index 0593765..16496ac 100644 --- a/contrib/nnc/unittests/core/ShapeRange.cpp +++ b/contrib/nnc/unittests/core/ShapeRange.cpp @@ -22,11 +22,11 @@ using namespace nnc::mir; namespace { struct ParamType { - uint32_t actual_length; + int32_t actual_length; Shape shape; template - explicit ParamType(uint32_t actual_len, Args&& ...args) : actual_length(actual_len), shape({static_cast(args)...}) {} + explicit ParamType(int32_t actual_len, Args&& ...args) : actual_length(actual_len), shape({static_cast(args)...}) {} }; class ShapeIteratorTest : public ::testing::TestWithParam { @@ -37,7 +37,7 @@ TEST_P(ShapeIteratorTest, ElementCount) { Shape sh(GetParam().shape); ShapeRange r(sh); - uint32_t cnt = 0; + int32_t cnt = 0; for( auto& idx : r ) { (void)idx; cnt++; @@ -57,4 +57,22 @@ std::vector test_data { INSTANTIATE_TEST_CASE_P(SimpleInput, ShapeIteratorTest, ::testing::ValuesIn(test_data)); +TEST(ShapeRange, Contains) { + const int h = 2; + const int w = 3; + Shape shape{static_cast(h), static_cast(w)}; + ShapeRange range(shape); + Index index{0,0,0,0}; + for (int32_t row = -2; row < h + 1; ++row) + for (int32_t col = -2; col < w + 1; ++col) + { + Index idx{row, col}; + if (row < 0 || row >= h || col < 0 || col >= w) + ASSERT_FALSE(range.contains(idx)); + else + ASSERT_TRUE(range.contains(idx)); + } + +} + } diff --git a/contrib/nnc/unittests/core/deserializer.cpp b/contrib/nnc/unittests/core/deserializer.cpp index f4421bb..1d69f6b 100644 --- a/contrib/nnc/unittests/core/deserializer.cpp +++ b/contrib/nnc/unittests/core/deserializer.cpp @@ -106,10 +106,11 @@ TEST(Deserializer, IntTensorDeserializationTest) { Shape shape_1{3}; for (auto& idx : ShapeRange(shape_1)) { + (void)idx; values.push_back(tmp++); } - proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(int) * num_elements(shape_1))); - for (uint32_t i = 0; i < shape_1.rank(); i++) + proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(int) * shape_1.numElements())); + for (int32_t i = 0; i < shape_1.rank(); i++) { proto_shapePtr->add_dims(shape_1.dim(i)); } @@ -123,10 +124,11 @@ TEST(Deserializer, IntTensorDeserializationTest) { proto_shapePtr->clear_dims(); for (auto& idx : ShapeRange(shape_2)) { + (void)idx; values.push_back(tmp--); } - proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(int) * num_elements(shape_2))); - for (uint32_t i = 0; i < shape_2.rank(); i++) + proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(int) * shape_2.numElements())); + for (int32_t i = 0; i < shape_2.rank(); i++) { proto_shapePtr->add_dims(shape_2.dim(i)); } @@ -140,10 +142,11 @@ TEST(Deserializer, IntTensorDeserializationTest) { proto_shapePtr->clear_dims(); for (auto& idx : ShapeRange(shape_3)) { + (void)idx; values.push_back(tmp++); } - proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(int) * num_elements(shape_3))); - for (uint32_t i = 0; i < shape_3.rank(); i++) + proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(int) * shape_3.numElements())); + for (int32_t i = 0; i < shape_3.rank(); i++) { proto_shapePtr->add_dims(shape_3.dim(i)); } @@ -166,11 +169,12 @@ TEST(Deserializer, FloatTensorDeserializationTest) { Shape shape_1{3}; for (auto& idx : ShapeRange(shape_1)) { + (void)idx; values.push_back(tmp); tmp += 7.3f; } - proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(float) * num_elements(shape_1))); - for (uint32_t i = 0; i < shape_1.rank(); i++) + proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(float) * shape_1.numElements())); + for (int32_t i = 0; i < shape_1.rank(); i++) { proto_shapePtr->add_dims(shape_1.dim(i)); } @@ -184,11 +188,12 @@ TEST(Deserializer, FloatTensorDeserializationTest) { proto_shapePtr->clear_dims(); for (auto& idx : ShapeRange(shape_2)) { + (void)idx; values.push_back(tmp); tmp *= -1.32f; } - proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(float) * num_elements(shape_2))); - for (uint32_t i = 0; i < shape_2.rank(); i++) + proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(float) * shape_2.numElements())); + for (int32_t i = 0; i < shape_2.rank(); i++) { proto_shapePtr->add_dims(shape_2.dim(i)); } @@ -202,11 +207,12 @@ TEST(Deserializer, FloatTensorDeserializationTest) { proto_shapePtr->clear_dims(); for (auto& idx : ShapeRange(shape_3)) { + (void)idx; tmp /= 2; values.push_back(tmp); } - proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(float) * num_elements(shape_3))); - for (uint32_t i = 0; i < shape_3.rank(); i++) + proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(float) * shape_3.numElements())); + for (int32_t i = 0; i < shape_3.rank(); i++) { proto_shapePtr->add_dims(shape_3.dim(i)); } @@ -229,11 +235,12 @@ TEST(Deserializer, DoubleTensorDeserializationTest) { Shape shape_1{3}; for (auto& idx : ShapeRange(shape_1)) { + (void)idx; values.push_back(tmp); tmp += 7.3f; } - proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(double) * num_elements(shape_1))); - for (uint32_t i = 0; i < shape_1.rank(); i++) + proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(double) * shape_1.numElements())); + for (int32_t i = 0; i < shape_1.rank(); i++) { proto_shapePtr->add_dims(shape_1.dim(i)); } @@ -247,11 +254,12 @@ TEST(Deserializer, DoubleTensorDeserializationTest) { proto_shapePtr->clear_dims(); for (auto& idx : ShapeRange(shape_2)) { + (void)idx; values.push_back(tmp); tmp *= -1.32f; } - proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(double) * num_elements(shape_2))); - for (uint32_t i = 0; i < shape_2.rank(); i++) + proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(double) * shape_2.numElements())); + for (int32_t i = 0; i < shape_2.rank(); i++) { proto_shapePtr->add_dims(shape_2.dim(i)); } @@ -265,11 +273,12 @@ TEST(Deserializer, DoubleTensorDeserializationTest) { proto_shapePtr->clear_dims(); for (auto& idx : ShapeRange(shape_3)) { + (void)idx; tmp /= 2; values.push_back(tmp); } - proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(double) * num_elements(shape_3))); - for (uint32_t i = 0; i < shape_3.rank(); i++) + proto_tensor.set_tensor_content(std::string((char*) values.data(), sizeof(double) * shape_3.numElements())); + for (int32_t i = 0; i < shape_3.rank(); i++) { proto_shapePtr->add_dims(shape_3.dim(i)); } diff --git a/contrib/nnc/unittests/core/serializer.cpp b/contrib/nnc/unittests/core/serializer.cpp index 5c2655c..54f84cb 100644 --- a/contrib/nnc/unittests/core/serializer.cpp +++ b/contrib/nnc/unittests/core/serializer.cpp @@ -47,7 +47,7 @@ template static std::shared_ptr allocateTensorContent(const Shape &shape) { size_t data_size = 1; - for (uint32_t i = 0; i < shape.rank(); ++i) + for (int32_t i = 0; i < shape.rank(); ++i) { data_size *= shape.dim(i); } diff --git a/contrib/nnc/unittests/soft_backend/CPPOperations.cpp b/contrib/nnc/unittests/soft_backend/CPPOperations.cpp index 9b277d2..12992a0 100644 --- a/contrib/nnc/unittests/soft_backend/CPPOperations.cpp +++ b/contrib/nnc/unittests/soft_backend/CPPOperations.cpp @@ -161,7 +161,7 @@ void fillNTensor(mir::TensorVariant &dst, float start) mir::TensorVariant createNTensor(mir::Shape &shape, float start) { shared_ptr dataBuf( - new char[sizeof(float)*mir::num_elements(shape)], default_delete()); + new char[sizeof(float)*shape.numElements()], default_delete()); mir::TensorVariant tensor(shape, dataBuf, mir::TensorVariant::DTYPE::FLOAT, sizeof(float)); fillNTensor(tensor, start); return tensor; @@ -192,7 +192,7 @@ void fillTensors(unique_ptr &nTensor, Tensor &aTensor, const fillShapes(nShape, aShape, shape); aTensor.reShape(aShape); shared_ptr dataBuf( - new char[sizeof(float)*mir::num_elements(nShape)], default_delete()); + new char[sizeof(float)*nShape.numElements()], default_delete()); nTensor.reset(new mir::TensorVariant(nShape, dataBuf, mir::TensorVariant::DTYPE::FLOAT, sizeof(float))); fillNTensor(*nTensor, start); copyATensorFromNTensor(aTensor, *nTensor); @@ -341,7 +341,7 @@ TEST(cpp_operations_test, conv2d) // input channels(inputC), output channels(outputC), // stride width, stride height // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal to 1 - using iT = uint32_t; + using iT = int32_t; for (iT kernelH = 1; kernelH <= 3; ++kernelH) for (iT kernelW = 1; kernelW <= 3; ++kernelW) for (iT inputC = 1; inputC <= 3; ++inputC) @@ -373,7 +373,7 @@ TEST(cpp_operations_tests, depthwise_conv) // stride width, stride height // layers multiplier // size 3 is chosen to cover all cases, where width bigger/smaller then height and equal/not equal to 1 - using iT = uint32_t; + using iT = int32_t; for (iT kernelH = 1; kernelH <= 3; ++kernelH) for (iT kernelW = 1; kernelW <= 3; ++kernelW) for (iT channels = 1; channels <= 3; ++channels) @@ -417,7 +417,7 @@ static void genericPoolTest(Func testFunc, const vector