diff options
Diffstat (limited to 'runtimes/neurun/src/kernel/cpu')
19 files changed, 0 insertions, 2091 deletions
diff --git a/runtimes/neurun/src/kernel/cpu/AvgPoolLayer.cc b/runtimes/neurun/src/kernel/cpu/AvgPoolLayer.cc deleted file mode 100644 index f434a6dec..000000000 --- a/runtimes/neurun/src/kernel/cpu/AvgPoolLayer.cc +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * Copyright (C) 2017 The Android Open Source Project - * - * 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 "AvgPoolLayer.h" - -#include "tensorflow/contrib/lite/kernels/internal/optimized/optimized_ops.h" -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -#define AVGPOOLING_PARAMETERS \ - tflite::PoolParams op_params; \ - op_params.stride_height = _strideHeight; \ - op_params.stride_width = _strideWidth; \ - op_params.filter_height = _kernelHeight; \ - op_params.filter_width = _kernelWidth; \ - op_params.padding_values.height = (int8_t)_paddingTop; \ - op_params.padding_values.width = (int8_t)_paddingLeft; - -AvgPoolLayer::AvgPoolLayer() - : _inputData(nullptr), _outputData(nullptr), _inputShape(), _outputShape(), _paddingLeft(0), - _paddingTop(0), _paddingRight(0), _paddingBottom(0), _strideWidth(0), _strideHeight(0), - _kernelWidth(0), _kernelHeight(0), _activation(ANEURALNETWORKS_FUSED_NONE), - _inputType(OperandType::SCALAR_FLOAT32) -{ - // DO NOTHING -} - -bool AvgPoolLayer::averagePoolFloat32() -{ - AVGPOOLING_PARAMETERS - float output_activation_min, output_activation_max; - CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max); - op_params.float_activation_min = output_activation_min; - op_params.float_activation_max = output_activation_max; - - ::tflite::optimized_ops::AveragePool(op_params, convertShapeToTFLiteShape(_inputShape), - reinterpret_cast<const float *>(_inputData), - convertShapeToTFLiteShape(_outputShape), - reinterpret_cast<float *>(_outputData)); - return true; -} -bool AvgPoolLayer::averagePoolQuant8() -{ - AVGPOOLING_PARAMETERS - int32_t output_activation_min = 0; - int32_t output_activation_max = 0; - CalculateActivationRangeUint8(_activation, _outputShape, &output_activation_min, - &output_activation_max); - op_params.quantized_activation_min = output_activation_min; - op_params.quantized_activation_max = output_activation_max; - - ::tflite::optimized_ops::AveragePool(op_params, convertShapeToTFLiteShape(_inputShape), - _inputData, convertShapeToTFLiteShape(_outputShape), - _outputData); - return true; -} - -void AvgPoolLayer::configure(uint8_t *inputData, const Shape inputShape, const uint32_t paddingLeft, - const uint32_t paddingRight, const uint32_t paddingTop, - const uint32_t paddingBottom, const uint32_t strideWidth, - const uint32_t strideHeight, const uint32_t kernelWidth, - const uint32_t kernelHeight, const FuseCode activation, - uint8_t *outputData, const Shape outputShape) -{ - _inputData = inputData; - _inputShape = inputShape; - _inputType = inputShape.type; - _paddingLeft = paddingLeft; - _paddingRight = paddingRight; - _paddingTop = paddingTop; - _paddingBottom = paddingBottom; - _strideWidth = strideWidth; - _strideHeight = strideHeight; - _kernelWidth = kernelWidth; - _kernelHeight = kernelHeight; - _activation = activation; - _outputData = outputData; - _outputShape = outputShape; -} - -void AvgPoolLayer::run() -{ - if (_inputType == OperandType::TENSOR_FLOAT32) - { - averagePoolFloat32(); - } - else if (_inputType == OperandType::TENSOR_QUANT8_ASYMM) - { - throw std::runtime_error{"AvgPoolLayer : Not tested for TENSOR_QUANT8_ASYMM"}; - // averagePoolQuant8(); - } -} - -#undef AVGPOOLING_PARAMETERS - -} // namespace cpu -} // namespace kernel -} // namespace neurun diff --git a/runtimes/neurun/src/kernel/cpu/AvgPoolLayer.h b/runtimes/neurun/src/kernel/cpu/AvgPoolLayer.h deleted file mode 100644 index 280f7ae5f..000000000 --- a/runtimes/neurun/src/kernel/cpu/AvgPoolLayer.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 __NEURUN_KERNEL_CPU_AVGPOOLLAYER_H__ -#define __NEURUN_KERNEL_CPU_AVGPOOLLAYER_H__ - -#include <NeuralNetworks.h> - -#include "exec/interface/IFunction.h" - -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -class AvgPoolLayer : public ::neurun::exec::IFunction -{ -public: - AvgPoolLayer(); - -public: - bool averagePoolFloat32(); - - bool averagePoolQuant8(); - - void configure(uint8_t *inputData, const Shape inputShape, const uint32_t paddingLeft, - const uint32_t paddingRight, const uint32_t paddingTop, - const uint32_t paddingBottom, const uint32_t strideWidth, - const uint32_t strideHeight, const uint32_t kernelWidth, - const uint32_t kernelHeight, const FuseCode activation, uint8_t *outputData, - const Shape outputShape); - - void run(); - -private: - uint8_t *_inputData; - uint8_t *_outputData; - - Shape _inputShape; - Shape _outputShape; - - uint32_t _paddingLeft; - uint32_t _paddingTop; - uint32_t _paddingRight; - uint32_t _paddingBottom; - - uint32_t _strideWidth; - uint32_t _strideHeight; - uint32_t _kernelWidth; - uint32_t _kernelHeight; - - FuseCode _activation; - - OperandType _inputType; -}; - -} // namespace cpu -} // namespace kernel -} // namespace neurun - -#endif // __NEURUN_KERNEL_CPU_AVGPOOLLAYER_H__ diff --git a/runtimes/neurun/src/kernel/cpu/CMakeLists.txt b/runtimes/neurun/src/kernel/cpu/CMakeLists.txt deleted file mode 100644 index 436cb898c..000000000 --- a/runtimes/neurun/src/kernel/cpu/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -file(GLOB SOURCES "*.cc") - -add_library(${LIB_NEURUN_KERNEL_CPU} STATIC ${SOURCES}) - -target_include_directories(${LIB_NEURUN_KERNEL_CPU} PUBLIC ${NNFW_INCLUDE_DIR}) -target_include_directories(${LIB_NEURUN_KERNEL_CPU} PUBLIC ${NEURUN_INCLUDE_DIR}) -target_include_directories(${LIB_NEURUN_KERNEL_CPU} PUBLIC ${CMAKE_SOURCE_DIR}/externals/tensorflow) - -target_link_libraries(${LIB_NEURUN_KERNEL_CPU} tensorflow-lite) -target_link_libraries(${LIB_NEURUN_KERNEL_CPU} nnfw_lib_misc) - -set_target_properties(${LIB_NEURUN_KERNEL_CPU} PROPERTIES POSITION_INDEPENDENT_CODE ON) -set_target_properties(${LIB_NEURUN_KERNEL_CPU} PROPERTIES OUTPUT_NAME kernel_cpu) -install(TARGETS ${LIB_NEURUN_KERNEL_CPU} DESTINATION lib/neurun) diff --git a/runtimes/neurun/src/kernel/cpu/ConcatLayer.cc b/runtimes/neurun/src/kernel/cpu/ConcatLayer.cc deleted file mode 100644 index be093b437..000000000 --- a/runtimes/neurun/src/kernel/cpu/ConcatLayer.cc +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * Copyright (C) 2017 The Android Open Source Project - * - * 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 "ConcatLayer.h" - -#include "tensorflow/contrib/lite/kernels/internal/optimized/optimized_ops.h" -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ - -namespace cpu -{ - -ConcatLayer::ConcatLayer() - : _inputDataPtrs(), _outputData(nullptr), _axis(0), _inputShapes(), _outputShape(), - _inputType(OperandType::SCALAR_FLOAT32) -{ - // DO NOTHING -} - -bool ConcatLayer::concatenationFloat32() -{ - uint32_t num_inputs = _inputShapes.size(); - - tflite::ConcatenationParams op_params; - op_params.axis = _axis; - op_params.inputs_count = num_inputs; - - std::vector<::tflite::RuntimeShape *> inputDimsPtr; - std::vector<::tflite::RuntimeShape> inputDims; - inputDimsPtr.reserve(num_inputs); - inputDims.reserve(num_inputs); - - for (uint32_t i = 0; i < num_inputs; i++) - { - inputDims.push_back(convertShapeToTFLiteShape(_inputShapes[i])); - inputDimsPtr.push_back(&inputDims[i]); - } - - std::vector<const float *> inputFloatPtrs; - - for (auto ptr : _inputDataPtrs) - { - inputFloatPtrs.emplace_back(reinterpret_cast<const float *>(ptr)); - } - - ::tflite::optimized_ops::Concatenation<float>( - op_params, inputDimsPtr.data(), inputFloatPtrs.data(), - convertShapeToTFLiteShape(_outputShape), reinterpret_cast<float *>(_outputData)); - return true; -} -bool ConcatLayer::concatenationQuant8() -{ - int num_inputs = _inputShapes.size(); - - std::vector<int32_t> input_zeropoints(num_inputs); - std::vector<float> input_scales(num_inputs); - for (uint32_t i = 0; i < num_inputs; i++) - { - input_zeropoints[i] = _inputShapes[i].offset; - input_scales[i] = _inputShapes[i].scale; - } - - tflite::ConcatenationParams op_params; - op_params.axis = _axis; - op_params.inputs_count = num_inputs; - op_params.input_zeropoint = input_zeropoints.data(); - op_params.input_scale = input_scales.data(); - op_params.output_zeropoint = _outputShape.offset; - op_params.output_scale = _outputShape.scale; - - std::vector<::tflite::RuntimeShape *> inputDimsPtr; - std::vector<::tflite::RuntimeShape> inputDims; - inputDimsPtr.reserve(num_inputs); - inputDims.reserve(num_inputs); - for (uint32_t i = 0; i < num_inputs; i++) - { - inputDims.push_back(convertShapeToTFLiteShape(_inputShapes[i])); - inputDimsPtr.push_back(&inputDims[i]); - } - - ::tflite::optimized_ops::Concatenation<uint8_t>( - op_params, inputDimsPtr.data(), _inputDataPtrs.data(), - convertShapeToTFLiteShape(_outputShape), _outputData); - return true; -} - -void ConcatLayer::configure(const std::vector<const uint8_t *> &inputDataPtrs, - const std::vector<Shape> &inputShapes, int32_t axis, - uint8_t *outputData, const Shape outputShape) -{ - _inputDataPtrs = inputDataPtrs; - - for (auto shape : inputShapes) - { - _inputShapes.emplace_back(shape); - _inputType = shape.type; - } - - _axis = axis; - - _outputData = outputData; - _outputShape = outputShape; -} - -void ConcatLayer::run() -{ - if (_inputType == OperandType::TENSOR_FLOAT32) - { - concatenationFloat32(); - } - else if (_inputType == OperandType::TENSOR_QUANT8_ASYMM) - { - throw std::runtime_error{"ConcatLayer : Not tested for TENSOR_QUANT8_ASYMM"}; - // concatenationQuant8(); - } -} - -} // namespace cpu -} // namespace kernel -} // namespace neurun diff --git a/runtimes/neurun/src/kernel/cpu/ConcatLayer.h b/runtimes/neurun/src/kernel/cpu/ConcatLayer.h deleted file mode 100644 index 64f813508..000000000 --- a/runtimes/neurun/src/kernel/cpu/ConcatLayer.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * Copyright (C) 2017 The Android Open Source Project - * - * 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 __NEURUN_KERNEL_CPU_CONCATLAYER_H__ -#define __NEURUN_KERNEL_CPU_CONCATLAYER_H__ - -#include <NeuralNetworks.h> - -#include "exec/interface/IFunction.h" - -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -class ConcatLayer : public ::neurun::exec::IFunction -{ -public: - ConcatLayer(); - -public: - bool concatenationFloat32(); - - bool concatenationQuant8(); - - void configure(const std::vector<const uint8_t *> &inputDataPtrs, - const std::vector<Shape> &inputShapes, int32_t axis, uint8_t *outputData, - const Shape outputShape); - - void run(); - -private: - std::vector<const uint8_t *> _inputDataPtrs; - uint8_t *_outputData; - - int32_t _axis; - - std::vector<Shape> _inputShapes; - Shape _outputShape; - - OperandType _inputType; -}; - -} // namespace cpu -} // namespace kernel -} // namespace neurun - -#endif // __NEURUN_KERNEL_CPU_CONCATLAYER_H__ diff --git a/runtimes/neurun/src/kernel/cpu/ConvolutionLayer.cc b/runtimes/neurun/src/kernel/cpu/ConvolutionLayer.cc deleted file mode 100644 index c694fa75f..000000000 --- a/runtimes/neurun/src/kernel/cpu/ConvolutionLayer.cc +++ /dev/null @@ -1,228 +0,0 @@ -/* - * 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 "ConvolutionLayer.h" - -#include "tensorflow/contrib/lite/kernels/internal/optimized/optimized_ops.h" -#include "kernel/cpu/OperationUtils.h" - -#include <mutex> - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -// If possible we will use this static buffer for the tensor. -static constexpr int kStaticBufferSize = 1605632; -static char static_scratch_buffer[kStaticBufferSize]; -static std::mutex executionMutex; - -#define ANDROID_NN_CONV_PARAMETERS(Type) \ - uint32_t height = getSizeOfDimension(_inputShape, 1); \ - uint32_t width = getSizeOfDimension(_inputShape, 2); \ - uint32_t kernelHeight = getSizeOfDimension(_kernelShape, 1); \ - uint32_t kernelWidth = getSizeOfDimension(_kernelShape, 2); \ - uint32_t outHeight = getSizeOfDimension(_outputShape, 1); \ - uint32_t outWidth = getSizeOfDimension(_outputShape, 2); \ - uint32_t inDepth = getSizeOfDimension(_inputShape, 3); \ - \ - uint32_t paddingHeight = (uint32_t)_paddingTop; \ - uint32_t paddingWidth = (uint32_t)_paddingLeft; \ - \ - Shape im2colShape; \ - im2colShape.dimensions.resize(4); \ - im2colShape.dimensions[0] = getSizeOfDimension(_outputShape, 0); \ - im2colShape.dimensions[1] = getSizeOfDimension(_outputShape, 1); \ - im2colShape.dimensions[2] = getSizeOfDimension(_outputShape, 2); \ - im2colShape.dimensions[3] = inDepth * kernelHeight * kernelWidth; \ - \ - Type *im2colData = nullptr; \ - uint64_t im2colByteSize = sizeof(Type); \ - std::unique_ptr<Type[]> im2colGuard; \ - for (int i = 0; i < 4; i++) \ - { \ - im2colByteSize *= im2colShape.dimensions[i]; \ - } \ - /* http://b/77982879, tflite::optimized_ops::Conv uses int for offsets */ \ - if (im2colByteSize >= 0x7fffffff) \ - { \ - std::cout << "Conv size is too large, not enough memory" << std::endl; \ - return false; \ - } \ - if (im2colByteSize <= kStaticBufferSize) \ - { \ - im2colData = reinterpret_cast<Type *>(static_scratch_buffer); \ - } \ - else \ - { \ - im2colData = new (std::nothrow) Type[im2colByteSize / sizeof(Type)]; \ - if (im2colData == nullptr) \ - { \ - std::cout << "Conv size is too large, not enough memory" << std::endl; \ - return false; \ - } \ - im2colGuard.reset(im2colData); \ - } - -ConvolutionLayer::ConvolutionLayer() - : _inputData(nullptr), _kernelData(nullptr), _outputData(nullptr), _biasData(nullptr), - _inputShape(), _kernelShape(), _outputShape(), _biasShape(), _paddingLeft(0), _paddingTop(0), - _paddingRight(0), _paddingBottom(0), _strideWidth(0), _strideHeight(0), - _activation(ANEURALNETWORKS_FUSED_NONE), _inputType(OperandType::SCALAR_FLOAT32) -{ - // DO NOTHING -} - -bool ConvolutionLayer::convFloat32() -{ - ANDROID_NN_CONV_PARAMETERS(float) - - const ::tflite::Dims<4> &kernel_dim = convertShapeToDims(_kernelShape); - const int kernel_width = ArraySize(kernel_dim, 1); - const int kernel_height = ArraySize(kernel_dim, 2); - const bool need_im2col = - _strideWidth != 1 || _strideHeight != 1 || kernel_width != 1 || kernel_height != 1; - - float *im2colDataToPass = nullptr; - if (need_im2col) - { - im2colDataToPass = im2colData; - } - - float output_activation_min, output_activation_max; - CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max); - int32_t dilationWidthFactor = 1, dilationHeightFactor = 1; - - ::tflite::ConvParams op_params; - op_params.padding_type = ::tflite::PaddingType::kSame; - op_params.padding_values.width = paddingWidth; - op_params.padding_values.height = paddingHeight; - op_params.stride_width = _strideWidth; - op_params.stride_height = _strideHeight; - op_params.dilation_width_factor = dilationWidthFactor; - op_params.dilation_height_factor = dilationHeightFactor; - op_params.float_activation_min = output_activation_min; - op_params.float_activation_max = output_activation_max; - - ::tflite::optimized_ops::Conv( - op_params, convertShapeToTFLiteShape(_inputShape), - reinterpret_cast<const float *>(_inputData), convertShapeToTFLiteShape(_kernelShape), - reinterpret_cast<const float *>(_kernelData), convertShapeToTFLiteShape(_biasShape), - reinterpret_cast<const float *>(_biasData), convertShapeToTFLiteShape(_outputShape), - reinterpret_cast<float *>(_outputData), convertShapeToTFLiteShape(im2colShape), - im2colDataToPass); - return true; -} - -bool ConvolutionLayer::convQuant8() -{ - ANDROID_NN_CONV_PARAMETERS(uint8_t) - - int32_t inputOffset = -_inputShape.offset; - int32_t kernelOffset = -_kernelShape.offset; - int32_t outputOffset = _outputShape.offset; - float real_multiplier = 0.0; - int32_t output_multiplier = 0; - int32_t output_shift = 0; - int32_t output_activation_min = 0; - int32_t output_activation_max = 0; - if (!GetQuantizedConvolutionMultipler(_inputShape, _kernelShape, _biasShape, _outputShape, - &real_multiplier) || - !QuantizeMultiplierSmallerThanOne(real_multiplier, &output_multiplier, &output_shift)) - { - return false; - } - CalculateActivationRangeUint8(_activation, _outputShape, &output_activation_min, - &output_activation_max); - int32_t dilationWidthFactor = 1, dilationHeightFactor = 1; - - ::tflite::ConvParams op_params; - op_params.padding_type = ::tflite::PaddingType::kSame; - op_params.padding_values.width = paddingWidth; - op_params.padding_values.height = paddingHeight; - op_params.stride_width = _strideWidth; - op_params.stride_height = _strideHeight; - op_params.dilation_width_factor = dilationWidthFactor; - op_params.dilation_height_factor = dilationHeightFactor; - op_params.input_offset = inputOffset; - op_params.weights_offset = kernelOffset; - op_params.output_offset = outputOffset; - op_params.output_multiplier = output_multiplier; - op_params.output_shift = output_shift; - op_params.quantized_activation_min = output_activation_min; - op_params.quantized_activation_max = output_activation_max; - - static gemmlowp::GemmContext gemm_context; - // Prevent concurrent executions that may access the scratch buffer and - // gemm_context. - std::unique_lock<std::mutex> lock(executionMutex); - // Alow gemmlowp automatically decide how many threads to use. - gemm_context.set_max_num_threads(0); - ::tflite::optimized_ops::Conv( - op_params, convertShapeToTFLiteShape(_inputShape), _inputData, - convertShapeToTFLiteShape(_kernelShape), _kernelData, convertShapeToTFLiteShape(_biasShape), - reinterpret_cast<const int32_t *>(_biasData), convertShapeToTFLiteShape(_outputShape), - _outputData, convertShapeToTFLiteShape(im2colShape), im2colData, &gemm_context); - return true; -} - -void ConvolutionLayer::configure(uint8_t *inputData, const Shape inputShape, uint8_t *kernelData, - const Shape kernelShape, uint8_t *biasData, const Shape biasShape, - const uint32_t paddingLeft, const uint32_t paddingRight, - const uint32_t paddingTop, const uint32_t paddingBottom, - const uint32_t strideWidth, const uint32_t strideHeight, - const FuseCode activation, uint8_t *outputData, - const Shape outputShape) -{ - _inputData = inputData; - _inputShape = inputShape; - _inputType = inputShape.type; - _kernelData = kernelData; - _kernelShape = kernelShape; - _biasData = biasData; - _biasShape = biasShape; - _paddingLeft = paddingLeft; - _paddingRight = paddingRight; - _paddingTop = paddingTop; - _paddingBottom = paddingBottom; - _strideWidth = strideWidth; - _strideHeight = strideHeight; - _activation = activation; - _outputData = outputData; - _outputShape = outputShape; -} - -void ConvolutionLayer::run() -{ - if (_inputType == OperandType::TENSOR_FLOAT32) - { - convFloat32(); - } - else if (_inputType == OperandType::TENSOR_QUANT8_ASYMM) - { - throw std::runtime_error{"ConvolutionLayer : Not tested for TENSOR_QUANT8_ASYMM"}; - // convQuant8(); - } -} - -#undef ANDROID_NN_CONV_PARAMETERS - -} // namespace cpu -} // namespace kernel -} // namespace neurun diff --git a/runtimes/neurun/src/kernel/cpu/ConvolutionLayer.h b/runtimes/neurun/src/kernel/cpu/ConvolutionLayer.h deleted file mode 100644 index 9b7f55ff1..000000000 --- a/runtimes/neurun/src/kernel/cpu/ConvolutionLayer.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 __NEURUN_KERNEL_CPU_CONVOLUTIONLAYER_H__ -#define __NEURUN_KERNEL_CPU_CONVOLUTIONLAYER_H__ - -#include <NeuralNetworks.h> - -#include "exec/interface/IFunction.h" - -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -class ConvolutionLayer : public ::neurun::exec::IFunction -{ -public: - ConvolutionLayer(); - -public: - bool convFloat32(); - - bool convQuant8(); - - void configure(uint8_t *inputData, const Shape inputShape, uint8_t *kernelData, - const Shape kernelShape, uint8_t *biasData, const Shape biasShape, - const uint32_t paddingLeft, const uint32_t paddingRight, const uint32_t paddingTop, - const uint32_t paddingBottom, const uint32_t strideW, const uint32_t strideH, - const FuseCode activation, uint8_t *outputData, const Shape outputShape); - - void run(); - -private: - uint8_t *_inputData; - uint8_t *_kernelData; - uint8_t *_outputData; - uint8_t *_biasData; - - Shape _inputShape; - Shape _kernelShape; - Shape _outputShape; - Shape _biasShape; - - uint32_t _paddingLeft; - uint32_t _paddingTop; - uint32_t _paddingRight; - uint32_t _paddingBottom; - - uint32_t _strideWidth; - uint32_t _strideHeight; - - FuseCode _activation; - - OperandType _inputType; -}; - -} // namespace cpu -} // namespace kernel -} // namespace neurun - -#endif // __NEURUN_KERNEL_CPU_CONVOLUTIONLAYER_H__ diff --git a/runtimes/neurun/src/kernel/cpu/FullyConnectedLayer.cc b/runtimes/neurun/src/kernel/cpu/FullyConnectedLayer.cc deleted file mode 100644 index abe82db5e..000000000 --- a/runtimes/neurun/src/kernel/cpu/FullyConnectedLayer.cc +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * Copyright (C) 2017 The Android Open Source Project - * - * 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 "FullyConnectedLayer.h" - -#include "tensorflow/contrib/lite/kernels/internal/optimized/optimized_ops.h" -#include "tensorflow/contrib/lite/kernels/internal/reference/reference_ops.h" -#include "kernel/cpu/OperationUtils.h" - -#include <mutex> - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -FullyConnectedLayer::FullyConnectedLayer() - : _inputData(nullptr), _weightsData(nullptr), _biasData(nullptr), _outputData(nullptr), - _inputShape(), _weightsShape(), _biasShape(), _outputShape(), - _activation(ANEURALNETWORKS_FUSED_NONE), _inputType(OperandType::SCALAR_FLOAT32) -{ - // DO NOTHING -} - -// executionMutex is used to protect concurrent access of non-threadsafe resources -// like gemmlowp::GemmContext. -// std::mutex is safe for pthreads on Android. -static std::mutex executionMutex; -bool FullyConnectedLayer::fullyConnectedFloat32() -{ - int total_input_size = 1; - for (int i = 0; i < _inputShape.dimensions.size(); i++) - { - total_input_size *= _inputShape.dimensions[i]; - } - - int input_size = _weightsShape.dimensions[1]; - const int batch_size = total_input_size / input_size; - const int num_units = _weightsShape.dimensions[0]; - - TfLiteFusedActivation act = convertFusedActivation(_activation); - - ::tflite::tensor_utils::VectorBatchVectorAssign(reinterpret_cast<const float *>(_biasData), - num_units, batch_size, - reinterpret_cast<float *>(_outputData)); - - // Compute output += weight * input - ::tflite::tensor_utils::MatrixBatchVectorMultiplyAccumulate( - reinterpret_cast<const float *>(_weightsData), num_units, input_size, - reinterpret_cast<const float *>(_inputData), batch_size, - reinterpret_cast<float *>(_outputData), /*result_stride=*/1); - - // Apply activation function - ::tflite::tensor_utils::ApplyActivationToVector(reinterpret_cast<float *>(_outputData), - batch_size * num_units, act, - reinterpret_cast<float *>(_outputData)); - - return true; -} - -bool FullyConnectedLayer::fullyConnectedQuant8() -{ - throw std::runtime_error{"FullyConnectedLayer : Not tested for TENSOR_QUANT8_ASYMM"}; -} - -void FullyConnectedLayer::configure(uint8_t *inputData, const Shape inputShape, - uint8_t *weightsData, const Shape weightsShape, - uint8_t *biasData, const Shape biasShape, FuseCode activation, - uint8_t *outputData, const Shape outputShape) -{ - _inputData = inputData; - _inputShape = inputShape; - _inputType = inputShape.type; - _weightsData = weightsData; - _weightsShape = weightsShape; - _biasData = biasData; - _biasShape = biasShape; - _activation = activation; - _outputData = outputData; - _outputShape = outputShape; -} - -void FullyConnectedLayer::run() -{ - if (_inputType == OperandType::TENSOR_FLOAT32) - { - fullyConnectedFloat32(); - } - else if (_inputType == OperandType::TENSOR_QUANT8_ASYMM) - { - throw std::runtime_error{"FullyConnectedLayer : Not tested for TENSOR_QUANT8_ASYMM"}; - // fullyConnectedQuant8(); - } -} - -} // namespace cpu -} // namespace kernel -} // namespace neurun diff --git a/runtimes/neurun/src/kernel/cpu/FullyConnectedLayer.h b/runtimes/neurun/src/kernel/cpu/FullyConnectedLayer.h deleted file mode 100644 index 20a388349..000000000 --- a/runtimes/neurun/src/kernel/cpu/FullyConnectedLayer.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 __NEURUN_KERNEL_CPU_FULLYCONNECTEDLAYER_H__ -#define __NEURUN_KERNEL_CPU_FULLYCONNECTEDLAYER_H__ - -#include <NeuralNetworks.h> - -#include "exec/interface/IFunction.h" - -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -class FullyConnectedLayer : public ::neurun::exec::IFunction -{ -public: - FullyConnectedLayer(); - -public: - bool fullyConnectedFloat32(); - - bool fullyConnectedQuant8(); - - void configure(uint8_t *inputData, const Shape inputShape, uint8_t *weightsData, - const Shape weightsShape, uint8_t *biasData, const Shape biasShape, - FuseCode activation, uint8_t *outputData, const Shape outputShape); - - void run(); - -private: - uint8_t *_inputData; - uint8_t *_weightsData; - uint8_t *_biasData; - uint8_t *_outputData; - - Shape _inputShape; - Shape _weightsShape; - Shape _biasShape; - Shape _outputShape; - - FuseCode _activation; - - OperandType _inputType; -}; - -} // namespace cpu -} // namespace kernel -} // namespace neurun - -#endif // __NEURUN_KERNEL_CPU_FULLYCONNECTEDLAYER_H__ diff --git a/runtimes/neurun/src/kernel/cpu/MaxPoolLayer.cc b/runtimes/neurun/src/kernel/cpu/MaxPoolLayer.cc deleted file mode 100644 index c4a288b07..000000000 --- a/runtimes/neurun/src/kernel/cpu/MaxPoolLayer.cc +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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 "MaxPoolLayer.h" - -#include "tensorflow/contrib/lite/kernels/internal/optimized/optimized_ops.h" -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -#define MAXPOOLING_PARAMETERS \ - tflite::PoolParams op_params; \ - op_params.stride_height = _strideHeight; \ - op_params.stride_width = _strideWidth; \ - op_params.filter_height = _kernelHeight; \ - op_params.filter_width = _kernelWidth; \ - op_params.padding_values.height = (int8_t)_paddingTop; \ - op_params.padding_values.width = (int8_t)_paddingLeft; - -MaxPoolLayer::MaxPoolLayer() - : _inputData(nullptr), _outputData(nullptr), _inputShape(), _outputShape(), _paddingLeft(0), - _paddingTop(0), _paddingRight(0), _paddingBottom(0), _strideWidth(0), _strideHeight(0), - _kernelWidth(0), _kernelHeight(0), _activation(ANEURALNETWORKS_FUSED_NONE), - _inputType(OperandType::SCALAR_FLOAT32) -{ - // DO NOTHING -} - -bool MaxPoolLayer::maxPoolFloat32() -{ - MAXPOOLING_PARAMETERS - float output_activation_min, output_activation_max; - CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max); - op_params.float_activation_min = output_activation_min; - op_params.float_activation_max = output_activation_max; - - ::tflite::optimized_ops::MaxPool(op_params, convertShapeToTFLiteShape(_inputShape), - reinterpret_cast<const float *>(_inputData), - convertShapeToTFLiteShape(_outputShape), - reinterpret_cast<float *>(_outputData)); - return true; -} -bool MaxPoolLayer::maxPoolQuant8() -{ - MAXPOOLING_PARAMETERS - int32_t output_activation_min = 0; - int32_t output_activation_max = 0; - CalculateActivationRangeUint8(_activation, _outputShape, &output_activation_min, - &output_activation_max); - op_params.quantized_activation_min = output_activation_min; - op_params.quantized_activation_max = output_activation_max; - - ::tflite::optimized_ops::MaxPool(op_params, convertShapeToTFLiteShape(_inputShape), _inputData, - convertShapeToTFLiteShape(_outputShape), _outputData); - return true; -} - -void MaxPoolLayer::configure(uint8_t *inputData, const Shape inputShape, const uint32_t paddingLeft, - const uint32_t paddingRight, const uint32_t paddingTop, - const uint32_t paddingBottom, const uint32_t strideWidth, - const uint32_t strideHeight, const uint32_t kernelWidth, - const uint32_t kernelHeight, const FuseCode activation, - uint8_t *outputData, const Shape outputShape) -{ - _inputData = inputData; - - _inputShape = inputShape; - _inputType = inputShape.type; - _paddingLeft = paddingLeft; - _paddingRight = paddingRight; - _paddingTop = paddingTop; - _paddingBottom = paddingBottom; - _strideWidth = strideWidth; - _strideHeight = strideHeight; - _kernelWidth = kernelWidth; - _kernelHeight = kernelHeight; - _activation = activation; - _outputData = outputData; - _outputShape = outputShape; -} - -void MaxPoolLayer::run() -{ - if (_inputType == OperandType::TENSOR_FLOAT32) - { - maxPoolFloat32(); - } - else if (_inputType == OperandType::TENSOR_QUANT8_ASYMM) - { - throw std::runtime_error{"MaxPoolLayer : Not tested for TENSOR_QUANT8_ASYMM"}; - // maxPoolQuant8(); - } -} - -#undef MAXPOOLING_PARAMETERS - -} // namespace cpu -} // namespace kernel -} // namespace neurun diff --git a/runtimes/neurun/src/kernel/cpu/MaxPoolLayer.h b/runtimes/neurun/src/kernel/cpu/MaxPoolLayer.h deleted file mode 100644 index 2b185550b..000000000 --- a/runtimes/neurun/src/kernel/cpu/MaxPoolLayer.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * 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 __NEURUN_KERNEL_CPU_MAXPOOLLAYER_H__ -#define __NEURUN_KERNEL_CPU_MAXPOOLLAYER_H__ - -#include <NeuralNetworks.h> - -#include "exec/interface/IFunction.h" - -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -class MaxPoolLayer : public ::neurun::exec::IFunction -{ -public: - MaxPoolLayer(); - -public: - bool maxPoolFloat32(); - - bool maxPoolQuant8(); - - void configure(uint8_t *inputData, const Shape inputShape, const uint32_t paddingLeft, - const uint32_t paddingRight, const uint32_t paddingTop, - const uint32_t paddingBottom, const uint32_t strideWidth, - const uint32_t strideHeight, const uint32_t kernelWidth, - const uint32_t kernelHeight, const FuseCode activation, uint8_t *outputData, - const Shape outputShape); - - void run(); - -private: - uint8_t *_inputData; - uint8_t *_outputData; - - Shape _inputShape; - Shape _outputShape; - - uint32_t _paddingLeft; - uint32_t _paddingTop; - uint32_t _paddingRight; - uint32_t _paddingBottom; - - uint32_t _strideWidth; - uint32_t _strideHeight; - uint32_t _kernelWidth; - uint32_t _kernelHeight; - - FuseCode _activation; - - OperandType _inputType; -}; - -} // namespace cpu -} // namespace kernel -} // namespace neurun - -#endif // __NEURUN_KERNEL_CPU_MAXPOOLLAYER_H__ diff --git a/runtimes/neurun/src/kernel/cpu/OperationUtils.cc b/runtimes/neurun/src/kernel/cpu/OperationUtils.cc deleted file mode 100644 index b28508c27..000000000 --- a/runtimes/neurun/src/kernel/cpu/OperationUtils.cc +++ /dev/null @@ -1,230 +0,0 @@ -/* - * 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 "kernel/cpu/OperationUtils.h" - -#include <cmath> -#include <algorithm> -#include <cassert> - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -uint32_t getNumberOfDimensions(const Shape &shape) { return shape.dimensions.size(); } - -uint32_t getNumberOfElements(const Shape &shape) -{ - uint32_t count = 1; - for (size_t i = 0; i < shape.dimensions.size(); i++) - { - count *= shape.dimensions[i]; - } - return count; -} - -uint32_t getSizeOfDimension(const Shape &shape, uint32_t dimensionIdx) -{ - if (dimensionIdx >= shape.dimensions.size()) - { - // TODO, log the error - return 0; - } - return shape.dimensions[dimensionIdx]; -} - -bool QuantizeMultiplierSmallerThanOne(double double_multiplier, int32_t *quantized_multiplier, - int32_t *right_shift) -{ - assert(double_multiplier >= 0.); - assert(double_multiplier < 1.); - if (double_multiplier == 0.) - { - *quantized_multiplier = 0; - *right_shift = 0; - return true; - } - assert(double_multiplier > 0.); - const double q = std::frexp(double_multiplier, right_shift); - *right_shift *= -1; - int64_t q_fixed = static_cast<int64_t>(std::round(q * (1ll << 31))); - assert(q_fixed <= (1ll << 31)); - if (q_fixed == (1ll << 31)) - { - q_fixed /= 2; - --*right_shift; - } - assert(*right_shift >= 0); - assert(q_fixed <= std::numeric_limits<int32_t>::max()); - *quantized_multiplier = static_cast<int32_t>(q_fixed); - return true; -} - -bool GetQuantizedConvolutionMultipler(const Shape &inputShape, const Shape &filterShape, - const Shape &biasShape, const Shape &outputShape, - float *multiplier) -{ - const float input_product_scale = inputShape.scale * filterShape.scale; - const float bias_scale = biasShape.scale; - const float output_scale = outputShape.scale; - // The following conditions must be guaranteed by the training pipeline. - assert(std::abs(input_product_scale - bias_scale) <= - 1e-6 * std::min(input_product_scale, bias_scale)); - assert(input_product_scale >= 0); - assert(input_product_scale < output_scale); - *multiplier = input_product_scale / output_scale; - return true; -} - -bool QuantizeMultiplierGreaterThanOne(double double_multiplier, int32_t *quantized_multiplier, - int *left_shift) -{ - assert(double_multiplier > 1.); - const double q = std::frexp(double_multiplier, left_shift); - int64_t q_fixed = static_cast<int64_t>(std::round(q * (1ll << 31))); - assert(q_fixed <= (1ll << 31)); - if (q_fixed == (1ll << 31)) - { - q_fixed /= 2; - ++*left_shift; - } - assert(*left_shift >= 0); - assert(q_fixed <= std::numeric_limits<int32_t>::max()); - *quantized_multiplier = static_cast<int32_t>(q_fixed); - return true; -} - -void CalculateActivationRangeFloat(int32_t activation, float *activation_min, float *activation_max) -{ - if (activation == ANEURALNETWORKS_FUSED_RELU) - { - *activation_min = 0.f; - *activation_max = std::numeric_limits<float>::max(); - } - else if (activation == ANEURALNETWORKS_FUSED_RELU6) - { - *activation_min = 0.f; - *activation_max = 6.f; - } - else if (activation == ANEURALNETWORKS_FUSED_RELU1) - { - *activation_min = -1.f; - *activation_max = 1.f; - } - else if (activation == ANEURALNETWORKS_FUSED_NONE) - { - *activation_min = std::numeric_limits<float>::lowest(); - *activation_max = std::numeric_limits<float>::max(); - } - else - { - std::cout << "Unsupported fused activation function." << std::endl; - } -} - -void CalculateActivationRangeUint8(int32_t activation, const Shape &outputShape, int32_t *act_min, - int32_t *act_max) -{ - const int32_t qmin = std::numeric_limits<uint8_t>::min(); - const int32_t qmax = std::numeric_limits<uint8_t>::max(); - const auto scale = outputShape.scale; - const auto zero_point = outputShape.offset; - auto quantize = [scale, zero_point](float f) { - return zero_point + static_cast<int32_t>(std::round(f / scale)); - }; - if (activation == ANEURALNETWORKS_FUSED_RELU) - { - *act_min = std::max(qmin, quantize(0.0)); - *act_max = qmax; - } - else if (activation == ANEURALNETWORKS_FUSED_RELU6) - { - *act_min = std::max(qmin, quantize(0.0)); - *act_max = std::min(qmax, quantize(6.0)); - } - else if (activation == ANEURALNETWORKS_FUSED_RELU1) - { - *act_min = std::max(qmin, quantize(-1.0)); - *act_max = std::min(qmax, quantize(1.0)); - } - else if (activation == ANEURALNETWORKS_FUSED_NONE) - { - *act_min = qmin; - *act_max = qmax; - } - else - { - std::cout << "Unsupported fused activation function." << std::endl; - } -} - -int32_t CalculateInputRadius(int input_integer_bits, int input_left_shift) -{ - const double max_input_rescaled = 1.0 * ((1 << input_integer_bits) - 1) * - (1ll << (31 - input_integer_bits)) / (1ll << input_left_shift); - // Tighten bound using floor. Suppose that we could use the exact value. - // After scaling the difference, the result would be at the maximum. Thus we - // must ensure that our value has lower magnitude. - return static_cast<int32_t>(std::floor(max_input_rescaled)); -} - -Shape getShape(const ::neurun::model::operand::Object &o) -{ - Shape shape; - - shape.type = static_cast<OperandType>(static_cast<int32_t>(o.typeInfo().type())); - shape.dimensions = std::vector<uint32_t>(o.shape().dims().begin(), o.shape().dims().end()); - shape.scale = o.typeInfo().scale(); - // shape.offset = _offset; - - return shape; -} - -size_t sizeOfData(OperandType type, const std::vector<uint32_t> &dimensions) -{ - size_t size = 4; - - switch (type) - { - case OperandType::SCALAR_FLOAT32: - case OperandType::SCALAR_INT32: - case OperandType::SCALAR_UINT32: - case OperandType::TENSOR_FLOAT32: - case OperandType::TENSOR_INT32: - size = 4; - break; - case OperandType::TENSOR_QUANT8_ASYMM: - size = 1; - break; - default: - throw std::runtime_error("Not supported operand type."); - break; - } - - for (auto d : dimensions) - { - size *= d; - } - - return size; -} - -} // namespace cpu -} // namespace kernel -} // namespace neurun diff --git a/runtimes/neurun/src/kernel/cpu/OperationUtils.h b/runtimes/neurun/src/kernel/cpu/OperationUtils.h deleted file mode 100644 index 3610990a5..000000000 --- a/runtimes/neurun/src/kernel/cpu/OperationUtils.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * 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 __NNFW_SUPPORT_NNAPI_OPERATION_UTILS_H__ -#define __NNFW_SUPPORT_NNAPI_OPERATION_UTILS_H__ - -#include <NeuralNetworks.h> - -#include <iostream> -#include <limits> -#include <vector> - -#include "tensorflow/contrib/lite/c/builtin_op_data.h" -#include "tensorflow/contrib/lite/kernels/internal/types.h" -#include "tensorflow/contrib/lite/kernels/internal/tensor.h" -#include "model/operand/Object.h" -#include "model/operand/DataType.h" - -using OperandType = neurun::model::operand::DataType; - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -struct Shape -{ - OperandType type; - std::vector<uint32_t> dimensions; - float scale; - int32_t offset; -}; - -uint32_t getNumberOfDimensions(const Shape &shape); - -uint32_t getNumberOfElements(const Shape &shape); - -uint32_t getSizeOfDimension(const Shape &shape, uint32_t dimensionIdx); - -inline ::tflite::Dims<4> convertShapeToDims(const Shape &shape) -{ - // nnAssert(shape.dimensions.size() <= 4); - ::tflite::Dims<4> dims; - // The dimensions are reversed in Dims<4>. - for (int i = 0; i < 4; ++i) - { - int src = static_cast<int>(shape.dimensions.size()) - i - 1; - if (src >= 0) - { - dims.sizes[i] = static_cast<int>(getSizeOfDimension(shape, src)); - } - else - { - dims.sizes[i] = 1; - } - } - dims.strides[0] = 1; - for (int i = 1; i < 4; i++) - { - dims.strides[i] = dims.strides[i - 1] * dims.sizes[i - 1]; - } - return dims; -} - -inline ::tflite::RuntimeShape convertShapeToTFLiteShape(const Shape &shape) -{ - std::vector<int32_t> raw_shape; - raw_shape.resize(4); - - for (uint32_t i = 0; i < 4; ++i) - { - if (i >= shape.dimensions.size()) - { - raw_shape[i] = 1; - } - else - { - raw_shape[i] = shape.dimensions[i]; - } - } - - return ::tflite::GetTensorShape(raw_shape); -} - -inline TfLiteFusedActivation convertFusedActivation(FuseCode act) -{ - if (act == ANEURALNETWORKS_FUSED_NONE) - { - return kTfLiteActNone; - } - - if (act == ANEURALNETWORKS_FUSED_RELU) - { - return kTfLiteActRelu; - } - - if (act == ANEURALNETWORKS_FUSED_RELU1) - { - return kTfLiteActRelu1; - } - - if (act == ANEURALNETWORKS_FUSED_RELU6) - { - return kTfLiteActRelu6; - } - - return kTfLiteActNone; -} - -__wur bool QuantizeMultiplierSmallerThanOne(double double_multiplier, int32_t *quantized_multiplier, - int32_t *right_shift); - -__wur bool GetQuantizedConvolutionMultipler(const Shape &inputShape, const Shape &filterShape, - const Shape &biasShape, const Shape &outputShape, - float *multiplier); -__wur bool QuantizeMultiplierGreaterThanOne(double double_multiplier, int32_t *quantized_multiplier, - int *left_shift); - -void CalculateActivationRangeFloat(int32_t activation, float *activation_min, - float *activation_max); - -void CalculateActivationRangeUint8(int32_t activation, const Shape &outputShape, int32_t *act_min, - int32_t *act_max); - -int32_t CalculateInputRadius(int input_integer_bits, int input_left_shift); - -Shape getShape(const ::neurun::model::operand::Object &o); - -uint32_t sizeOfData(OperandType type, const std::vector<uint32_t> &dimensions); - -} // namespace cpu -} // namespace kernel -} // namespace neurun - -#endif // __NNFW_SUPPORT_NNAPI_OPERATION_UTILS_H__ diff --git a/runtimes/neurun/src/kernel/cpu/PermuteLayer.cc b/runtimes/neurun/src/kernel/cpu/PermuteLayer.cc deleted file mode 100644 index ba8c5ab92..000000000 --- a/runtimes/neurun/src/kernel/cpu/PermuteLayer.cc +++ /dev/null @@ -1,201 +0,0 @@ -/* - * 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 "PermuteLayer.h" - -#include "util/feature/nhwc/Reader.h" -#include "util/feature/nhwc/View.h" -#include "util/feature/nchw/View.h" -#include "util/feature/Coordinate4D.h" - -#include <misc/feature/IndexIterator.h> - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -using Type = model::operation::PermuteNode::Type; - -void PermuteLayer::configure(std::shared_ptr<::neurun::backend::operand::IObject> input, - std::shared_ptr<::neurun::backend::operand::IObject> output, - const model::operand::Shape &shape, Type type) -{ - _input = input; - _output = output; - _shape = shape; - _type = type; -} - -void PermuteLayer::run() -{ - auto rank = _shape.rank(); - - switch (_type) - { - case Type::NHWC_TO_NCHW: - { - auto fn = [&](::neurun::backend::operand::ITensor &tensor) { - auto input_tensor = _input->ptr(); - - auto input_buffer = input_tensor->buffer(); - auto input_size = input_tensor->total_size(); - - auto output_buffer = tensor.buffer(); - auto output_size = tensor.total_size(); - switch (rank) - { - case 0: - case 1: - { - memcpy(output_buffer, input_buffer, input_size); - break; - } - case 2: - { - auto matrix_shape = _shape.asMatrix(); - - for (auto h = 0; h < matrix_shape.H; ++h) - { - neurun::util::feature::Coordinate4D coord{0, h, 0, 0}; - memcpy(output_buffer + tensor.calcOffset(coord), input_buffer + h * matrix_shape.W, - matrix_shape.W * sizeof(float)); - } - break; - } - case 3: - { - const int32_t depth = _shape.dim(0); - const int32_t height = _shape.dim(1); - const int32_t width = _shape.dim(2); - - for (auto c = 0; c < depth; ++c) - { - for (auto h = 0; h < height; ++h) - { - neurun::util::feature::Coordinate4D coord{0, h, 0, c}; - memcpy(output_buffer + tensor.calcOffset(coord), - input_buffer + c * height * width + h * width, width * sizeof(float)); - } - } - break; - } - case 4: - { - auto feature = _shape.asFeature(); - - const util::feature::nhwc::Reader<float> from{ - feature, reinterpret_cast<const float *>(input_buffer), input_size}; - util::feature::nchw::View<float> into{&tensor}; - - ::nnfw::misc::feature::iterate(feature) - << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) { - const auto value = from.at(batch, ch, row, col); - into.at(batch, ch, row, col) = value; - }; - break; - } - default: - throw "NYI"; - break; - } - }; - _output->access(fn); - break; - } - case Type::NCHW_TO_NHWC: - { - auto fn = [&](::neurun::backend::operand::ITensor &tensor) { - auto input_buffer = tensor.buffer(); - auto input_size = tensor.total_size(); - - auto output_tensor = _output->ptr(); - - auto output_buffer = output_tensor->buffer(); - auto output_size = output_tensor->total_size(); - - switch (rank) - { - case 0: - case 1: - { - memcpy(output_buffer, input_buffer, output_size); - break; - } - case 2: - { - auto matrix_shape = _shape.asMatrix(); - - for (auto h = 0; h < matrix_shape.H; ++h) - { - neurun::util::feature::Coordinate4D coord{0, h, 0, 0}; - memcpy(output_buffer + h * matrix_shape.W, input_buffer + tensor.calcOffset(coord), - matrix_shape.W * sizeof(float)); - } - break; - } - case 3: - { - const int32_t depth = _shape.dim(0); - const int32_t height = _shape.dim(1); - const int32_t width = _shape.dim(2); - - for (auto c = 0; c < depth; ++c) - { - for (auto h = 0; h < height; ++h) - { - neurun::util::feature::Coordinate4D coord{0, h, 0, c}; - memcpy(output_buffer + c * height * width + h * width, - input_buffer + tensor.calcOffset(coord), width * sizeof(float)); - } - } - break; - } - case 4: - { - auto feature = _shape.asFeature(); - - const util::feature::nchw::View<float> from{&tensor}; - util::feature::nhwc::View<float> into{feature, reinterpret_cast<float *>(output_buffer), - output_size}; - - ::nnfw::misc::feature::iterate(feature) - << [&](uint32_t batch, uint32_t ch, uint32_t row, uint32_t col) { - const auto value = from.at(batch, ch, row, col); - into.at(batch, ch, row, col) = value; - }; - break; - } - default: - throw "NYI"; - break; - } - }; - _input->access(fn); - break; - } - case Type::COPY: - // If two different backends using same tensor layout, we need this. - throw "NYI"; - break; - } -} - -} // namespace cpu -} // namespace kernel -} // namespace neurun diff --git a/runtimes/neurun/src/kernel/cpu/PermuteLayer.h b/runtimes/neurun/src/kernel/cpu/PermuteLayer.h deleted file mode 100644 index d9e1709bc..000000000 --- a/runtimes/neurun/src/kernel/cpu/PermuteLayer.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 __NEURUN_KERNEL_CPU_PERMUTE_LAYER_H__ -#define __NEURUN_KERNEL_CPU_PERMUTE_LAYER_H__ - -#include <NeuralNetworks.h> - -#include "exec/interface/IFunction.h" - -#include "util/feature/nhwc/View.h" -#include "OperationUtils.h" -#include "backend/interface/operand/IObject.h" -#include "model/operation/PermuteNode.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -class PermuteLayer : public ::neurun::exec::IFunction -{ -public: - PermuteLayer() = default; - -public: - void configure(std::shared_ptr<::neurun::backend::operand::IObject> input, - std::shared_ptr<::neurun::backend::operand::IObject> output, - const model::operand::Shape &shape, model::operation::PermuteNode::Type type); - void run(); - -private: - std::shared_ptr<::neurun::backend::operand::IObject> _input; - std::shared_ptr<::neurun::backend::operand::IObject> _output; - model::operand::Shape _shape; - model::operation::PermuteNode::Type _type; -}; - -} // namespace cpu -} // namespace kernel -} // namespace neurun - -#endif // __NEURUN_KERNEL_CPU_PERMUTE_LAYER_H__ diff --git a/runtimes/neurun/src/kernel/cpu/ReshapeLayer.cc b/runtimes/neurun/src/kernel/cpu/ReshapeLayer.cc deleted file mode 100644 index 377f783e0..000000000 --- a/runtimes/neurun/src/kernel/cpu/ReshapeLayer.cc +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved - * Copyright (C) 2017 The Android Open Source Project - * - * 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 "ReshapeLayer.h" - -#include "tensorflow/contrib/lite/kernels/internal/optimized/optimized_ops.h" -#include "tensorflow/contrib/lite/kernels/internal/reference/reference_ops.h" -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -ReshapeLayer::ReshapeLayer() - : _inputData(nullptr), _outputData(nullptr), _inputShape(), _outputShape() -{ - // DO NOTHING -} - -bool ReshapeLayer::reshapeGeneric() -{ - size_t count = sizeOfData(_inputShape.type, _inputShape.dimensions); - memcpy(reinterpret_cast<void *>(_outputData), reinterpret_cast<const void *>(_inputData), count); - return true; -} - -void ReshapeLayer::configure(uint8_t *inputData, const Shape &inputShape, uint8_t *outputData, - const Shape &outputShape) -{ - _inputData = inputData; - _inputShape = inputShape; - _outputData = outputData; - _outputShape = outputShape; -} - -void ReshapeLayer::run() { reshapeGeneric(); } - -} // namespace cpu -} // namespace kernel -} // namespace neurun diff --git a/runtimes/neurun/src/kernel/cpu/ReshapeLayer.h b/runtimes/neurun/src/kernel/cpu/ReshapeLayer.h deleted file mode 100644 index 51d0bacee..000000000 --- a/runtimes/neurun/src/kernel/cpu/ReshapeLayer.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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 __NEURUN_KERNEL_CPU_RESHAPELAYER_H__ -#define __NEURUN_KERNEL_CPU_RESHAPELAYER_H__ - -#include <NeuralNetworks.h> - -#include "exec/interface/IFunction.h" - -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -class ReshapeLayer : public ::neurun::exec::IFunction -{ -public: - ReshapeLayer(); - -public: - bool reshapeGeneric(); - - void configure(uint8_t *inputData, const Shape &inputShape, uint8_t *outputData, - const Shape &outputShape); - - void run(); - -private: - uint8_t *_inputData; - uint8_t *_outputData; - - Shape _inputShape; - Shape _outputShape; -}; - -} // namespace cpu -} // namespace kernel -} // namespace neurun - -#endif // __NEURUN_KERNEL_CPU_RESHAPELAYER_H__ diff --git a/runtimes/neurun/src/kernel/cpu/SoftMaxLayer.cc b/runtimes/neurun/src/kernel/cpu/SoftMaxLayer.cc deleted file mode 100644 index c998c65f6..000000000 --- a/runtimes/neurun/src/kernel/cpu/SoftMaxLayer.cc +++ /dev/null @@ -1,174 +0,0 @@ -/* - * 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 "SoftMaxLayer.h" - -#include "tensorflow/contrib/lite/kernels/internal/optimized/optimized_ops.h" -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -SoftMaxLayer::SoftMaxLayer() - : _inputData(nullptr), _outputData(nullptr), _beta(0.0), _inputShape(), _outputShape(), - _inputType(OperandType::SCALAR_FLOAT32) -{ - // DO NOTHING -} - -// Performs softmax along the input of size (input_size * batch_size). -void Softmax(const float *in, const int input_size, const int batch_size, const float beta, - float *out) -{ - TF_LITE_ASSERT(input_size > 0); - - // For each batch - for (int b = 0; b < batch_size; b++) - { - // Find the max coeff. - float max_coeff = in[0]; - for (int i = 1; i < input_size; i++) - { - if (in[i] > max_coeff) - max_coeff = in[i]; - } - - // Compute the normalized sum of exps. - float exp_sum = 0.0; - for (int i = 0; i < input_size; i++) - { - out[i] = std::exp((in[i] - max_coeff) * beta); - exp_sum += out[i]; - } - - // Divide by the sum of exps. - float reciprocal_sum_exp = 1.f / exp_sum; - for (int i = 0; i < input_size; i++) - { - out[i] *= reciprocal_sum_exp; - } - - // Advance in and out pointers for the next batch. - in += input_size; - out += input_size; - } -} - -bool SoftMaxLayer::softmaxFloat32() -{ - Shape shapeIn4D; - - if (getNumberOfDimensions(_inputShape) == 2) - { - uint32_t batch_size = getSizeOfDimension(_inputShape, 0); - uint32_t input_size = getNumberOfElements(_inputShape) / batch_size; - Softmax(reinterpret_cast<const float *>(_inputData), input_size, batch_size, _beta, - reinterpret_cast<float *>(_outputData)); - } - else if (getNumberOfDimensions(_inputShape) == 4) - { - ::tflite::SoftmaxParams op_params; - op_params.beta = _beta; - ::tflite::optimized_ops::Softmax(op_params, convertShapeToTFLiteShape(_inputShape), - reinterpret_cast<const float *>(_inputData), - convertShapeToTFLiteShape(_outputShape), - reinterpret_cast<float *>(_outputData)); - } - else - { - std::cout << "only 2D and 4D tensors supported" << std::endl; - return false; - } - - return true; -} - -bool SoftMaxLayer::softmaxQuant8() -{ - Shape shapeIn4D = _inputShape; - - if (getNumberOfDimensions(_inputShape) == 2) - { - uint32_t batch_size = getSizeOfDimension(_inputShape, 0); - uint32_t input_size = getNumberOfElements(_inputShape) / batch_size; - shapeIn4D.dimensions = {batch_size, 1, 1, input_size}; - } - else if (getNumberOfDimensions(_inputShape) == 4) - { - shapeIn4D = _inputShape; - } - else - { - std::cout << "only 2D and 4D tensors supported" << std::endl; - return false; - } - if (_outputShape.offset != 0 || _outputShape.scale != 1.f / 256) - { - std::cout << "incorrect scale / offset for output" << std::endl; - return false; - } - static const int32_t kScaledDiffIntegerBits = 5; - const double input_beta_real_multiplier = std::min( - 1.0 * _beta * _inputShape.scale * (1 << (31 - kScaledDiffIntegerBits)), (1ll << 31) - 1.0); - int32_t input_multiplier = 0; - int32_t input_left_shift = 0; - if (!QuantizeMultiplierGreaterThanOne(input_beta_real_multiplier, &input_multiplier, - &input_left_shift)) - { - return false; - } - float diff_min = -1.0f * CalculateInputRadius(kScaledDiffIntegerBits, input_left_shift); - - ::tflite::SoftmaxParams op_params; - op_params.input_multiplier = input_multiplier; - op_params.input_left_shift = input_left_shift; - op_params.diff_min = diff_min; - ::tflite::optimized_ops::Softmax(op_params, convertShapeToTFLiteShape(shapeIn4D), _inputData, - convertShapeToTFLiteShape(shapeIn4D), _outputData); - return true; -} - -void SoftMaxLayer::configure(uint8_t *inputData, const Shape &inputShape, const float beta, - uint8_t *outputData, const Shape &outputShape) -{ - _inputData = inputData; - _inputShape = inputShape; - _inputType = inputShape.type; - _outputData = outputData; - _outputShape = outputShape; - _beta = beta; -} - -void SoftMaxLayer::run() -{ - if (_inputType == OperandType::TENSOR_FLOAT32) - { - softmaxFloat32(); - } - else if (_inputType == OperandType::TENSOR_QUANT8_ASYMM) - { - throw std::runtime_error{"SoftMaxLayer : Not tested for TENSOR_QUANT8_ASYMM"}; - // softmaxQuant8(); - } -} - -} // namespace cpu -} // namespace kernel -} // namespace neurun diff --git a/runtimes/neurun/src/kernel/cpu/SoftMaxLayer.h b/runtimes/neurun/src/kernel/cpu/SoftMaxLayer.h deleted file mode 100644 index df1aa4044..000000000 --- a/runtimes/neurun/src/kernel/cpu/SoftMaxLayer.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 __NEURUN_KERNEL_CPU_SOFTMAXLAYER_H__ -#define __NEURUN_KERNEL_CPU_SOFTMAXLAYER_H__ - -#include <NeuralNetworks.h> - -#include "exec/interface/IFunction.h" - -#include "kernel/cpu/OperationUtils.h" - -namespace neurun -{ -namespace kernel -{ -namespace cpu -{ - -class SoftMaxLayer : public ::neurun::exec::IFunction -{ -public: - SoftMaxLayer(); - -public: - bool softmaxFloat32(); - - bool softmaxQuant8(); - - void configure(uint8_t *inputData, const Shape &inputShape, const float beta, uint8_t *outputData, - const Shape &outputShape); - - void run(); - -private: - uint8_t *_inputData; - uint8_t *_outputData; - - float _beta; - - Shape _inputShape; - Shape _outputShape; - - OperandType _inputType; -}; - -} // namespace cpu -} // namespace kernel -} // namespace neurun - -#endif // __NEURUN_KERNEL_CPU_SOFTMAXLAYER_H__ |