diff options
Diffstat (limited to 'libs/kernel/acl/src/IO_accessor.cpp')
-rw-r--r-- | libs/kernel/acl/src/IO_accessor.cpp | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/libs/kernel/acl/src/IO_accessor.cpp b/libs/kernel/acl/src/IO_accessor.cpp new file mode 100644 index 000000000..410fb8ea5 --- /dev/null +++ b/libs/kernel/acl/src/IO_accessor.cpp @@ -0,0 +1,310 @@ +/* + * 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 "IO_accessor.h" + +#include <cassert> + +namespace nnfw { +namespace kernel { +namespace acl { + +InputAccessor::InputAccessor(const float* inputData, const nnfw::rt::Shape& inputShape) + : _inputData(inputData) + , _inputShape(inputShape) +{ +} + +MatrixInputAccessor::MatrixInputAccessor(const float* inputData, const nnfw::rt::Shape& inputShape) + : _inputData(inputData) + , _inputShape(inputShape) +{ +} + +VectorInputAccessor::VectorInputAccessor(const float* inputData, const nnfw::rt::Shape& inputShape) + : _inputData(inputData) + , _inputShape(inputShape) +{ +} + +WeightAccessor::WeightAccessor(const float* filterData, const nnfw::rt::Shape& filterShape) + : _filterData(filterData) + , _filterShape(filterShape) +{ +} + +MatrixWeightAccessor::MatrixWeightAccessor(const float* filterData, const nnfw::rt::Shape& filterShape) + : _filterData(filterData) + , _filterShape(filterShape) +{ +} + +BiasAccessor::BiasAccessor(const float* biasData, const nnfw::rt::Shape& biasShape) + : _biasData(biasData) + , _biasShape(biasShape) +{ +} + +OutputAccessor::OutputAccessor(float* outputData, const nnfw::rt::Shape& outputShape) + : _outputData(outputData) + , _outputShape(outputShape) +{ +} + +MatrixOutputAccessor::MatrixOutputAccessor(float* outputData, const nnfw::rt::Shape& outputShape) + : _outputData(outputData) + , _outputShape(outputShape) +{ +} + +VectorOutputAccessor::VectorOutputAccessor(float* outputData, const nnfw::rt::Shape& outputShape) + : _outputData(outputData) + , _outputShape(outputShape) +{ +} + +static uint32_t getOffsetNCHW(const nnfw::rt::Shape& shape, const arm_compute::Coordinates& id) +{ + // get offset for ACL(NCHW) from data of NNAPI(NHWC) + uint32_t num = getSizeOfDimension(shape, 0); + uint32_t height = getSizeOfDimension(shape, 1); + uint32_t width = getSizeOfDimension(shape, 2); + uint32_t chann = getSizeOfDimension(shape, 3); + uint32_t stride = 1; + uint32_t offset = 0; + uint32_t numdim = id.num_dimensions(); + offset += numdim > 0 ? id[0] * stride : 0; stride *= width; + offset += numdim > 1 ? id[1] * stride : 0; stride *= height; + offset += numdim > 2 ? id[2] * stride : 0; stride *= chann; + offset += numdim > 3 ? id[3] * stride : 0; stride *= num; + return offset; +} + +static uint32_t getElementOffset(const nnfw::rt::Shape& shape, + uint32_t ch, uint32_t row, uint32_t col) +{ + assert(getSizeOfDimension(shape, 0) == 1); + assert(shape.dimensions.size() == 4); + + // TODO Optimize this! + const uint32_t W = getSizeOfDimension(shape, 2); + const uint32_t C = getSizeOfDimension(shape, 3); + + int offset = 0; + + // NNAPI uses NHWC ordering + offset += row * W * C; + offset += col * C; + offset += ch; + + return offset; +} + +static uint32_t getElementOffset(const nnfw::rt::Shape& shape, + uint32_t nth, uint32_t ch, uint32_t row, uint32_t col) +{ + assert(shape.dimensions.size() == 4); + + // TODO Optimize this! + const uint32_t H = getSizeOfDimension(shape, 1); + const uint32_t W = getSizeOfDimension(shape, 2); + const uint32_t C = getSizeOfDimension(shape, 3); + + int offset = 0; + + // NNAPI uses NHWC ordering + offset += nth * H * W * C; + offset += row * W * C; + offset += col * C; + offset += ch; + + return offset; +} + +bool InputAccessor::access_tensor(arm_compute::ITensor &tensor) +{ + arm_compute::Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + execute_window_loop(window, [&](const arm_compute::Coordinates& id) + { + const uint32_t ch = id[2]; + const uint32_t row = id[1]; + const uint32_t col = id[0]; + + uint32_t offset = getElementOffset(_inputShape, ch, row, col); + + *reinterpret_cast<float *>(tensor.ptr_to_element(id)) = + *(_inputData + offset); + }); + return true; +} + +bool MatrixInputAccessor::access_tensor(arm_compute::ITensor &tensor) +{ + arm_compute::Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + assert(tensor.info()->tensor_shape().num_dimensions() <= 2); + + execute_window_loop(window, [&](const arm_compute::Coordinates& id) + { + const auto row = id[1]; + const auto col = id[0]; + const auto W = tensor.info()->tensor_shape().x(); + + const auto offset = row * W + col; + + *reinterpret_cast<float *>(tensor.ptr_to_element(id)) = + *(_inputData + offset); + }); + return true; +} + +bool VectorInputAccessor::access_tensor(arm_compute::ITensor &tensor) +{ + arm_compute::Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + assert(tensor.info()->tensor_shape().num_dimensions() == 1); + + execute_window_loop(window, [&](const arm_compute::Coordinates& id) + { + uint32_t offset = id[0]; + + *reinterpret_cast<float *>(tensor.ptr_to_element(id)) = + *(_inputData + offset); + }); + return true; +} + +bool WeightAccessor::access_tensor(arm_compute::ITensor &tensor) +{ + arm_compute::Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + execute_window_loop(window, [&](const arm_compute::Coordinates& id) + { + const uint32_t nth = id[3]; + const uint32_t ch = id[2]; + const uint32_t row = id[1]; + const uint32_t col = id[0]; + + uint32_t offset = getElementOffset(_filterShape, nth, ch, row, col); + + *reinterpret_cast<float *>(tensor.ptr_to_element(id)) = + *(_filterData + offset); + }); + return true; +} + +bool MatrixWeightAccessor::access_tensor(arm_compute::ITensor &tensor) +{ + arm_compute::Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + assert(tensor.info()->tensor_shape().num_dimensions() <= 2); + + execute_window_loop(window, [&](const arm_compute::Coordinates& id) + { + const auto row = id[1]; + const auto col = id[0]; + const auto W = tensor.info()->tensor_shape().x(); + + uint32_t offset = row * W + col; + + *reinterpret_cast<float *>(tensor.ptr_to_element(id)) = + *(_filterData + offset); + }); + return true; +} + +bool BiasAccessor::access_tensor(arm_compute::ITensor &tensor) +{ + arm_compute::Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + execute_window_loop(window, [&](const arm_compute::Coordinates& id) + { + uint32_t offset = getOffsetNCHW(_biasShape, id); + *reinterpret_cast<float *>(tensor.ptr_to_element(id)) = + *(_biasData + offset); + }); + return true; +} + +bool OutputAccessor::access_tensor(arm_compute::ITensor &tensor) +{ + arm_compute::Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + execute_window_loop(window, [&](const arm_compute::Coordinates& id) + { + const uint32_t ch = id[2]; + const uint32_t row = id[1]; + const uint32_t col = id[0]; + + uint32_t offset = getElementOffset(_outputShape, ch, row, col); + + *(_outputData + offset) = + *reinterpret_cast<float *>(tensor.ptr_to_element(id)); + }); + return false; // end the network +} + +bool VectorOutputAccessor::access_tensor(arm_compute::ITensor &tensor) +{ + arm_compute::Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + assert(tensor.info()->tensor_shape().num_dimensions() == 1); + + execute_window_loop(window, [&](const arm_compute::Coordinates& id) + { + const uint32_t x = id[0]; + + uint32_t offset = x; + + *(_outputData + offset) = + *reinterpret_cast<float *>(tensor.ptr_to_element(id)); + }); + return false; // end the network +} + +bool MatrixOutputAccessor::access_tensor(arm_compute::ITensor &tensor) +{ + arm_compute::Window window; + window.use_tensor_dimensions(tensor.info()->tensor_shape()); + + assert(tensor.info()->tensor_shape().num_dimensions() <= 2); + + execute_window_loop(window, [&](const arm_compute::Coordinates& id) + { + const auto row = id[1]; + const auto col = id[0]; + const auto W = tensor.info()->tensor_shape().x(); + + const auto offset = row * W + col; + + *(_outputData + offset) = + *reinterpret_cast<float *>(tensor.ptr_to_element(id)); + }); + return false; // end the network +} + +} // namespace acl +} // namespace kernel +} // namespace nnfw |