From 2bb69e635a7bcf26c8200389caa324d47ba15bf5 Mon Sep 17 00:00:00 2001 From: "Efimov Alexander/AI Tools Lab/./Samsung Electronics" Date: Tue, 4 Sep 2018 17:09:19 +0300 Subject: [PATCH] Fix arm c++ artifact generation (#1285) + Fix alignment of serialized data + Fix build with NEON enabled + Fix -Wall warnings Signed-off-by: Efimov Alexander --- contrib/nnc/plugin/soft_backend/cpp_operations.def | 54 +++++++++++++++------- contrib/nnc/plugin/soft_backend/cpp_ops/eigen.def | 1 + contrib/nnc/plugin/soft_backend/serializer.cpp | 31 +++++++------ 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/contrib/nnc/plugin/soft_backend/cpp_operations.def b/contrib/nnc/plugin/soft_backend/cpp_operations.def index aa2f76e..d9dc525 100644 --- a/contrib/nnc/plugin/soft_backend/cpp_operations.def +++ b/contrib/nnc/plugin/soft_backend/cpp_operations.def @@ -9,6 +9,8 @@ using namespace std; +#define UNUSED(x) ((void)(x)) + static_assert(numeric_limits::is_iec559, "Unsupported float type"); void readParameters(char *&data, size_t &len, const string &path, @@ -23,37 +25,46 @@ void readParameters(char *&data, size_t &len, const string &path, // gather file info int statRes = fstat(fd, &st); - (void)statRes; assert(statRes != -1); + UNUSED(statRes); len = st.st_size; assert(len >= params::HEADER_LEN); // check magic correctness char magic[params::MAGIC_LEN + 1] = {}; - read(fd, magic, params::MAGIC_LEN); + ssize_t magic_len = read(fd, magic, params::MAGIC_LEN); + assert(magic_len == params::MAGIC_LEN); + UNUSED(magic_len); assert(strncmp(magic, params::MAGIC, params::MAGIC_LEN) == 0); + UNUSED(magic); // checkversion correctness decltype(expectedVersion) version; - read(fd, &version, sizeof(version)); + ssize_t version_len = read(fd, &version, sizeof(version)); + assert(version_len == sizeof(version)); + UNUSED(version_len); assert(version == expectedVersion); + UNUSED(version); // check hash correctness decltype(expectedHash) hash; - read(fd, &hash, sizeof(hash)); + ssize_t hash_len = read(fd, &hash, sizeof(hash)); + assert(hash_len == sizeof(hash)); + UNUSED(hash_len); assert(hash == expectedHash); + UNUSED(hash); data = static_cast(mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0)); int is_error = close(fd); assert(!is_error && "Can not close file!"); - (void)is_error; + UNUSED(is_error); } void releaseParameters(char *data, size_t len) { int res = munmap(data, len); - (void)res; assert(res == 0); + UNUSED(res); } template @@ -100,7 +111,7 @@ static inline T deserializeT(const char *&buf) static inline Shape deserializeShape(const char *&buf) { Shape s; - char rank = deserializeT(buf); + int32_t rank = deserializeT(buf); s.setDims(rank); for (int i = 0; i < rank; ++i) { @@ -115,15 +126,23 @@ struct Kernel Dims<4> dims; }; +static bool isAddrAligned(const void *data, int alignment) +{ + return (reinterpret_cast(data) % alignment) == 0; +} + static inline Kernel deserializeKernel(const char *&buf) { - char dType = deserializeT(buf); + int32_t dType = deserializeT(buf); assert(dType == 1 && "Unknown data type"); - char eSize = deserializeT(buf); + UNUSED(dType); + int32_t eSize = deserializeT(buf); assert(eSize == 4 && "Unsupported element size"); + UNUSED(eSize); Kernel k; k.dims = shapeToDims(deserializeShape(buf)); k.data = reinterpret_cast(buf); + assert(isAddrAligned(buf, 4) && "data should be aligned to 4 bytes to use arm vector instructions"); buf += volume(k.dims) * eSize; return k; } @@ -135,7 +154,7 @@ void concat(Tensor &out, const char *params, const Args &...inputs) { const float *input[] = {inputs.getData()...}; Dims<4> input_d[] = {shapeToDims(inputs.getShape())...}; - int axis = deserializeT(params); + int axis = deserializeT(params); Shape out_s = deserializeShape(params); // because inner functions accepts axis in reverse order axis = out_s.getDims() - 1 - axis; @@ -155,8 +174,8 @@ void conv2d(Tensor &out, const char *params, const Tensor &in) Kernel kernel = deserializeKernel(params); Shape strides = deserializeShape(params); // pads type. unused for now - char pt = deserializeT(params); - (void)pt; + int32_t pt = deserializeT(params); + UNUSED(pt); Shape pads = deserializeShape(params); Shape out_s = deserializeShape(params); @@ -203,8 +222,8 @@ void depthwiseConv2d(Tensor &out, const char *params, const Tensor &in) Kernel kernel = deserializeKernel(params); Shape strides = deserializeShape(params); // pads type. unused for now - char pt = deserializeT(params); - (void)pt; + int32_t pt = deserializeT(params); + UNUSED(pt); Shape pads = deserializeShape(params); Shape out_s = deserializeShape(params); @@ -241,8 +260,9 @@ void softmax(Tensor &out, const char *params, const Tensor &in) const float *input = in.getData(); Dims<4> input_d = shapeToDims(in.getShape()); float beta = 1; - char axis = deserializeT(params); + int32_t axis = deserializeT(params); assert(axis == in.getShape().getDims() - 1); + UNUSED(axis); out.reShape(in.getShape()); @@ -257,8 +277,8 @@ static inline void genericPool(Executor executor, Tensor &out, const char *param Shape window = deserializeShape(params); Shape strides = deserializeShape(params); // pads type. unused for now - char pt = deserializeT(params); - (void)pt; + int32_t pt = deserializeT(params); + UNUSED(pt); Shape pads = deserializeShape(params); Shape out_s = deserializeShape(params); diff --git a/contrib/nnc/plugin/soft_backend/cpp_ops/eigen.def b/contrib/nnc/plugin/soft_backend/cpp_ops/eigen.def index 24f01de..d83f608 100644 --- a/contrib/nnc/plugin/soft_backend/cpp_ops/eigen.def +++ b/contrib/nnc/plugin/soft_backend/cpp_ops/eigen.def @@ -13229,6 +13229,7 @@ struct palign_impl\ first = Command(first, second, Offset);\ }\ };\ + PALIGN_NEON(0,Packet4f,vextq_f32) PALIGN_NEON(1,Packet4f,vextq_f32) PALIGN_NEON(2,Packet4f,vextq_f32) diff --git a/contrib/nnc/plugin/soft_backend/serializer.cpp b/contrib/nnc/plugin/soft_backend/serializer.cpp index a272b91..9580646 100644 --- a/contrib/nnc/plugin/soft_backend/serializer.cpp +++ b/contrib/nnc/plugin/soft_backend/serializer.cpp @@ -16,6 +16,8 @@ #include +#define UNUSED(x) ((void)(x)) + namespace nncc { namespace contrib @@ -37,8 +39,10 @@ using nncc::contrib::core::ADT::TensorVariant; namespace { - const auto MAX_DIMS = numeric_limits::max(); + // Currently there are no operations with more then 4 dimensions in kernels/weights etc supported + const auto MAX_DIMS = 4; const auto MAX_DIM_SIZE = numeric_limits::max(); + // Assuming there are no large enums const auto MAX_ENUM_VAL = numeric_limits::max(); } // unnamed namespace @@ -66,8 +70,8 @@ typename underlying_type::type etoi(E enumVal) void Serializer::serializeShape(const Shape &s) { int32_t rank = s.rank(); - assert(rank < MAX_DIMS); - serializeT(s.rank()); + assert(rank <= MAX_DIMS); + serializeT(s.rank()); for (int32_t i = 0; i < rank; ++i) { int32_t dim = s.dim(i); @@ -79,11 +83,11 @@ void Serializer::serializeTensor(const TensorVariant &t) { // serialize type assert(etoi(t.getDataType()) < MAX_ENUM_VAL); - serializeT(etoi(t.getDataType())); + serializeT(etoi(t.getDataType())); // seriazlie data size size_t eSize = t.getElementSize(); - assert(eSize < MAX_DIMS); - serializeT(eSize); + assert(eSize <= MAX_DIMS); + serializeT(eSize); // serialize shape const Shape &shape = t.getShape(); serializeShape(shape); @@ -103,15 +107,16 @@ void Serializer::serializePads(const Op &op, int32_t padsRank) { // serialize padding type assert(etoi(op.getPaddingType()) < MAX_ENUM_VAL); - serializeT(etoi(op.getPaddingType())); + serializeT(etoi(op.getPaddingType())); // serialize pads - assert(padsRank < MAX_DIMS); - serializeT(padsRank); + assert(padsRank <= MAX_DIMS); + serializeT(padsRank); for (int i = 0; i < static_cast(padsRank); ++i) { auto pad = op.getPadding(i); assert(pad <= MAX_DIM_SIZE); assert(pad >= 0); + UNUSED(pad); serializeT(op.getPadding(i)); } } @@ -120,8 +125,8 @@ void Serializer::visit(ADT::INode *node, ops::ConcatOp &op) { _curOp->_paramStartOffset = _buffer.size(); // axis number should fit into one byte - assert(op.getAxis() < MAX_DIMS); - serializeT(op.getAxis()); + assert(op.getAxis() <= MAX_DIMS); + serializeT(op.getAxis()); serializeShape(op.getOutputShape(0)); } @@ -161,8 +166,8 @@ void Serializer::visit(ADT::INode *node, ops::SoftmaxOp &op) { _curOp->_paramStartOffset = _buffer.size(); // axis number should fit into one byte - assert(op.getAxis() < MAX_DIMS); - serializeT(op.getAxis()); + assert(op.getAxis() <= MAX_DIMS); + serializeT(op.getAxis()); } void Serializer::visit(ADT::INode *node, ops::PoolOp &op) -- 2.7.4