diff options
author | Chunseok Lee <chunseok.lee@samsung.com> | 2020-04-23 14:45:49 +0900 |
---|---|---|
committer | Chunseok Lee <chunseok.lee@samsung.com> | 2020-04-23 14:45:49 +0900 |
commit | e2ef8438a24f7c56a0744eb579a6e293ee2fbf8e (patch) | |
tree | 44a1a7951d168dd4370e13593ed03f4bc6d920c5 /runtime/onert/backend/cpu/kernel | |
parent | 302e6564a7a76109e1178207e44e45a58631c477 (diff) | |
download | nnfw-e2ef8438a24f7c56a0744eb579a6e293ee2fbf8e.tar.gz nnfw-e2ef8438a24f7c56a0744eb579a6e293ee2fbf8e.tar.bz2 nnfw-e2ef8438a24f7c56a0744eb579a6e293ee2fbf8e.zip |
Imported Upstream version 1.4.0upstream/1.4.0submit/tizen/20200423.054851
Diffstat (limited to 'runtime/onert/backend/cpu/kernel')
70 files changed, 6290 insertions, 0 deletions
diff --git a/runtime/onert/backend/cpu/kernel/AbsLayer.cc b/runtime/onert/backend/cpu/kernel/AbsLayer.cc new file mode 100644 index 000000000..770386826 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/AbsLayer.cc @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020 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 "AbsLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Elementwise.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +AbsLayer::AbsLayer() : _input(nullptr), _output(nullptr) +{ + // DO NOTHING +} + +void AbsLayer::absFloat32() +{ + nnfw::cker::Abs(convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void AbsLayer::absQuant8() { throw std::runtime_error{"NYI"}; } + +void AbsLayer::configure(const operand::Tensor *input, operand::Tensor *output) +{ + _input = input; + _output = output; +} + +void AbsLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + absFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + absQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/AbsLayer.h b/runtime/onert/backend/cpu/kernel/AbsLayer.h new file mode 100644 index 000000000..551782a45 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/AbsLayer.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020 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 riting, 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 __ONERT_BACKEND_CPU_KERNEL_ABSLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_ABSLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class AbsLayer : public ::onert::exec::IFunction +{ +public: + AbsLayer(); + +public: + void absFloat32(); + + void absQuant8(); + + void configure(const operand::Tensor *input, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_ABSLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/AddLayer.cc b/runtime/onert/backend/cpu/kernel/AddLayer.cc new file mode 100644 index 000000000..51320907d --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/AddLayer.cc @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019 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 "AddLayer.h" + +#include <cker/operation/BinaryArithmeticOps.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +void AddLayer::addFloat32() +{ + float output_activation_min, output_activation_max; + CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max); + nnfw::cker::BinaryArithmeticOpParam op_params; + op_params.type = nnfw::cker::BinaryArithmeticOpType::ADD; + op_params.float_activation_max = output_activation_max; + op_params.float_activation_min = output_activation_min; + + if (!HaveSameShapes(_lhs, _rhs)) + { + nnfw::cker::BroadcastBinaryArithmeticOpSlow( + op_params, convertToExtendedCkerShape(_lhs), + reinterpret_cast<const float *>(_lhs->buffer()), convertToExtendedCkerShape(_rhs), + reinterpret_cast<const float *>(_rhs->buffer()), convertToExtendedCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); + return; + } + + nnfw::cker::BinaryArithmeticOp( + op_params, convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()), + convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void AddLayer::addQuant8() +{ + int32_t output_activation_min, output_activation_max; + CalculateActivationRangeUint8(_activation, _output, &output_activation_min, + &output_activation_max); + // nnfw::cker::BinaryArithmeticOpParam op_params; + // op_params.quantized_activation_max = output_activation_max; + // op_params.quantized_activation_min = output_activation_min; + + // cker quant8 add is not implemented yet + throw std::runtime_error{"NYI"}; +} + +void AddLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + const ir::Activation activation, operand::Tensor *output) +{ + assert(lhs != nullptr); + assert(rhs != nullptr); + assert(output != nullptr); + + _lhs = lhs; + _rhs = rhs; + _activation = activation; + _output = output; +} + +void AddLayer::run() +{ + if (_lhs->data_type() == OperandType::FLOAT32) + { + addFloat32(); + } + else if (_lhs->data_type() == OperandType::QUANT8_ASYMM) + { + addQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/AddLayer.h b/runtime/onert/backend/cpu/kernel/AddLayer.h new file mode 100644 index 000000000..657decc72 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/AddLayer.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 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 __ONERT_BACKEND_CPU_KERNEL_ADDLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_ADDLAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class AddLayer : public ::onert::exec::IFunction +{ +public: + AddLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr) + { + // DO NOTHING + } + +public: + void addFloat32(); + + void addQuant8(); + + void configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + const ir::Activation activation, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_lhs; + const operand::Tensor *_rhs; + operand::Tensor *_output; + + ir::Activation _activation{ir::Activation::NONE}; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_ADDLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/AvgPoolLayer.cc b/runtime/onert/backend/cpu/kernel/AvgPoolLayer.cc new file mode 100644 index 000000000..ba11b7cde --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/AvgPoolLayer.cc @@ -0,0 +1,116 @@ +/* + * 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 "AvgPoolLayer.h" + +#include <cker/operation/AveragePool.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +#define AVGPOOLING_PARAMETERS \ + nnfw::cker::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() + : _input(nullptr), _output(nullptr), _paddingLeft(0), _paddingTop(0), _paddingRight(0), + _paddingBottom(0), _strideWidth(0), _strideHeight(0), _kernelWidth(0), _kernelHeight(0), + _activation(ir::Activation::NONE) +{ + // DO NOTHING +} + +void 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; + + nnfw::cker::AveragePool(op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); +} +void AvgPoolLayer::averagePoolQuant8() +{ + AVGPOOLING_PARAMETERS + int32_t output_activation_min = 0; + int32_t output_activation_max = 0; + CalculateActivationRangeUint8(_activation, _output, &output_activation_min, + &output_activation_max); + op_params.quantized_activation_min = output_activation_min; + op_params.quantized_activation_max = output_activation_max; + + nnfw::cker::AveragePool(op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const uint8_t *>(_input->buffer()), + convertTensorToCkerShape(_output), + reinterpret_cast<uint8_t *>(_output->buffer())); +} + +void AvgPoolLayer::configure(const operand::Tensor *input, 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 ir::Activation activation, + operand::Tensor *output) +{ + assert(input != nullptr); + assert(output != nullptr); + + _input = input; + _paddingLeft = paddingLeft; + _paddingRight = paddingRight; + _paddingTop = paddingTop; + _paddingBottom = paddingBottom; + _strideWidth = strideWidth; + _strideHeight = strideHeight; + _kernelWidth = kernelWidth; + _kernelHeight = kernelHeight; + _activation = activation; + _output = output; +} + +void AvgPoolLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + averagePoolFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + averagePoolQuant8(); + } +} + +#undef AVGPOOLING_PARAMETERS + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/AvgPoolLayer.h b/runtime/onert/backend/cpu/kernel/AvgPoolLayer.h new file mode 100644 index 000000000..7d7ef980d --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/AvgPoolLayer.h @@ -0,0 +1,81 @@ +/* + * 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 __ONERT_BACKEND_CPU_KERNEL_AVGPOOLLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_AVGPOOLLAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class AvgPoolLayer : public ::onert::exec::IFunction +{ +public: + AvgPoolLayer(); + +public: + void averagePoolFloat32(); + + void averagePoolQuant8(); + + void configure(const operand::Tensor *input, 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 ir::Activation activation, + operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; + + uint32_t _paddingLeft; + uint32_t _paddingTop; + uint32_t _paddingRight; + uint32_t _paddingBottom; + + uint32_t _strideWidth; + uint32_t _strideHeight; + uint32_t _kernelWidth; + uint32_t _kernelHeight; + + ir::Activation _activation; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_AVGPOOLLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/CastLayer.cc b/runtime/onert/backend/cpu/kernel/CastLayer.cc new file mode 100644 index 000000000..e485e04c7 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/CastLayer.cc @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2020 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 "CastLayer.h" + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +CastLayer::CastLayer() : _input(nullptr), _output(nullptr) +{ + // DO NOTHING +} + +void CastLayer::configure(const operand::Tensor *input, operand::Tensor *output) +{ + _input = input; + _output = output; +} + +template <typename FromT, typename ToT> void CastLayer::castTensor(const FromT *in, ToT *out) +{ + auto input_shape = convertTensorToCkerShape(_input); + auto output_shape = convertTensorToCkerShape(_output); + const auto num_elements = MatchingFlatSize(input_shape, output_shape); + + std::transform(in, in + num_elements, out, [](FromT a) { return static_cast<ToT>(a); }); +} + +template <typename FromT> void CastLayer::castPtr(const FromT *in, DataPtr out) +{ + switch (_output->data_type()) + { + case ir::DataType::FLOAT32: + castTensor(in, out.f); + return; + case ir::DataType::INT32: + castTensor(in, out.i32); + return; + case ir::DataType::UINT32: + castTensor(in, out.u32); + return; + case ir::DataType::UINT8: + castTensor(in, out.u8); + return; + case ir::DataType::BOOL8: + castTensor(in, out.b); + return; + case ir::DataType::QUANT8_ASYMM: + case ir::DataType::QUANT8_SYMM: + throw std::runtime_error("Not supported output type" + + std::to_string((int)_output->data_type())); + } +} + +void CastLayer::run() +{ + auto input_buf = _input->buffer(); + auto output_buf = _output->buffer(); + const auto in = *reinterpret_cast<const DataPtr *>(&input_buf); + auto out = *reinterpret_cast<DataPtr *>(&output_buf); + + switch (_input->data_type()) + { + case ir::DataType::FLOAT32: + castPtr(in.f, out); + return; + case ir::DataType::INT32: + castPtr(in.i32, out); + return; + case ir::DataType::UINT32: + castPtr(in.u32, out); + return; + case ir::DataType::UINT8: + castPtr(in.u8, out); + return; + case ir::DataType::BOOL8: + castPtr(in.b, out); + return; + case ir::DataType::QUANT8_ASYMM: + case ir::DataType::QUANT8_SYMM: + throw std::runtime_error("Not supported input type" + + std::to_string((int)_input->data_type())); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/CastLayer.h b/runtime/onert/backend/cpu/kernel/CastLayer.h new file mode 100644 index 000000000..4690e1007 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/CastLayer.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_CASTLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_CASTLAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class CastLayer : public ::onert::exec::IFunction +{ +public: + CastLayer(); + +public: + template <typename FromT, typename ToT> void castTensor(const FromT *in, ToT *out); + template <typename FromT> void castPtr(const FromT *in, DataPtr out); + + void configure(const operand::Tensor *input, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_CASTLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/CompareLayer.cc b/runtime/onert/backend/cpu/kernel/CompareLayer.cc new file mode 100644 index 000000000..c8ee683b1 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/CompareLayer.cc @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2020 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 "CompareLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Comparison.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +namespace +{ + +using OpType = onert::ir::operation::Comparison::ComparisonType; +using namespace onert::backend::cpu; + +template <typename T> +void compareScalar(const operand::Tensor *lhs, const operand::Tensor *rhs, operand::Tensor *output, + OpType op_type) +{ + bool requires_broadcast = !HaveSameShapes(lhs, rhs); + + if (requires_broadcast) + { + switch (op_type) + { + case OpType::Equal: + Broadcast4DSlowEqual( + convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer())); + break; + case OpType::NotEqual: + Broadcast4DSlowNotEqual( + convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer())); + break; + case OpType::Greater: + Broadcast4DSlowGreater( + convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer())); + break; + case OpType::GreaterEqual: + Broadcast4DSlowGreaterEqual( + convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer())); + break; + case OpType::Less: + Broadcast4DSlowLess( + convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer())); + break; + case OpType::LessEqual: + Broadcast4DSlowLessEqual( + convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer())); + break; + default: + throw std::runtime_error{"Invalid OpType for CompareLayer"}; + } + } + else // if (requires_broadcast == false) + { + switch (op_type) + { + case OpType::Equal: + EqualNoScaling(convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), + reinterpret_cast<bool *>(output->buffer())); + break; + case OpType::NotEqual: + NotEqualNoScaling( + convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer())); + break; + case OpType::Greater: + GreaterNoScaling( + convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer())); + break; + case OpType::GreaterEqual: + GreaterEqualNoScaling( + convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer())); + break; + case OpType::Less: + LessNoScaling(convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), + reinterpret_cast<bool *>(output->buffer())); + break; + case OpType::LessEqual: + LessEqualNoScaling( + convertToExtendedCkerShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), + convertToExtendedCkerShape(rhs), reinterpret_cast<const T *>(rhs->buffer()), + convertToExtendedCkerShape(output), reinterpret_cast<bool *>(output->buffer())); + break; + default: + throw std::runtime_error{"Invalid OpType for CompareLayer"}; + } + } + return; +} +} // namespace + +CompareLayer::CompareLayer() + : _lhs(nullptr), _rhs(nullptr), _output(nullptr), + _op_type(ir::operation::Comparison::ComparisonType::Equal) +{ + // DO NOTHING +} + +void CompareLayer::compareQuant8() { throw std::runtime_error{"Compare NYI for quantized"}; } + +void CompareLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + const OpType op_type, operand::Tensor *output) +{ + _lhs = lhs; + _rhs = rhs; + _op_type = op_type; + _output = output; +} + +void CompareLayer::run() +{ + if (_lhs->data_type() == OperandType::FLOAT32) + { + compareScalar<float>(_lhs, _rhs, _output, _op_type); + } + else if (_lhs->data_type() == OperandType::INT32) + { + compareScalar<int32_t>(_lhs, _rhs, _output, _op_type); + } + else if (_lhs->data_type() == OperandType::BOOL8) + { + compareScalar<uint8_t>(_lhs, _rhs, _output, _op_type); + } + else if (_lhs->data_type() == OperandType::QUANT8_ASYMM) + { + compareQuant8(); + } + else + { + throw std::runtime_error{"Compare: unsupported data type"}; + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/CompareLayer.h b/runtime/onert/backend/cpu/kernel/CompareLayer.h new file mode 100644 index 000000000..b62e5a2e4 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/CompareLayer.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_COMPARELAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_COMPARELAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> +#include <ir/operation/Comparison.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class CompareLayer : public ::onert::exec::IFunction +{ +public: + CompareLayer(); + +public: + void compareQuant8(); + + void configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + const ir::operation::Comparison::ComparisonType op_type, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_lhs; + const operand::Tensor *_rhs; + operand::Tensor *_output; + ir::operation::Comparison::ComparisonType _op_type; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_COMPARELAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/ConcatLayer.cc b/runtime/onert/backend/cpu/kernel/ConcatLayer.cc new file mode 100644 index 000000000..80a29e8ce --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ConcatLayer.cc @@ -0,0 +1,134 @@ +/* + * 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 "ConcatLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Concatenation.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +ConcatLayer::ConcatLayer() : _inputs(), _output(nullptr), _axis(0) +{ + // DO NOTHING +} + +void ConcatLayer::concatenationFloat32() +{ + uint32_t num_inputs = _inputs.size(); + + nnfw::cker::ConcatenationParams op_params; + op_params.axis = _axis; + op_params.inputs_count = num_inputs; + + std::vector<nnfw::cker::Shape *> inputDimsPtr; + std::vector<nnfw::cker::Shape> inputDims; + inputDimsPtr.reserve(num_inputs); + inputDims.reserve(num_inputs); + + for (uint32_t i = 0; i < num_inputs; i++) + { + inputDims.push_back(convertTensorToCkerShape(_inputs[i])); + inputDimsPtr.push_back(&inputDims[i]); + } + + std::vector<const float *> inputFloatPtrs; + + for (const auto input : _inputs) + { + inputFloatPtrs.emplace_back(reinterpret_cast<const float *>(input->buffer())); + } + + nnfw::cker::Concatenation<float>(op_params, inputDimsPtr.data(), inputFloatPtrs.data(), + convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); +} +void ConcatLayer::concatenationQuant8() +{ + uint32_t num_inputs = _inputs.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] = _inputs[i]->offset(); + input_scales[i] = _inputs[i]->scale(); + } + + nnfw::cker::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 = _output->offset(); + op_params.output_scale = _output->scale(); + + std::vector<nnfw::cker::Shape *> inputDimsPtr; + std::vector<nnfw::cker::Shape> inputDims; + inputDimsPtr.reserve(num_inputs); + inputDims.reserve(num_inputs); + for (uint32_t i = 0; i < num_inputs; i++) + { + inputDims.push_back(convertTensorToCkerShape(_inputs[i])); + inputDimsPtr.push_back(&inputDims[i]); + } + + std::vector<const uint8_t *> inputDataPtrs; + for (const auto input : _inputs) + { + inputDataPtrs.emplace_back(reinterpret_cast<const uint8_t *>(input->buffer())); + } + + nnfw::cker::ConcatenationWithScaling(op_params, inputDimsPtr.data(), inputDataPtrs.data(), + convertTensorToCkerShape(_output), + reinterpret_cast<uint8_t *>(_output->buffer())); +} + +void ConcatLayer::configure(const std::vector<const operand::Tensor *> &inputs, int32_t axis, + operand::Tensor *output) +{ + assert(inputs.size() > 0); + assert(output != nullptr); + + _inputs = inputs; + _axis = axis; + _output = output; +} + +void ConcatLayer::run() +{ + if (_output->data_type() == OperandType::FLOAT32) + { + concatenationFloat32(); + } + else if (_output->data_type() == OperandType::QUANT8_ASYMM) + { + concatenationQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/ConcatLayer.h b/runtime/onert/backend/cpu/kernel/ConcatLayer.h new file mode 100644 index 000000000..1ac1604cf --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ConcatLayer.h @@ -0,0 +1,65 @@ +/* + * 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 __ONERT_BACKEND_CPU_KERNEL_CONCATLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_CONCATLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class ConcatLayer : public ::onert::exec::IFunction +{ +public: + ConcatLayer(); + +public: + void concatenationFloat32(); + + void concatenationQuant8(); + + void configure(const std::vector<const operand::Tensor *> &inputs, int32_t axis, + operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + std::vector<const operand::Tensor *> _inputs; + operand::Tensor *_output; + int32_t _axis; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_CONCATLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/ConvolutionLayer.cc b/runtime/onert/backend/cpu/kernel/ConvolutionLayer.cc new file mode 100644 index 000000000..398054527 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ConvolutionLayer.cc @@ -0,0 +1,159 @@ +/* + * 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 <cker/operation/Conv.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ +ConvolutionLayer::ConvolutionLayer() + : _input(nullptr), _kernel(nullptr), _bias(nullptr), _output(nullptr), + _paddingType(ir::PaddingType::EXPLICIT), _paddingLeft(0), _paddingTop(0), _paddingRight(0), + _paddingBottom(0), _strideWidth(0), _strideHeight(0), _activation(ir::Activation::NONE), + _conv_kernel(new nnfw::cker::Conv()), _prepare(false) +{ + // DO NOTHING +} + +ConvolutionLayer::~ConvolutionLayer() = default; + +void ConvolutionLayer::convFloat32() +{ + float output_activation_min, output_activation_max; + CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max); + + nnfw::cker::ConvParams op_params; + op_params.padding_type = getPaddingType(_paddingType); + op_params.padding_values.width = _paddingLeft; + op_params.padding_values.height = _paddingTop; + op_params.stride_width = _strideWidth; + op_params.stride_height = _strideHeight; + op_params.dilation_width_factor = 1; + op_params.dilation_height_factor = 1; + op_params.float_activation_min = output_activation_min; + op_params.float_activation_max = output_activation_max; + + nnfw::cker::Conv &kernel = *_conv_kernel; + if (!_prepare) + { + bool is_replaced_weights = false; + kernel.prepare(convertTensorToCkerShape(_kernel), + reinterpret_cast<const float *>(_kernel->buffer()), op_params.padding_type, + is_replaced_weights); + + if (is_replaced_weights) + { + // TODO Remove const_cast + const_cast<operand::Tensor *>(_kernel)->decrease_ref(); + } + _prepare = true; + } + kernel(op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), convertTensorToCkerShape(_kernel), + reinterpret_cast<const float *>(_kernel->buffer()), convertTensorToCkerShape(_bias), + reinterpret_cast<const float *>(_bias->buffer()), convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); +} + +void ConvolutionLayer::convQuant8() +{ + int32_t output_activation_min = 0; + int32_t output_activation_max = 0; + CalculateActivationRangeUint8(_activation, _output, &output_activation_min, + &output_activation_max); + + double real_multiplier = 0.0; + int32_t output_multiplier = 0; + int32_t output_shift = 0; + GetQuantizedConvolutionMultiplier(_input, _kernel, _bias, _output, &real_multiplier); + QuantizeMultiplier(real_multiplier, &output_multiplier, &output_shift); + + nnfw::cker::ConvParams op_params; + op_params.stride_width = _strideWidth; + op_params.stride_height = _strideHeight; + op_params.dilation_width_factor = 1; + op_params.dilation_height_factor = 1; + op_params.padding_type = getPaddingType(_paddingType); + op_params.padding_values.width = _paddingLeft; + op_params.padding_values.height = _paddingTop; + op_params.input_offset = -_input->offset(); + op_params.weights_offset = -_kernel->offset(); + op_params.output_offset = _output->offset(); + 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; + + nnfw::cker::Conv &kernel = *_conv_kernel; + if (!_prepare) + { + kernel.prepareQuant(convertTensorToCkerShape(_input), convertTensorToCkerShape(_kernel), + convertTensorToCkerShape(_output), _strideWidth, _strideHeight); + _prepare = true; + } + kernel(op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const uint8_t *>(_input->buffer()), convertTensorToCkerShape(_kernel), + reinterpret_cast<const uint8_t *>(_kernel->buffer()), convertTensorToCkerShape(_bias), + reinterpret_cast<const int32_t *>(_bias->buffer()), convertTensorToCkerShape(_output), + reinterpret_cast<uint8_t *>(_output->buffer())); +} + +void ConvolutionLayer::configure(const operand::Tensor *input, const operand::Tensor *kernel, + const operand::Tensor *bias, const ir::PaddingType paddingType, + 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 ir::Activation activation, operand::Tensor *output) +{ + _input = input; + _kernel = kernel; + _bias = bias; + _paddingType = paddingType; + _paddingLeft = paddingLeft; + _paddingRight = paddingRight; + _paddingTop = paddingTop; + _paddingBottom = paddingBottom; + _strideWidth = strideWidth; + _strideHeight = strideHeight; + _activation = activation; + _output = output; +} + +void ConvolutionLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + convFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + convQuant8(); + } +} + +#undef ANDROID_NN_CONV_PARAMETERS + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/ConvolutionLayer.h b/runtime/onert/backend/cpu/kernel/ConvolutionLayer.h new file mode 100644 index 000000000..70af098c4 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ConvolutionLayer.h @@ -0,0 +1,96 @@ +/* + * 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 __ONERT_BACKEND_CPU_KERNEL_CONVOLUTIONLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_CONVOLUTIONLAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> +#include <functional> +#include <memory> + +namespace nnfw +{ +namespace cker +{ +class Conv; +} +} // namespace nnfw + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class ConvolutionLayer : public ::onert::exec::IFunction +{ +public: + ConvolutionLayer(); + ~ConvolutionLayer(); + +public: + void convFloat32(); + + void convQuant8(); + + void configure(const operand::Tensor *input, const operand::Tensor *kernel, + const operand::Tensor *bias, const ir::PaddingType paddingType, + 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 ir::Activation activation, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + const operand::Tensor *_kernel; + const operand::Tensor *_bias; + operand::Tensor *_output; + + ir::PaddingType _paddingType; + uint32_t _paddingLeft; + uint32_t _paddingTop; + uint32_t _paddingRight; + uint32_t _paddingBottom; + + uint32_t _strideWidth; + uint32_t _strideHeight; + + ir::Activation _activation; + + std::unique_ptr<nnfw::cker::Conv> _conv_kernel; + + bool _prepare; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_CONVOLUTIONLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.cc b/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.cc new file mode 100644 index 000000000..a1efe9fed --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.cc @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2019 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 "DepthwiseConvolutionLayer.h" + +#include <cker/operation/DepthwiseConv.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +DepthwiseConvolutionLayer::DepthwiseConvolutionLayer() + : _input(nullptr), _kernel(nullptr), _bias(nullptr), _output(nullptr), _paddingLeft(0), + _paddingTop(0), _paddingRight(0), _paddingBottom(0), _strideWidth(0), _strideHeight(0), + _multiplier(0), _activation(ir::Activation::NONE) +{ + // DO NOTHING +} + +void DepthwiseConvolutionLayer::convFloat32() +{ + float output_activation_min, output_activation_max; + CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max); + + nnfw::cker::DepthwiseConvParams op_params; + op_params.stride_width = _strideWidth; + op_params.stride_height = _strideHeight; + op_params.dilation_width_factor = 1; + op_params.dilation_height_factor = 1; + op_params.padding_values.width = _paddingLeft; + op_params.padding_values.height = _paddingTop; + op_params.depth_multiplier = _multiplier; + op_params.float_activation_min = output_activation_min; + op_params.float_activation_max = output_activation_max; + + nnfw::cker::DepthwiseConv( + op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), convertTensorToCkerShape(_kernel), + reinterpret_cast<const float *>(_kernel->buffer()), convertTensorToCkerShape(_bias), + reinterpret_cast<const float *>(_bias->buffer()), convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); +} + +void DepthwiseConvolutionLayer::convQuant8() +{ + int32_t output_activation_min = 0; + int32_t output_activation_max = 0; + CalculateActivationRangeUint8(_activation, _output, &output_activation_min, + &output_activation_max); + + double real_multiplier = 0.0; + int32_t output_multiplier = 0; + int32_t output_shift = 0; + GetQuantizedConvolutionMultiplier(_input, _kernel, _bias, _output, &real_multiplier); + QuantizeMultiplier(real_multiplier, &output_multiplier, &output_shift); + + nnfw::cker::DepthwiseConvParams op_params; + op_params.stride_width = _strideWidth; + op_params.stride_height = _strideHeight; + op_params.dilation_width_factor = 1; + op_params.dilation_height_factor = 1; + op_params.padding_values.width = _paddingLeft; + op_params.padding_values.height = _paddingTop; + op_params.depth_multiplier = _multiplier; + op_params.input_offset = -_input->offset(); + op_params.weights_offset = -_kernel->offset(); + op_params.output_offset = _output->offset(); + 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; + + nnfw::cker::DepthwiseConv( + op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const uint8_t *>(_input->buffer()), convertTensorToCkerShape(_kernel), + reinterpret_cast<const uint8_t *>(_kernel->buffer()), convertTensorToCkerShape(_bias), + reinterpret_cast<const int32_t *>(_bias->buffer()), convertTensorToCkerShape(_output), + reinterpret_cast<uint8_t *>(_output->buffer())); +} + +void DepthwiseConvolutionLayer::configure(const operand::Tensor *input, + const operand::Tensor *kernel, + const operand::Tensor *bias, 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 multiplier, + const ir::Activation activation, operand::Tensor *output) +{ + _input = input; + _kernel = kernel; + _bias = bias; + _paddingLeft = paddingLeft; + _paddingRight = paddingRight; + _paddingTop = paddingTop; + _paddingBottom = paddingBottom; + _strideWidth = strideWidth; + _strideHeight = strideHeight; + _multiplier = multiplier; + _activation = activation; + _output = output; +} + +void DepthwiseConvolutionLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + convFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + convQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.h b/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.h new file mode 100644 index 000000000..dcc3762cc --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/DepthwiseConvolutionLayer.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2019 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 __ONERT_KERNEL_CPU_DEPTHWISECONVOLUTIONLAYER_H__ +#define __ONERT_KERNEL_CPU_DEPTHWISECONVOLUTIONLAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class DepthwiseConvolutionLayer : public ::onert::exec::IFunction +{ +public: + DepthwiseConvolutionLayer(); + +public: + void convFloat32(); + + void convQuant8(); + + void configure(const operand::Tensor *input, const operand::Tensor *kernel, + const operand::Tensor *bias, 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 uint32_t multiplier, const ir::Activation activation, + operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + const operand::Tensor *_kernel; + const operand::Tensor *_bias; + operand::Tensor *_output; + + uint32_t _paddingLeft; + uint32_t _paddingTop; + uint32_t _paddingRight; + uint32_t _paddingBottom; + + uint32_t _strideWidth; + uint32_t _strideHeight; + + uint32_t _multiplier; + + ir::Activation _activation; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_KERNEL_CPU_DEPTHWISECONVOLUTIONLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/DivLayer.cc b/runtime/onert/backend/cpu/kernel/DivLayer.cc new file mode 100644 index 000000000..ec9daae9b --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/DivLayer.cc @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019 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 "DivLayer.h" + +#include <cker/operation/BinaryArithmeticOps.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +void DivLayer::divFloat32() +{ + float output_activation_min, output_activation_max; + CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max); + nnfw::cker::BinaryArithmeticOpParam op_params; + op_params.type = nnfw::cker::BinaryArithmeticOpType::DIV; + op_params.float_activation_max = output_activation_max; + op_params.float_activation_min = output_activation_min; + + if (!HaveSameShapes(_lhs, _rhs)) + { + nnfw::cker::BroadcastBinaryArithmeticOpSlow( + op_params, convertToExtendedCkerShape(_lhs), + reinterpret_cast<const float *>(_lhs->buffer()), convertToExtendedCkerShape(_rhs), + reinterpret_cast<const float *>(_rhs->buffer()), convertToExtendedCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); + return; + } + + nnfw::cker::BinaryArithmeticOp( + op_params, convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()), + convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void DivLayer::divQuant8() +{ + int32_t output_activation_min, output_activation_max; + CalculateActivationRangeUint8(_activation, _output, &output_activation_min, + &output_activation_max); + // nnfw::cker::BinaryArithmeticOpParam op_params; + // op_params.quantized_activation_max = output_activation_max; + // op_params.quantized_activation_min = output_activation_min; + + // cker quant8 div is not implemented yet + throw std::runtime_error{"Div NYI for quantized"}; +} + +void DivLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + const ir::Activation activation, operand::Tensor *output) +{ + _lhs = lhs; + _rhs = rhs; + _activation = activation; + _output = output; +} + +void DivLayer::run() +{ + if (_output->data_type() == OperandType::FLOAT32) + { + divFloat32(); + } + else if (_output->data_type() == OperandType::QUANT8_ASYMM) + { + divQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/DivLayer.h b/runtime/onert/backend/cpu/kernel/DivLayer.h new file mode 100644 index 000000000..3e14d9c19 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/DivLayer.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_DIVLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_DIVLAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class DivLayer : public ::onert::exec::IFunction +{ +public: + DivLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr) + { + // DO NOTHING + } + +public: + void divFloat32(); + + void divQuant8(); + + void configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + const ir::Activation activation, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_lhs; + const operand::Tensor *_rhs; + operand::Tensor *_output; + + ir::Activation _activation{ir::Activation::NONE}; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_DIVLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/ExpLayer.cc b/runtime/onert/backend/cpu/kernel/ExpLayer.cc new file mode 100644 index 000000000..335a789b2 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ExpLayer.cc @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 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 "ExpLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Exp.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +ExpLayer::ExpLayer() : _input(nullptr), _output(nullptr) +{ + // DO NOTHING +} + +void ExpLayer::expFloat32() +{ + nnfw::cker::Exp(convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void ExpLayer::expQuant8() +{ + // cker quant8 exp is not implemented yet + throw std::runtime_error{"NYI"}; +} + +void ExpLayer::configure(const operand::Tensor *input, operand::Tensor *output) +{ + _input = input; + _output = output; +} + +void ExpLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + expFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + expQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/ExpLayer.h b/runtime/onert/backend/cpu/kernel/ExpLayer.h new file mode 100644 index 000000000..5a7222fad --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ExpLayer.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_EXPLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_EXPLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class ExpLayer : public ::onert::exec::IFunction +{ +public: + ExpLayer(); + +public: + void expFloat32(); + + void expQuant8(); + + void configure(const operand::Tensor *input, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_EXPLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.cc b/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.cc new file mode 100644 index 000000000..636df8941 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.cc @@ -0,0 +1,141 @@ +/* + * 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 "FullyConnectedLayer.h" + +#include <cker/operation/FullyConnected.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +FullyConnectedLayer::FullyConnectedLayer() + : _input(nullptr), _weights(nullptr), _bias(nullptr), _output(nullptr), + _activation(ir::Activation::NONE), _temp_arena(new nnfw::cker::FCTempArena()) +{ + // DO NOTHING +} + +FullyConnectedLayer::~FullyConnectedLayer() = default; + +void FullyConnectedLayer::fullyConnectedFloat32() +{ + float output_activation_min, output_activation_max; + CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max); + + nnfw::cker::FullyConnectedParams op_params; + op_params.float_activation_min = output_activation_min; + op_params.float_activation_max = output_activation_max; + op_params.activation = convertActivationType(_activation); + + nnfw::cker::FullyConnected( + op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), convertTensorToCkerShape(_weights), + reinterpret_cast<const float *>(_weights->buffer()), convertTensorToCkerShape(_bias), + reinterpret_cast<const float *>(_bias->buffer()), convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); +} + +// executionMutex is used to protect concurrent access of non-threadsafe resources +// like gemmlowp::GemmContext. +void FullyConnectedLayer::fullyConnectedQuant8() +{ + double 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; + GetQuantizedConvolutionMultiplier(_input, _weights, _bias, _output, &real_multiplier); + QuantizeMultiplier(real_multiplier, &output_multiplier, &output_shift); + CalculateActivationRangeUint8(_activation, _output, &output_activation_min, + &output_activation_max); + + nnfw::cker::FullyConnectedParams op_params; + op_params.input_offset = -_input->offset(); + op_params.weights_offset = -_weights->offset(); + op_params.output_offset = _output->offset(); + 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; + + nnfw::cker::FullyConnected( + op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const uint8_t *>(_input->buffer()), convertTensorToCkerShape(_weights), + reinterpret_cast<const uint8_t *>(_weights->buffer()), convertTensorToCkerShape(_bias), + reinterpret_cast<const int32_t *>(_bias->buffer()), convertTensorToCkerShape(_output), + reinterpret_cast<uint8_t *>(_output->buffer())); +} + +void FullyConnectedLayer::fullyConnectedHybrid() +{ + nnfw::cker::FCTempArena &temp_arena = *_temp_arena; + if (!temp_arena.prepared) + { + temp_arena.prepare(convertTensorToCkerShape(_input), convertTensorToCkerShape(_weights)); + } + + nnfw::cker::FullyConnectedParams op_params; + op_params.activation = convertActivationType(_activation); + op_params.weights_scale = _weights->scale(); + + nnfw::cker::FullyConnectedHybrid( + op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), convertTensorToCkerShape(_weights), + reinterpret_cast<const int8_t *>(_weights->buffer()), convertTensorToCkerShape(_bias), + reinterpret_cast<const float *>(_bias->buffer()), convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer()), temp_arena); +} + +void FullyConnectedLayer::configure(const operand::Tensor *input, const operand::Tensor *weights, + const operand::Tensor *bias, ir::Activation activation, + operand::Tensor *output) +{ + _input = input; + _weights = weights; + _bias = bias; + _activation = activation; + _output = output; +} + +void FullyConnectedLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + if (_weights->data_type() == OperandType::QUANT8_SYMM) + { + fullyConnectedHybrid(); + } + else + { + fullyConnectedFloat32(); + } + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + fullyConnectedQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.h b/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.h new file mode 100644 index 000000000..616124bac --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/FullyConnectedLayer.h @@ -0,0 +1,81 @@ +/* + * 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 __ONERT_BACKEND_CPU_KERNEL_FULLYCONNECTEDLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_FULLYCONNECTEDLAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> + +namespace nnfw +{ +namespace cker +{ +class FCTempArena; +} +} // namespace nnfw + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class FullyConnectedLayer : public ::onert::exec::IFunction +{ +public: + FullyConnectedLayer(); + ~FullyConnectedLayer(); + +public: + void fullyConnectedFloat32(); + + void fullyConnectedQuant8(); + + void fullyConnectedHybrid(); + + void configure(const operand::Tensor *input, const operand::Tensor *weights, + const operand::Tensor *bias, ir::Activation activation, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + const operand::Tensor *_weights; + const operand::Tensor *_bias; + operand::Tensor *_output; + + ir::Activation _activation; + std::unique_ptr<nnfw::cker::FCTempArena> _temp_arena; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_FULLYCONNECTEDLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/GatherLayer.cc b/runtime/onert/backend/cpu/kernel/GatherLayer.cc new file mode 100644 index 000000000..07f30136c --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/GatherLayer.cc @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2019 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 "GatherLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Gather.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +void GatherLayer::configure(const operand::Tensor *input, const operand::Tensor *indices, + operand::Tensor *output, int32_t axis) +{ + _input = input; + _indices = indices; + _axis = axis; + _output = output; +} + +void GatherLayer::run() +{ + nnfw::cker::GatherParams op_params; + op_params.axis = _axis; + + switch (_input->data_type()) + { + case OperandType::FLOAT32: + nnfw::cker::Gather<float>( + op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), convertTensorToCkerShape(_indices), + reinterpret_cast<const int32_t *>(_indices->buffer()), convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); + break; + case OperandType::QUANT8_ASYMM: + nnfw::cker::Gather<uint8_t>( + op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const uint8_t *>(_input->buffer()), convertTensorToCkerShape(_indices), + reinterpret_cast<const int32_t *>(_indices->buffer()), convertTensorToCkerShape(_output), + reinterpret_cast<uint8_t *>(_output->buffer())); + break; + case OperandType::INT32: + nnfw::cker::Gather<int32_t>( + op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const int32_t *>(_input->buffer()), convertTensorToCkerShape(_indices), + reinterpret_cast<const int32_t *>(_indices->buffer()), convertTensorToCkerShape(_output), + reinterpret_cast<int32_t *>(_output->buffer())); + break; + default: + throw std::runtime_error("Gather NYI for this operand type!"); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/GatherLayer.h b/runtime/onert/backend/cpu/kernel/GatherLayer.h new file mode 100644 index 000000000..2ff3605a2 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/GatherLayer.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019 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 __ONERT_BACKEND_CPU_KERNEL_GATHERLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_GATHERLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class GatherLayer : public ::onert::exec::IFunction +{ +public: + GatherLayer() : _input{nullptr}, _indices{nullptr}, _output{nullptr}, _axis{-1} + { + // DO NOTHING + } + +public: + void configure(const operand::Tensor *input, const operand::Tensor *indices, + operand::Tensor *output, int32_t axis); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + const operand::Tensor *_indices; + operand::Tensor *_output; + + int32_t _axis; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_GATHERLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/LogisticLayer.cc b/runtime/onert/backend/cpu/kernel/LogisticLayer.cc new file mode 100644 index 000000000..07f434048 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/LogisticLayer.cc @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 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 "LogisticLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Logistic.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +LogisticLayer::LogisticLayer() : _input(nullptr), _output(nullptr) +{ + // DO NOTHING +} + +void LogisticLayer::logisticFloat32() +{ + nnfw::cker::Logistic( + convertTensorToCkerShape(_input), reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void LogisticLayer::logisticQuant8() +{ + // cker quant8 logistic is not implemented yet + throw std::runtime_error{"NYI"}; +} + +void LogisticLayer::configure(const operand::Tensor *input, operand::Tensor *output) +{ + _input = input; + _output = output; +} + +void LogisticLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + logisticFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + logisticQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/LogisticLayer.h b/runtime/onert/backend/cpu/kernel/LogisticLayer.h new file mode 100644 index 000000000..76ee1600f --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/LogisticLayer.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019 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 __ONERT_BACKEND_CPU_KERNEL_LOGISTICLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_LOGISTICLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class LogisticLayer : public ::onert::exec::IFunction +{ +public: + LogisticLayer(); + +public: + void logisticFloat32(); + + void logisticQuant8(); + + void configure(const operand::Tensor *input, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_LOGISTICLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/MaxLayer.cc b/runtime/onert/backend/cpu/kernel/MaxLayer.cc new file mode 100644 index 000000000..701d73a35 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/MaxLayer.cc @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020 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 "MaxLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/MaxMin.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +void MaxLayer::maxFloat32() +{ + nnfw::cker::Max<float>( + convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()), + convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void MaxLayer::maxQuant8() +{ + // TODO Check whether cker for quant8 max produces correct results + // nnfw::cker::Max<uint8_t>( + // convertTensorToCkerShape(_lhs), reinterpret_cast<const uint8_t*>(_lhs->buffer()), + // convertTensorToCkerShape(_rhs), reinterpret_cast<const uint8_t*>(_rhs->buffer()), + // convertTensorToCkerShape(_output), reinterpret_cast<uint8_t*>(_output->buffer())); + + throw std::runtime_error("Max NYI for quantized"); +} + +void MaxLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + operand::Tensor *output) +{ + assert(lhs != nullptr); + assert(rhs != nullptr); + assert(output != nullptr); + + _lhs = lhs; + _rhs = rhs; + _output = output; +} + +void MaxLayer::run() +{ + if (_lhs->data_type() == OperandType::FLOAT32) + { + maxFloat32(); + } + else if (_lhs->data_type() == OperandType::QUANT8_ASYMM) + { + maxQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/MaxLayer.h b/runtime/onert/backend/cpu/kernel/MaxLayer.h new file mode 100644 index 000000000..2cccf26ae --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/MaxLayer.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_MAXLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_MAXLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class MaxLayer : public ::onert::exec::IFunction +{ +public: + MaxLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr) + { + // DO NOTHING + } + +public: + void maxFloat32(); + + void maxQuant8(); + + void configure(const operand::Tensor *lhs, const operand::Tensor *rhs, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_lhs; + const operand::Tensor *_rhs; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_MAXLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/MaxPoolLayer.cc b/runtime/onert/backend/cpu/kernel/MaxPoolLayer.cc new file mode 100644 index 000000000..e35d5e92a --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/MaxPoolLayer.cc @@ -0,0 +1,113 @@ +/* + * 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 <cker/operation/MaxPool.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +#define MAXPOOLING_PARAMETERS \ + nnfw::cker::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() + : _input(nullptr), _output(nullptr), _paddingLeft(0), _paddingTop(0), _paddingRight(0), + _paddingBottom(0), _strideWidth(0), _strideHeight(0), _kernelWidth(0), _kernelHeight(0), + _activation(ir::Activation::NONE) +{ + // DO NOTHING +} + +void 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; + + nnfw::cker::MaxPool(op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); +} +void MaxPoolLayer::maxPoolQuant8() +{ + MAXPOOLING_PARAMETERS + int32_t output_activation_min = 0; + int32_t output_activation_max = 0; + CalculateActivationRangeUint8(_activation, _output, &output_activation_min, + &output_activation_max); + op_params.quantized_activation_min = output_activation_min; + op_params.quantized_activation_max = output_activation_max; + + nnfw::cker::MaxPool(op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const uint8_t *>(_input->buffer()), + convertTensorToCkerShape(_output), + reinterpret_cast<uint8_t *>(_output->buffer())); +} + +void MaxPoolLayer::configure(const operand::Tensor *input, 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 ir::Activation activation, + operand::Tensor *output) +{ + _input = input; + _paddingLeft = paddingLeft; + _paddingRight = paddingRight; + _paddingTop = paddingTop; + _paddingBottom = paddingBottom; + _strideWidth = strideWidth; + _strideHeight = strideHeight; + _kernelWidth = kernelWidth; + _kernelHeight = kernelHeight; + _activation = activation; + _output = output; +} + +void MaxPoolLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + maxPoolFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + maxPoolQuant8(); + } +} + +#undef MAXPOOLING_PARAMETERS + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/MaxPoolLayer.h b/runtime/onert/backend/cpu/kernel/MaxPoolLayer.h new file mode 100644 index 000000000..a29e09e1b --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/MaxPoolLayer.h @@ -0,0 +1,81 @@ +/* + * 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 __ONERT_BACKEND_CPU_KERNEL_MAXPOOLLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_MAXPOOLLAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class MaxPoolLayer : public ::onert::exec::IFunction +{ +public: + MaxPoolLayer(); + +public: + void maxPoolFloat32(); + + void maxPoolQuant8(); + + void configure(const operand::Tensor *input, 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 ir::Activation activation, + operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; + + uint32_t _paddingLeft; + uint32_t _paddingTop; + uint32_t _paddingRight; + uint32_t _paddingBottom; + + uint32_t _strideWidth; + uint32_t _strideHeight; + uint32_t _kernelWidth; + uint32_t _kernelHeight; + + ir::Activation _activation; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_MAXPOOLLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/MinLayer.cc b/runtime/onert/backend/cpu/kernel/MinLayer.cc new file mode 100644 index 000000000..07cb8ab91 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/MinLayer.cc @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020 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 "MinLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/MaxMin.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +void MinLayer::minFloat32() +{ + nnfw::cker::Min<float>( + convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()), + convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void MinLayer::minQuant8() +{ + // TODO Check whether cker for quant8 min produces correct results + // nnfw::cker::Min<uint8_t>( + // convertTensorToCkerShape(_lhs), reinterpret_cast<const uint8_t*>(_lhs->buffer()), + // convertTensorToCkerShape(_rhs), reinterpret_cast<const uint8_t*>(_rhs->buffer()), + // convertTensorToCkerShape(_output), reinterpret_cast<uint8_t*>(_output->buffer())); + + throw std::runtime_error("Min NYI for quantized"); +} + +void MinLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + operand::Tensor *output) +{ + assert(lhs != nullptr); + assert(rhs != nullptr); + assert(output != nullptr); + + _lhs = lhs; + _rhs = rhs; + _output = output; +} + +void MinLayer::run() +{ + if (_lhs->data_type() == OperandType::FLOAT32) + { + minFloat32(); + } + else if (_lhs->data_type() == OperandType::QUANT8_ASYMM) + { + minQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/MinLayer.h b/runtime/onert/backend/cpu/kernel/MinLayer.h new file mode 100644 index 000000000..5beb6444a --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/MinLayer.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_MINLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_MINLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class MinLayer : public ::onert::exec::IFunction +{ +public: + MinLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr) + { + // DO NOTHING + } + +public: + void minFloat32(); + + void minQuant8(); + + void configure(const operand::Tensor *lhs, const operand::Tensor *rhs, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_lhs; + const operand::Tensor *_rhs; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_MINLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/MulLayer.cc b/runtime/onert/backend/cpu/kernel/MulLayer.cc new file mode 100644 index 000000000..df7d71eec --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/MulLayer.cc @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019 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 "MulLayer.h" + +#include <cker/operation/BinaryArithmeticOps.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +void MulLayer::mulFloat32() +{ + float output_activation_min, output_activation_max; + CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max); + nnfw::cker::BinaryArithmeticOpParam op_params; + op_params.type = nnfw::cker::BinaryArithmeticOpType::MUL; + op_params.float_activation_max = output_activation_max; + op_params.float_activation_min = output_activation_min; + + if (!HaveSameShapes(_lhs, _rhs)) + { + nnfw::cker::BroadcastBinaryArithmeticOpSlow( + op_params, convertToExtendedCkerShape(_lhs), + reinterpret_cast<const float *>(_lhs->buffer()), convertToExtendedCkerShape(_rhs), + reinterpret_cast<const float *>(_rhs->buffer()), convertToExtendedCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); + return; + } + + nnfw::cker::BinaryArithmeticOp( + op_params, convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()), + convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void MulLayer::mulQuant8() +{ + int32_t output_activation_min, output_activation_max; + CalculateActivationRangeUint8(_activation, _output, &output_activation_min, + &output_activation_max); + // nnfw::cker::BinaryArithmeticOpParam op_params; + // op_params.quantized_activation_max = output_activation_max; + // op_params.quantized_activation_min = output_activation_min; + + // cker quant8 mul is not implemented yet + throw std::runtime_error{"Mull NYI for quantized"}; +} + +void MulLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + const ir::Activation activation, operand::Tensor *output) +{ + _lhs = lhs; + _rhs = rhs; + _activation = activation; + _output = output; +} + +void MulLayer::run() +{ + if (_output->data_type() == OperandType::FLOAT32) + { + mulFloat32(); + } + else if (_output->data_type() == OperandType::QUANT8_ASYMM) + { + mulQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/MulLayer.h b/runtime/onert/backend/cpu/kernel/MulLayer.h new file mode 100644 index 000000000..a5cf25f0f --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/MulLayer.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 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 __ONERT_BACKEND_CPU_KERNEL_MULLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_MULLAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class MulLayer : public ::onert::exec::IFunction +{ +public: + MulLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr) + { + // DO NOTHING + } + +public: + void mulFloat32(); + + void mulQuant8(); + + void configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + const ir::Activation activation, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_lhs; + const operand::Tensor *_rhs; + operand::Tensor *_output; + + ir::Activation _activation{ir::Activation::NONE}; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_MULLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/OneHotLayer.cc b/runtime/onert/backend/cpu/kernel/OneHotLayer.cc new file mode 100644 index 000000000..fd2c1b795 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/OneHotLayer.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020 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 "OneHotLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/OneHot.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +void OneHotLayer::oneHotFloat32() +{ + nnfw::cker::OneHot<float, int32_t>( + _depth, _on_value, _off_value, _axis, convertTensorToCkerShape(_indices), + reinterpret_cast<const int32_t *>(_indices->buffer()), convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); +} + +void OneHotLayer::oneHotQuant8() { throw std::runtime_error{"OneHot NYI for quantized"}; } + +void OneHotLayer::configure(const operand::Tensor *indices, operand::Tensor *output, int32_t depth, + float on_value, float off_value, int32_t axis) +{ + _indices = indices; + _output = output; + _depth = depth; + _on_value = on_value; + _off_value = off_value; + _axis = axis; + if (_axis == -1) + _axis = _indices->num_dimensions(); +} + +void OneHotLayer::run() +{ + if (_output->data_type() == OperandType::FLOAT32) + { + oneHotFloat32(); + } + else if (_output->data_type() == OperandType::QUANT8_ASYMM) + { + oneHotQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/OneHotLayer.h b/runtime/onert/backend/cpu/kernel/OneHotLayer.h new file mode 100644 index 000000000..5f23481ba --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/OneHotLayer.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_ONEHOTLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_ONEHOTLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class OneHotLayer : public ::onert::exec::IFunction +{ +public: + OneHotLayer() + : _indices(nullptr), _output(nullptr), _depth(0), _on_value(1), _off_value(0), _axis(-1) + { + // DO NOTHING + } + +public: + void oneHotFloat32(); + + void oneHotQuant8(); + + void configure(const operand::Tensor *indices, operand::Tensor *output, int32_t depth, + float on_value, float off_value, int32_t axis); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_indices; + operand::Tensor *_output; + + int32_t _depth; + float _on_value; + float _off_value; + int32_t _axis; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_ONEHOTLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/OperationUtils.cc b/runtime/onert/backend/cpu/kernel/OperationUtils.cc new file mode 100644 index 000000000..178aac833 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/OperationUtils.cc @@ -0,0 +1,269 @@ +/* + * 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 "OperationUtils.h" + +#include <algorithm> +#include <cassert> +#include <cmath> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +uint32_t getNumberOfDimensions(const operand::Tensor *tensor) +{ + assert(tensor); + return tensor->num_dimensions(); +} + +uint32_t getNumberOfElements(const operand::Tensor *tensor) +{ + assert(tensor); + uint32_t count = 1; + for (size_t i = 0; i < tensor->num_dimensions(); i++) + { + count *= tensor->dimension(i); + } + return count; +} + +uint32_t getSizeOfDimension(const operand::Tensor *tensor, uint32_t dimensionIdx) +{ + assert(tensor); + if (dimensionIdx >= tensor->num_dimensions()) + { + // TODO, log the error + return 0; + } + return tensor->dimension(dimensionIdx); +} + +void QuantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift) +{ + if (double_multiplier == 0.) + { + *quantized_multiplier = 0; + *shift = 0; + return; + } + const double q = std::frexp(double_multiplier, shift); + auto q_fixed = static_cast<int64_t>(std::round(q * (1ll << 31))); + + assert(q_fixed <= (1ll << 31)); + if (q_fixed == (1ll << 31)) + { + q_fixed /= 2; + ++*shift; + } + assert(q_fixed <= std::numeric_limits<int32_t>::max()); + *quantized_multiplier = static_cast<int32_t>(q_fixed); +} + +void GetQuantizedConvolutionMultiplier(const operand::Tensor *input, const operand::Tensor *filter, + const operand::Tensor *bias, const operand::Tensor *output, + double *multiplier) +{ + const double input_product_scale = input->scale() * filter->scale(); + const double bias_scale = bias->scale(); + const double output_scale = output->scale(); + // The following conditions must be guaranteed by the training pipeline. + UNUSED_RELEASE(bias_scale); + 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; +} + +void 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); +} + +void CalculateActivationRangeFloat(ir::Activation activation, float *activation_min, + float *activation_max) +{ + if (activation == ir::Activation::RELU) + { + *activation_min = 0.f; + *activation_max = std::numeric_limits<float>::max(); + } + else if (activation == ir::Activation::RELU6) + { + *activation_min = 0.f; + *activation_max = 6.f; + } + else if (activation == ir::Activation::RELU1) + { + *activation_min = -1.f; + *activation_max = 1.f; + } + else if (activation == ir::Activation::SIGMOID) + { + *activation_min = 0.f; + *activation_max = 1.f; + } + else if (activation == ir::Activation::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(ir::Activation activation, const operand::Tensor *output, + 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 = output->scale(); + const auto zero_point = output->offset(); + auto quantize = [scale, zero_point](float f) { + return zero_point + static_cast<int32_t>(std::round(f / scale)); + }; + if (activation == ir::Activation::RELU) + { + *act_min = std::max(qmin, quantize(0.0)); + *act_max = qmax; + } + else if (activation == ir::Activation::RELU6) + { + *act_min = std::max(qmin, quantize(0.0)); + *act_max = std::min(qmax, quantize(6.0)); + } + else if (activation == ir::Activation::RELU1) + { + *act_min = std::max(qmin, quantize(-1.0)); + *act_max = std::min(qmax, quantize(1.0)); + } + else if (activation == ir::Activation::SIGMOID) + { + *act_min = std::max(qmin, quantize(0.0)); + *act_max = std::min(qmax, quantize(1.0)); + } + else if (activation == ir::Activation::NONE) + { + *act_min = qmin; + *act_max = qmax; + } + else + { + std::cout << "Unsupported fused activation function." << std::endl; + } +} + +bool HaveSameShapes(const operand::Tensor *input1, const operand::Tensor *input2) +{ + if (input1 == input2) + return true; + if (input2 == NULL || input2 == NULL) + return false; + + if (input1 == NULL) + { + return (getNumberOfDimensions(input2) == 0); + } + + if (getNumberOfDimensions(input1) != getNumberOfDimensions(input2)) + return false; + + for (uint32_t i = 0; i < getNumberOfDimensions(input1); i++) + if (input1->dimension(i) != input2->dimension(i)) + return false; + + return true; +} + +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)); +} + +uint32_t sizeOfData(OperandType type, const std::vector<uint32_t> &dimensions) +{ + uint32_t size = 4; + + switch (type) + { + case OperandType::FLOAT32: + case OperandType::INT32: + case OperandType::UINT32: + size = 4; + break; + case OperandType::BOOL8: + case OperandType::QUANT8_ASYMM: + case OperandType::QUANT8_SYMM: + size = 1; + break; + default: + throw std::runtime_error("Not supported operand type."); + break; + } + + for (auto d : dimensions) + { + size *= d; + } + + return size; +} + +nnfw::cker::PaddingType getPaddingType(ir::PaddingType ir_padding_type) +{ + switch (ir_padding_type) + { + case ir::PaddingType::EXPLICIT: + return nnfw::cker::PaddingType::kNone; + case ir::PaddingType::SAME: + return nnfw::cker::PaddingType::kSame; + case ir::PaddingType::VALID: + return nnfw::cker::PaddingType::kValid; + default: + throw std::runtime_error("Wrong padding type."); + break; + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/OperationUtils.h b/runtime/onert/backend/cpu/kernel/OperationUtils.h new file mode 100644 index 000000000..be9b24f36 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/OperationUtils.h @@ -0,0 +1,162 @@ +/* + * 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 "../operand/Tensor.h" + +#include <cker/Shape.h> +#include <cker/Types.h> +#include <iostream> +#include <ir/DataType.h> +#include <ir/InternalType.h> +#include <ir/Operand.h> +#include <ir/Padding.h> + +#include <limits> +#include <vector> + +using OperandType = onert::ir::DataType; + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +union DataPtr { + uint8_t *u8; + int8_t *i8; + uint32_t *u32; + int32_t *i32; + bool *b; + float *f; + void *v; +}; + +uint32_t getNumberOfDimensions(const operand::Tensor *tensor); + +uint32_t getNumberOfElements(const operand::Tensor *tensor); + +uint32_t getSizeOfDimension(const operand::Tensor *tensor, uint32_t dimensionIdx); + +inline nnfw::cker::Shape convertToExtendedCkerShape(const operand::Tensor *tensor) +{ + assert(tensor); + std::vector<int32_t> raw_shape; + raw_shape.resize(4); + + uint32_t src = 4 - tensor->num_dimensions(); + for (uint32_t i = 0; i < 4; ++i) + { + if (i < src) + { + raw_shape[i] = 1; + } + else + { + raw_shape[i] = tensor->dimension(i - src); + } + } + + return nnfw::cker::GetShape(raw_shape); +} + +inline nnfw::cker::Shape convertTensorToCkerShape(const operand::Tensor *tensor) +{ + assert(tensor); + assert(tensor->layout() == ir::Layout::NHWC); + std::vector<int32_t> raw_shape; + raw_shape.resize(tensor->num_dimensions()); + for (uint32_t i = 0; i < tensor->num_dimensions(); ++i) + { + raw_shape[i] = tensor->dimension(i); + } + + return nnfw::cker::GetShape(raw_shape); +} + +inline nnfw::cker::FusedActivationFunctionType +convertActivationType(const ir::Activation activation) +{ + switch (activation) + { + case ir::Activation::NONE: + return nnfw::cker::FusedActivationFunctionType::kNone; + case ir::Activation::RELU: + return nnfw::cker::FusedActivationFunctionType::kRelu; + case ir::Activation::RELU1: + return nnfw::cker::FusedActivationFunctionType::kRelu1; + case ir::Activation::RELU6: + return nnfw::cker::FusedActivationFunctionType::kRelu6; + default: + throw std::runtime_error{"CPU backend: Cannot convert activation type"}; + } +} + +inline int32_t getAxis(uint32_t rank, int32_t axis, ir::Layout frontend_layout) +{ + auto ret = axis; + + if (axis < 0) + { + ret += rank; + } + + // NCHW -> NHWC + if (frontend_layout == ir::Layout::NCHW) + { + int32_t permutation[4] = {0, 3, 1, 2}; + ret = permutation[ret]; + } + + return ret; +} + +void QuantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift); + +void GetQuantizedConvolutionMultiplier(const operand::Tensor *inputDescr, + const operand::Tensor *filterDescr, + const operand::Tensor *biasDescr, + const operand::Tensor *outputDescr, double *multiplier); + +void QuantizeMultiplierGreaterThanOne(double double_multiplier, int32_t *quantized_multiplier, + int *left_shift); + +void CalculateActivationRangeFloat(ir::Activation activation, float *activation_min, + float *activation_max); + +void CalculateActivationRangeUint8(ir::Activation activation, const operand::Tensor *output, + int32_t *act_min, int32_t *act_max); + +bool HaveSameShapes(const operand::Tensor *input1, const operand::Tensor *input2); + +int32_t CalculateInputRadius(int input_integer_bits, int input_left_shift); + +uint32_t sizeOfData(OperandType type, const std::vector<uint32_t> &dimensions); + +nnfw::cker::PaddingType getPaddingType(ir::PaddingType ir_padding_type); + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __NNFW_SUPPORT_NNAPI_OPERATION_UTILS_H__ diff --git a/runtime/onert/backend/cpu/kernel/PackLayer.cc b/runtime/onert/backend/cpu/kernel/PackLayer.cc new file mode 100644 index 000000000..01e69ff1d --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/PackLayer.cc @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020 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 "PackLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Pack.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +PackLayer::PackLayer() : _inputs(), _output(nullptr), _axis(0) +{ + // DO NOTHING +} + +void PackLayer::packFloat32() +{ + uint32_t num_inputs = _inputs.size(); + nnfw::cker::PackParams op_params; + op_params.axis = _axis; + op_params.inputs_count = num_inputs; + + std::vector<nnfw::cker::Shape *> inputDimsPtr; + std::vector<nnfw::cker::Shape> inputDims; + inputDimsPtr.reserve(num_inputs); + inputDims.reserve(num_inputs); + + for (uint32_t i = 0; i < num_inputs; i++) + { + inputDims.push_back(convertTensorToCkerShape(_inputs[i])); + inputDimsPtr.push_back(&inputDims[i]); + } + + std::vector<const float *> inputFloatPtrs; + + for (const auto input : _inputs) + { + inputFloatPtrs.emplace_back(reinterpret_cast<const float *>(input->buffer())); + } + + nnfw::cker::Pack<float>(op_params, inputFloatPtrs.data(), convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); +} + +void PackLayer::packQuant8() +{ + // cker quant8 pack is not implemented yet + throw std::runtime_error{"NYI"}; +} + +void PackLayer::configure(const std::vector<const operand::Tensor *> &inputs, int32_t axis, + operand::Tensor *output) +{ + assert(inputs.size() > 0); + assert(output != nullptr); + + _inputs = inputs; + _axis = axis; + _output = output; +} + +void PackLayer::run() +{ + if (_output->data_type() == OperandType::FLOAT32) + { + packFloat32(); + } + else if (_output->data_type() == OperandType::QUANT8_ASYMM) + { + packQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/PackLayer.h b/runtime/onert/backend/cpu/kernel/PackLayer.h new file mode 100644 index 000000000..5c87382be --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/PackLayer.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_PACKLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_PACKLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class PackLayer : public ::onert::exec::IFunction +{ +public: + PackLayer(); + +public: + void packFloat32(); + + void packQuant8(); + + void configure(const std::vector<const operand::Tensor *> &inputs, int32_t axis, + operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + std::vector<const operand::Tensor *> _inputs; + operand::Tensor *_output; + int32_t _axis; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_PACKLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/PadLayer.cc b/runtime/onert/backend/cpu/kernel/PadLayer.cc new file mode 100644 index 000000000..393856178 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/PadLayer.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2019 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 "PadLayer.h" + +#include <cker/operation/Pad.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +PadLayer::PadLayer() + : _input(nullptr), _output(nullptr), _padData(), _padRank(), _constantValueData() +{ + // DO NOTHING +} + +void PadLayer::padFloat32() +{ + nnfw::cker::Pad(_padData, _padRank, convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer()), + _constantValueData.f); +} +void PadLayer::padQuant8() { throw std::runtime_error("Quantized Pad isn't supported NYI"); } + +void PadLayer::configure(const operand::Tensor *input, operand::Tensor *output, + const int32_t *padData, int32_t padRank, uint8_t *constantValueData) +{ + _input = input; + _output = output; + _padData = padData; + _padRank = padRank; + _constantValueData.u8 = constantValueData; +} + +void PadLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + padFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + padQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/PadLayer.h b/runtime/onert/backend/cpu/kernel/PadLayer.h new file mode 100644 index 000000000..fc14ae033 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/PadLayer.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 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 __ONERT_BACKEND_CPU_KERNEL_PADLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_PADLAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +// Note, this is pad with mode=`CONSTANT`: it doesn't support `REFLECT` and +// `SYMMETRIC` +class PadLayer : public ::onert::exec::IFunction +{ +public: + PadLayer(); + +public: + void padFloat32(); + + void padQuant8(); + + void configure(const operand::Tensor *input, operand::Tensor *output, const int32_t *padData, + int32_t padRank, uint8_t *constantValueData = nullptr); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; + + const int32_t *_padData; + int32_t _padRank; + DataPtr _constantValueData; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_PADLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/PermuteLayer.cc b/runtime/onert/backend/cpu/kernel/PermuteLayer.cc new file mode 100644 index 000000000..a3e828255 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/PermuteLayer.cc @@ -0,0 +1,71 @@ +/* + * 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" + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +using Type = ir::operation::Permute::Type; + +void PermuteLayer::configure(std::shared_ptr<backend::ITensor> input, + std::shared_ptr<backend::ITensor> output, + const ir::Shape &output_shape, Type type, ir::DataType dataType) +{ + _input = input; + _output = output; + _output_shape = output_shape; + _type = type; + _dataType = dataType; +} + +void PermuteLayer::run() +{ + using ir::DataType; + switch (_dataType) + { + case DataType::FLOAT32: + runTempl<float>(); + break; + case DataType::INT32: + runTempl<int32_t>(); + break; + case DataType::UINT32: + runTempl<uint32_t>(); + break; + case DataType::BOOL8: + case DataType::QUANT8_ASYMM: + runTempl<uint8_t>(); + break; + case DataType::QUANT8_SYMM: + runTempl<int8_t>(); + break; + default: + throw std::runtime_error("NYI"); + break; + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/PermuteLayer.h b/runtime/onert/backend/cpu/kernel/PermuteLayer.h new file mode 100644 index 000000000..52b96caba --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/PermuteLayer.h @@ -0,0 +1,209 @@ +/* + * 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 __ONERT_BACKEND_CPU_KERNEL_PERMUTE_LAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_PERMUTE_LAYER_H__ + +#include "OperationUtils.h" + +#include <exec/IFunction.h> +#include <ir/Coordinates.h> +#include <ir/operation/Permute.h> +#include <misc/feature/IndexIterator.h> +#include <util/feature/nchw/View.h> +#include <util/feature/nhwc/Reader.h> +#include <util/feature/nhwc/View.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class PermuteLayer : public ::onert::exec::IFunction +{ +public: + PermuteLayer() = default; + +public: + void configure(std::shared_ptr<backend::ITensor> input, std::shared_ptr<backend::ITensor> output, + const ir::Shape &output_shape, ir::operation::Permute::Type type, + ir::DataType dataType); + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + template <class T> void runTempl() + { + auto rank = _output_shape.rank(); + auto fn = [&](ITensor &in_tensor) { + _output->access([&](ITensor &out_tensor) { + auto input_buffer = in_tensor.buffer(); + auto input_size = in_tensor.total_size(); + auto output_buffer = out_tensor.buffer(); + if (_type == ir::operation::Permute::Type::COPY) + { + assert(in_tensor.layout() == out_tensor.layout()); + if (!in_tensor.has_padding() && !out_tensor.has_padding()) + { + assert(input_size == out_tensor.total_size()); + memcpy(output_buffer, input_buffer, input_size); + return; + } + } + switch (rank) + { + case 0: + case 1: + { + const int32_t copy_len = _output_shape.dim(0); + + memcpy(output_buffer, input_buffer, copy_len); + break; + } + case 2: + { + const int32_t copy_len = _output_shape.dim(1); + + for (auto i = 0; i < _output_shape.dim(0); ++i) + { + ir::Coordinates coords{i, 0}; + memcpy(output_buffer + out_tensor.calcOffset(coords), + input_buffer + in_tensor.calcOffset(coords), copy_len * sizeof(T)); + } + break; + } + case 3: + { + const int32_t copy_len = _output_shape.dim(2); + + for (auto i = 0; i < _output_shape.dim(0); ++i) + { + for (auto j = 0; j < _output_shape.dim(1); ++j) + { + ir::Coordinates coords{i, j, 0}; + memcpy(output_buffer + out_tensor.calcOffset(coords), + input_buffer + in_tensor.calcOffset(coords), copy_len * sizeof(T)); + } + } + break; + } + case 4: + { + // TODO Unify permute type and remove switch case + switch (_type) + { + case ir::operation::Permute::Type::NHWC_TO_NCHW: + { + for (auto n = 0; n < _output_shape.dim(0); ++n) + { + for (auto c = 0; c < _output_shape.dim(1); ++c) + { + for (auto h = 0; h < _output_shape.dim(2); ++h) + { + for (auto w = 0; w < _output_shape.dim(3); ++w) + { + const ir::Coordinates in_coords{n, h, w, c}; + const auto out_coords = + convertCoordinates(in_coords, in_tensor.layout(), out_tensor.layout()); + const auto value = + *reinterpret_cast<T *>(input_buffer + in_tensor.calcOffset(in_coords)); + *reinterpret_cast<T *>(output_buffer + out_tensor.calcOffset(out_coords)) = + value; + } + } + } + } + break; + } + case ir::operation::Permute::Type::NCHW_TO_NHWC: + { + for (auto n = 0; n < _output_shape.dim(0); ++n) + { + for (auto h = 0; h < _output_shape.dim(1); ++h) + { + for (auto w = 0; w < _output_shape.dim(2); ++w) + { + for (auto c = 0; c < _output_shape.dim(3); ++c) + { + const ir::Coordinates in_coords{n, c, h, w}; + const auto out_coords = + convertCoordinates(in_coords, in_tensor.layout(), out_tensor.layout()); + const auto value = + *reinterpret_cast<T *>(input_buffer + in_tensor.calcOffset(in_coords)); + *reinterpret_cast<T *>(output_buffer + out_tensor.calcOffset(out_coords)) = + value; + } + } + } + } + break; + } + case ir::operation::Permute::Type::COPY: + { + const int32_t copy_len = _output_shape.dim(3); + + for (auto i = 0; i < _output_shape.dim(0); ++i) + { + for (auto j = 0; j < _output_shape.dim(1); ++j) + { + for (auto k = 0; k < _output_shape.dim(2); ++k) + { + ir::Coordinates coords{i, j, k, 0}; + memcpy(output_buffer + out_tensor.calcOffset(coords), + input_buffer + in_tensor.calcOffset(coords), copy_len * sizeof(T)); + } + } + } + break; + } + default: + throw std::runtime_error("NYI"); + break; + } + break; + } + default: + throw std::runtime_error("NYI"); + break; + } + }); + }; + _input->access(fn); + } + +private: + std::shared_ptr<backend::ITensor> _input{nullptr}; + std::shared_ptr<backend::ITensor> _output{nullptr}; + ir::Shape _output_shape{}; + ir::operation::Permute::Type _type{ir::operation::Permute::Type::COPY}; + ir::DataType _dataType{ir::DataType::FLOAT32}; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_PERMUTE_LAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/ReduceLayer.cc b/runtime/onert/backend/cpu/kernel/ReduceLayer.cc new file mode 100644 index 000000000..78c82f1cc --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ReduceLayer.cc @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2020 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 "ReduceLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Reduce.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +namespace +{ + +template <typename T> +void evalLogic(const operand::Tensor *input, operand::Tensor *output, const std::vector<int> &axes, + bool keep_dims, T init_value, nnfw::cker::Reduce &reduce_kernel, + T reducer(const T current, const T in)) +{ + reduce_kernel.prepare(input->num_dimensions(), axes.size()); + bool result = reduce_kernel.ReduceGeneric<T>( + convertTensorToCkerShape(input), reinterpret_cast<const T *>(input->buffer()), + convertTensorToCkerShape(output), reinterpret_cast<T *>(output->buffer()), axes, keep_dims, + init_value, reducer); + + if (!result) + { + throw std::runtime_error{"Reduce: Fail to run"}; + } +} + +template <typename T> +void evalType(const operand::Tensor *input, operand::Tensor *output, const std::vector<int> &axes, + bool keep_dims, nnfw::cker::Reduce &reduce_kernel, ReduceType reduce_type) +{ + switch (reduce_type) + { + case ReduceType::kSum: + return evalLogic<T>(input, output, axes, keep_dims, static_cast<T>(0), reduce_kernel, + [](const T current, const T in) -> T { return in + current; }); + break; + case ReduceType::kProd: + return evalLogic<T>(input, output, axes, keep_dims, static_cast<T>(1), reduce_kernel, + [](const T current, const T in) -> T { return in * current; }); + break; + case ReduceType::kMax: + return evalLogic<T>( + input, output, axes, keep_dims, std::numeric_limits<T>::lowest(), reduce_kernel, + [](const T current, const T in) -> T { return (in > current) ? in : current; }); + break; + case ReduceType::kMin: + return evalLogic<T>( + input, output, axes, keep_dims, std::numeric_limits<T>::max(), reduce_kernel, + [](const T current, const T in) -> T { return (in < current) ? in : current; }); + break; + default: + throw std::runtime_error{"Reduce: Unsupported reduce type"}; + } +} + +template <ReduceType reduce_type> +void evalGeneric(const operand::Tensor *input, operand::Tensor *output, + const std::vector<int> &axes, bool keep_dims, nnfw::cker::Reduce &reduce_kernel) +{ + switch (input->data_type()) + { + case OperandType::FLOAT32: + return evalType<float>(input, output, axes, keep_dims, reduce_kernel, reduce_type); + case OperandType::INT32: + return evalType<int32_t>(input, output, axes, keep_dims, reduce_kernel, reduce_type); + default: + throw std::runtime_error{"Reduce(generic): Unsupported input type"}; + } +} +} // namespace + +ReduceLayer::ReduceLayer() + : _input(nullptr), _output(nullptr), _reduceType(ReduceType::kAny), _axes(), _keep_dims(false), + _reduce_kernel(new nnfw::cker::Reduce()) +{ + // DO NOTHING +} + +ReduceLayer::~ReduceLayer() = default; + +void ReduceLayer::configure(const operand::Tensor *input, operand::Tensor *output, + ReduceType reduceType, const std::vector<int> &axes, bool keep_dims) +{ + _input = input; + _output = output; + _reduceType = reduceType; + _axes = axes; + _keep_dims = keep_dims; +} + +void ReduceLayer::run() +{ + switch (_reduceType) + { + case ReduceType::kSum: + evalGeneric<ReduceType::kSum>(_input, _output, _axes, _keep_dims, *_reduce_kernel); + break; + case ReduceType::kMax: + evalGeneric<ReduceType::kMax>(_input, _output, _axes, _keep_dims, *_reduce_kernel); + break; + case ReduceType::kMin: + evalGeneric<ReduceType::kMin>(_input, _output, _axes, _keep_dims, *_reduce_kernel); + break; + default: + throw std::runtime_error{"ReduceSum: Unsupported reduce type"}; + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/ReduceLayer.h b/runtime/onert/backend/cpu/kernel/ReduceLayer.h new file mode 100644 index 000000000..9310882c9 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ReduceLayer.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_REDUCESUMLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_REDUCESUMLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> +#include <memory> + +namespace nnfw +{ +namespace cker +{ +class Reduce; +} +} // namespace nnfw + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +enum class ReduceType +{ + kSum, + kProd, + kMax, + kMin, + kAny, +}; + +class ReduceLayer : public ::onert::exec::IFunction +{ +public: + ReduceLayer(); + ~ReduceLayer(); + +public: + void configure(const operand::Tensor *input, operand::Tensor *output, ReduceType reduceType, + const std::vector<int> &axes, bool keep_dims); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; + ReduceType _reduceType; + std::vector<int> _axes; + bool _keep_dims; + + std::unique_ptr<nnfw::cker::Reduce> _reduce_kernel; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_REDUCESUMLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/ReshapeLayer.cc b/runtime/onert/backend/cpu/kernel/ReshapeLayer.cc new file mode 100644 index 000000000..b8bd5a45c --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ReshapeLayer.cc @@ -0,0 +1,55 @@ +/* + * 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 "ReshapeLayer.h" + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +ReshapeLayer::ReshapeLayer() : _input(nullptr), _shape(nullptr), _output(nullptr) +{ + // DO NOTHING +} + +void ReshapeLayer::reshapeGeneric() +{ + // TODO use _shape to calculate shape of output when _shape is not nullptr && not constant + + size_t count = _input->total_size(); + memcpy(_output->buffer(), _input->buffer(), count); +} + +void ReshapeLayer::configure(const operand::Tensor *input, const operand::Tensor *shape, + operand::Tensor *output) +{ + _input = input; + /* note : shape is optional. If not provided from model, _shape is nullptr. */ + _shape = shape; + _output = output; +} + +void ReshapeLayer::run() { reshapeGeneric(); } + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/ReshapeLayer.h b/runtime/onert/backend/cpu/kernel/ReshapeLayer.h new file mode 100644 index 000000000..7a95b6d35 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ReshapeLayer.h @@ -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. + */ + +#ifndef __ONERT_BACKEND_CPU_KERNEL_RESHAPELAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_RESHAPELAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class ReshapeLayer : public ::onert::exec::IFunction +{ +public: + ReshapeLayer(); + +public: + void reshapeGeneric(); + + void configure(const operand::Tensor *input, const operand::Tensor *shape, + operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + const operand::Tensor *_shape; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_RESHAPELAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/RsqrtLayer.cc b/runtime/onert/backend/cpu/kernel/RsqrtLayer.cc new file mode 100644 index 000000000..d94ff8751 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/RsqrtLayer.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020 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 "RsqrtLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Elementwise.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ +RsqrtLayer::RsqrtLayer() : _input(nullptr), _output(nullptr) +{ + // DO NOTHING +} + +void RsqrtLayer::rsqrtFloat32() +{ + nnfw::cker::Rsqrt( + convertTensorToCkerShape(_input), reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void RsqrtLayer::rsqrtQuant8() { throw std::runtime_error{"NYI : QASYMM8 not supported"}; } + +void RsqrtLayer::configure(const operand::Tensor *input, operand::Tensor *output) +{ + _input = input; + _output = output; +} + +void RsqrtLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + rsqrtFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + rsqrtQuant8(); + } + else + { + throw std::runtime_error{"Rsqrt: unsupported data type"}; + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/RsqrtLayer.h b/runtime/onert/backend/cpu/kernel/RsqrtLayer.h new file mode 100644 index 000000000..188d53160 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/RsqrtLayer.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020 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 riting, 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 __ONERT_BACKEND_CPU_KERNEL_RSQRTLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_RSQRTLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ +class RsqrtLayer : public ::onert::exec::IFunction +{ +public: + RsqrtLayer(); + + void configure(const operand::Tensor *input, operand::Tensor *output); + + void run(); + void runSync() + { + // this rsqrttract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + void rsqrtFloat32(); + void rsqrtQuant8(); + const operand::Tensor *_input; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_RSQRTLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/ShapeLayer.cc b/runtime/onert/backend/cpu/kernel/ShapeLayer.cc new file mode 100644 index 000000000..1cd183331 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ShapeLayer.cc @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2020 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 "ShapeLayer.h" + +#include "OperationUtils.h" + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +ShapeLayer::ShapeLayer() : _input(nullptr), _output(nullptr) +{ + // DO NOTHING +} + +template <typename T> void GetRawShape(const operand::Tensor *input, T *output_data) +{ + for (uint32_t i = 0; i < input->num_dimensions(); ++i) + { + output_data[i] = static_cast<T>(input->dimension(i)); + } +} + +void ShapeLayer::shape() +{ + if (_output->data_type() == OperandType::UINT32) + { + GetRawShape(_input, reinterpret_cast<uint32_t *>(_output->buffer())); + } + else if (_output->data_type() == OperandType::INT32) + { + GetRawShape(_input, reinterpret_cast<int32_t *>(_output->buffer())); + } + else + { + throw std::runtime_error{"NYI : not supported output type for ShapeLayer"}; + } +} + +void ShapeLayer::configure(const operand::Tensor *input, operand::Tensor *output) +{ + _input = input; + _output = output; +} + +void ShapeLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32 || + _input->data_type() == OperandType::QUANT8_ASYMM) + { + shape(); + } + else + { + throw std::runtime_error{"NYI : not supported input type for ShapeLayer"}; + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/ShapeLayer.h b/runtime/onert/backend/cpu/kernel/ShapeLayer.h new file mode 100644 index 000000000..cb4acedb8 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/ShapeLayer.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020 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 riting, 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 __ONERT_BACKEND_CPU_KERNEL_SHAPELAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_SHAPELAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class ShapeLayer : public ::onert::exec::IFunction +{ +public: + ShapeLayer(); + +public: + void shape(); + + void configure(const operand::Tensor *input, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_SHAPELAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/SinLayer.cc b/runtime/onert/backend/cpu/kernel/SinLayer.cc new file mode 100644 index 000000000..db8186ac6 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/SinLayer.cc @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020 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 "SinLayer.h" +#include "OperationUtils.h" + +#include <cker/operation/Elementwise.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ +SinLayer::SinLayer() : _input(nullptr), _output(nullptr) +{ + // DO NOTHING +} + +void SinLayer::sinFloat32() +{ + nnfw::cker::Sin(convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void SinLayer::sinQuant8() { throw std::runtime_error{"NYI"}; } + +void SinLayer::configure(const operand::Tensor *input, operand::Tensor *output) +{ + _input = input; + _output = output; +} + +void SinLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + sinFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + sinQuant8(); + } + else + { + throw std::runtime_error{"Sin: unsupported data type"}; + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/SinLayer.h b/runtime/onert/backend/cpu/kernel/SinLayer.h new file mode 100644 index 000000000..7898cf050 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/SinLayer.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020 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 riting, 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 __ONERT_BACKEND_CPU_KERNEL_SINLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_SINLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ +class SinLayer : public ::onert::exec::IFunction +{ +public: + SinLayer(); + + void configure(const operand::Tensor *input, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + void sinFloat32(); + void sinQuant8(); + + const operand::Tensor *_input; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_SINLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/SliceLayer.cc b/runtime/onert/backend/cpu/kernel/SliceLayer.cc new file mode 100644 index 000000000..1ade5fb44 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/SliceLayer.cc @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2020 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 "SliceLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Slice.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +SliceLayer::SliceLayer() : _input(nullptr), _begin(nullptr), _size(nullptr), _output(nullptr) +{ + // DO NOTHING +} + +template <typename T> +void SliceLayer::GetBeginAndSizeVectors(int dimensions, const operand::Tensor *begin, + const operand::Tensor *size, std::vector<int> *begins, + std::vector<int> *sizes) +{ + for (int idx = dimensions - 1; idx >= 0; --idx) + { + begins->push_back(reinterpret_cast<T *>(begin->buffer())[idx]); + sizes->push_back(reinterpret_cast<T *>(size->buffer())[idx]); + } +} + +void SliceLayer::sliceFloat32() +{ + const int kMaxDim = nnfw::cker::Shape::kMaxSmallSize; + + std::vector<int> begins; + std::vector<int> sizes; + begins.reserve(kMaxDim); + sizes.reserve(kMaxDim); + + GetBeginAndSizeVectors<int32_t>(_input->num_dimensions(), _begin, _size, &begins, &sizes); + + // begins : 0-based, sizes : 1-based + for (int i = _input->num_dimensions(); i < kMaxDim; ++i) + { + begins.push_back(0); + sizes.push_back(1); + } + + nnfw::cker::SliceParams op_params; + op_params.begin_count = 4; + op_params.size_count = 4; + for (int i = 0; i < 4; ++i) + { + op_params.begin[i] = begins[3 - i]; + op_params.size[i] = sizes[3 - i]; + } + + nnfw::cker::Slice(op_params, convertToExtendedCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), + reinterpret_cast<float *>(_output->buffer())); +} + +void SliceLayer::sliceQuant8() +{ + // cker quant8 slice is not implemented yet + throw std::runtime_error{"NYI"}; +} + +void SliceLayer::configure(const operand::Tensor *input, const operand::Tensor *begin, + const operand::Tensor *size, operand::Tensor *output) +{ + _input = input; + _output = output; + _begin = begin; + _size = size; +} + +void SliceLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + sliceFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + sliceQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/SliceLayer.h b/runtime/onert/backend/cpu/kernel/SliceLayer.h new file mode 100644 index 000000000..bb18c890c --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/SliceLayer.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_SLICELAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_SLICELAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class SliceLayer : public ::onert::exec::IFunction +{ +public: + SliceLayer(); + +public: + void configure(const operand::Tensor *input, const operand::Tensor *begin, + const operand::Tensor *size, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + void sliceFloat32(); + void sliceQuant8(); + + template <typename T> + void GetBeginAndSizeVectors(int dimensions, const operand::Tensor *begin, + const operand::Tensor *size, std::vector<int> *begins, + std::vector<int> *sizes); + +private: + const operand::Tensor *_input; + const operand::Tensor *_begin; + const operand::Tensor *_size; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_SLICELAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/SoftMaxLayer.cc b/runtime/onert/backend/cpu/kernel/SoftMaxLayer.cc new file mode 100644 index 000000000..7a1ba48aa --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/SoftMaxLayer.cc @@ -0,0 +1,173 @@ +/* + * 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 "OperationUtils.h" + +#include <cker/operation/SoftMax.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +SoftMaxLayer::SoftMaxLayer() : _input(nullptr), _output(nullptr), _beta(0.0) +{ + // 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) +{ + 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; + } +} + +void SoftMaxLayer::softmaxFloat32() +{ + if (getNumberOfDimensions(_input) == 2) + { + uint32_t batch_size = getSizeOfDimension(_input, 0); + if (batch_size == 0) + throw std::runtime_error("batch_size should not be 0"); + + uint32_t input_size = getNumberOfElements(_input) / batch_size; + Softmax(reinterpret_cast<const float *>(_input->buffer()), input_size, batch_size, _beta, + reinterpret_cast<float *>(_output->buffer())); + } + else if (getNumberOfDimensions(_input) == 4) + { + nnfw::cker::SoftmaxParams op_params; + op_params.beta = _beta; + nnfw::cker::Softmax(op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); + } + else + { + throw std::runtime_error{"only 2D and 4D tensors supported"}; + } +} + +void SoftMaxLayer::softmaxQuant8() +{ + nnfw::cker::Shape descrIn4D(4); + + if (getNumberOfDimensions(_input) == 2) + { + auto batch_size = getSizeOfDimension(_input, 0); + if (batch_size == 0) + throw std::runtime_error("batch_size should not be 0"); + + auto input_size = getNumberOfElements(_input) / batch_size; + descrIn4D.SetDim(0, batch_size); + descrIn4D.SetDim(1, 1); + descrIn4D.SetDim(2, 1); + descrIn4D.SetDim(3, input_size); + } + else if (getNumberOfDimensions(_input) == 4) + { + descrIn4D.SetDim(0, _input->dimension(0)); + descrIn4D.SetDim(1, _input->dimension(1)); + descrIn4D.SetDim(2, _input->dimension(2)); + descrIn4D.SetDim(3, _input->dimension(3)); + } + else + { + throw std::runtime_error{"only 2D and 4D tensors supported"}; + } + if (_output->offset() != 0 || _output->scale() != 1.f / 256) + { + throw std::runtime_error{"incorrect scale / offset for output"}; + } + static const int32_t kScaledDiffIntegerBits = 5; + const double input_beta_real_multiplier = std::min( + 1.0 * _beta * _input->scale() * (1 << (31 - kScaledDiffIntegerBits)), (1ll << 31) - 1.0); + int32_t input_multiplier = 0; + int32_t input_left_shift = 0; + QuantizeMultiplierGreaterThanOne(input_beta_real_multiplier, &input_multiplier, + &input_left_shift); + float diff_min = -1.0f * CalculateInputRadius(kScaledDiffIntegerBits, input_left_shift); + + nnfw::cker::SoftmaxParams op_params; + op_params.input_multiplier = input_multiplier; + op_params.input_left_shift = input_left_shift; + op_params.diff_min = diff_min; + nnfw::cker::Softmax(op_params, descrIn4D, reinterpret_cast<const uint8_t *>(_input->buffer()), + descrIn4D, reinterpret_cast<uint8_t *>(_output->buffer())); +} + +void SoftMaxLayer::configure(const operand::Tensor *input, const float beta, + operand::Tensor *output) +{ + _input = input; + _output = output; + _beta = beta; +} + +void SoftMaxLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + softmaxFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + softmaxQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/SoftMaxLayer.h b/runtime/onert/backend/cpu/kernel/SoftMaxLayer.h new file mode 100644 index 000000000..bb29b4fda --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/SoftMaxLayer.h @@ -0,0 +1,65 @@ +/* + * 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 __ONERT_BACKEND_CPU_KERNEL_SOFTMAXLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_SOFTMAXLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class SoftMaxLayer : public ::onert::exec::IFunction +{ +public: + SoftMaxLayer(); + +public: + void softmaxFloat32(); + + void softmaxQuant8(); + + void configure(const operand::Tensor *input, const float beta, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; + + float _beta; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_SOFTMAXLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/SplitLayer.cc b/runtime/onert/backend/cpu/kernel/SplitLayer.cc new file mode 100644 index 000000000..e4c5ef3a0 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/SplitLayer.cc @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020 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 "SplitLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Split.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +SplitLayer::SplitLayer() : _input(nullptr), _num_splits(0), _axis(0), _outputs() +{ + // DO NOTHING +} + +void SplitLayer::splitFloat32() +{ + nnfw::cker::SplitParams op_params; + op_params.axis = _axis; + op_params.num_split = _num_splits; + + std::vector<nnfw::cker::Shape *> outputDimsPtr; + std::vector<nnfw::cker::Shape> outputDims; + outputDimsPtr.reserve(_num_splits); + outputDims.reserve(_num_splits); + + for (uint32_t i = 0; i < _num_splits; i++) + { + outputDims.push_back(convertTensorToCkerShape(_outputs[i])); + outputDimsPtr.push_back(&outputDims[i]); + } + + std::vector<float *> outputFloatPtrs; + + for (const auto output : _outputs) + { + outputFloatPtrs.emplace_back(reinterpret_cast<float *>(output->buffer())); + } + + nnfw::cker::Split<float>(op_params, convertTensorToCkerShape(_input), + reinterpret_cast<float *>(_input->buffer()), + convertTensorToCkerShape(_outputs[0]), outputFloatPtrs.data()); +} + +void SplitLayer::splitQuant8() { throw std::runtime_error{"Split: NYI quant8 type"}; } + +void SplitLayer::configure(const operand::Tensor *input, uint16_t num_splits, int16_t axis, + std::vector<operand::Tensor *> &outputs) +{ + assert(input != nullptr); + + _num_splits = num_splits; + _input = input; + _axis = axis; + _outputs = outputs; +} + +void SplitLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + splitFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + splitQuant8(); + } + else + { + throw std::runtime_error{"Split: Unsupported input type"}; + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/SplitLayer.h b/runtime/onert/backend/cpu/kernel/SplitLayer.h new file mode 100644 index 000000000..9f236f0af --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/SplitLayer.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_SPLITLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_SPLITLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class SplitLayer : public ::onert::exec::IFunction +{ +public: + SplitLayer(); + +public: + void splitFloat32(); + + void splitQuant8(); + + void configure(const operand::Tensor *input, uint16_t num_splits, int16_t axis, + std::vector<operand::Tensor *> &outputs); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + uint16_t _num_splits; + int16_t _axis; + std::vector<operand::Tensor *> _outputs; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_SPLITLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/StridedSliceLayer.cc b/runtime/onert/backend/cpu/kernel/StridedSliceLayer.cc new file mode 100644 index 000000000..22315c7c6 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/StridedSliceLayer.cc @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020 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 "StridedSliceLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/StridedSlice.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +StridedSliceLayer::StridedSliceLayer() + : _input(nullptr), _begin(nullptr), _end(nullptr), _strides(nullptr), _output(nullptr), + _begin_mask(0), _ellipsis_mask(0), _end_mask(0), _new_axis_mask(0), _shrink_axis_mask(0), + _rank(0) +{ +} + +void StridedSliceLayer::stridedSliceFloat32() +{ + auto op_params = nnfw::cker::buildStridedSliceParams( + reinterpret_cast<uint32_t *>(_begin->buffer()), reinterpret_cast<uint32_t *>(_end->buffer()), + reinterpret_cast<uint32_t *>(_strides->buffer()), _begin_mask, _end_mask, _shrink_axis_mask, + _rank); + + nnfw::cker::checkOutputSize(op_params, convertTensorToCkerShape(_input), + convertTensorToCkerShape(_output), _rank); + + nnfw::cker::StridedSlice(op_params, convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); +} + +void StridedSliceLayer::stridedSliceQuant8() +{ + // cker quant8 stridedSlice is not implemented yet + throw std::runtime_error{"NYI"}; +} + +void StridedSliceLayer::configure(const operand::Tensor *input, const operand::Tensor *begin, + const operand::Tensor *end, const operand::Tensor *strides, + operand::Tensor *output, const int32_t begin_mask, + const int32_t end_mask, const int32_t shrink_axis_mask, + const int32_t rank) +{ + _input = input; + _begin = begin; + _end = end; + _strides = strides; + _output = output; + + _rank = rank; + _begin_mask = begin_mask; + _ellipsis_mask = 0; + _end_mask = end_mask; + _new_axis_mask = 0; + _shrink_axis_mask = shrink_axis_mask; +} + +void StridedSliceLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + stridedSliceFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + stridedSliceQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/StridedSliceLayer.h b/runtime/onert/backend/cpu/kernel/StridedSliceLayer.h new file mode 100644 index 000000000..7888eff3c --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/StridedSliceLayer.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_STRIDEDSLICELAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_STRIDEDSLICELAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class StridedSliceLayer : public ::onert::exec::IFunction +{ +public: + StridedSliceLayer(); + +public: + void configure(const operand::Tensor *input, const operand::Tensor *begin, + const operand::Tensor *end, const operand::Tensor *strides, + operand::Tensor *output, const int32_t begin_mask, const int32_t end_mask, + const int32_t shrink_axis_mask, const int32_t rank); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + void stridedSliceFloat32(); + void stridedSliceQuant8(); + +private: + const operand::Tensor *_input; + const operand::Tensor *_begin; + const operand::Tensor *_end; + const operand::Tensor *_strides; + operand::Tensor *_output; + + int32_t _begin_mask; + int32_t _ellipsis_mask; + int32_t _end_mask; + int32_t _new_axis_mask; + int32_t _shrink_axis_mask; + + int32_t _rank; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_STRIDEDSLICELAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/SubLayer.cc b/runtime/onert/backend/cpu/kernel/SubLayer.cc new file mode 100644 index 000000000..15aa43835 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/SubLayer.cc @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2019 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 "SubLayer.h" + +#include <cker/operation/BinaryArithmeticOps.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +void SubLayer::subFloat32() +{ + float output_activation_min, output_activation_max; + CalculateActivationRangeFloat(_activation, &output_activation_min, &output_activation_max); + nnfw::cker::BinaryArithmeticOpParam op_params; + op_params.type = nnfw::cker::BinaryArithmeticOpType::SUB; + op_params.float_activation_max = output_activation_max; + op_params.float_activation_min = output_activation_min; + + if (!HaveSameShapes(_lhs, _rhs)) + { + nnfw::cker::BroadcastBinaryArithmeticOpSlow( + op_params, convertToExtendedCkerShape(_lhs), + reinterpret_cast<const float *>(_lhs->buffer()), convertToExtendedCkerShape(_rhs), + reinterpret_cast<const float *>(_rhs->buffer()), convertToExtendedCkerShape(_output), + reinterpret_cast<float *>(_output->buffer())); + return; + } + + nnfw::cker::BinaryArithmeticOp( + op_params, convertTensorToCkerShape(_lhs), reinterpret_cast<const float *>(_lhs->buffer()), + convertTensorToCkerShape(_rhs), reinterpret_cast<const float *>(_rhs->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void SubLayer::subQuant8() +{ + int32_t output_activation_min, output_activation_max; + CalculateActivationRangeUint8(_activation, _output, &output_activation_min, + &output_activation_max); + // nnfw::cker::SubParam op_params; + // op_params.quantized_activation_max = output_activation_max; + // op_params.quantized_activation_min = output_activation_min; + + // cker quant8 sub is not implemented yet + throw std::runtime_error{"NYI"}; +} + +void SubLayer::configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + const ir::Activation activation, operand::Tensor *output) +{ + _lhs = lhs; + _rhs = rhs; + _activation = activation; + _output = output; +} + +void SubLayer::run() +{ + if (_output->data_type() == OperandType::FLOAT32) + { + subFloat32(); + } + else if (_output->data_type() == OperandType::QUANT8_ASYMM) + { + subQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/SubLayer.h b/runtime/onert/backend/cpu/kernel/SubLayer.h new file mode 100644 index 000000000..48fa97669 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/SubLayer.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019 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 __ONERT_BACKEND_CPU_KERNEL_SUBLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_SUBLAYER_H__ + +#include "../operand/Tensor.h" +#include "OperationUtils.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class SubLayer : public ::onert::exec::IFunction +{ +public: + SubLayer() : _lhs(nullptr), _rhs(nullptr), _output(nullptr) + { + // DO NOTHING + } + +public: + void subFloat32(); + + void subQuant8(); + + void configure(const operand::Tensor *lhs, const operand::Tensor *rhs, + const ir::Activation activation, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_lhs; + const operand::Tensor *_rhs; + operand::Tensor *_output; + + ir::Activation _activation{ir::Activation::NONE}; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_SUBLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/TanhLayer.cc b/runtime/onert/backend/cpu/kernel/TanhLayer.cc new file mode 100644 index 000000000..6a9274f7a --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/TanhLayer.cc @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020 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 "TanhLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Tanh.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +TanhLayer::TanhLayer() : _input(nullptr), _output(nullptr) +{ + // DO NOTHING +} + +void TanhLayer::tanhFloat32() +{ + nnfw::cker::Tanh(convertTensorToCkerShape(_input), + reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void TanhLayer::tanhQuant8() +{ + // cker quant8 tanh is not implemented yet + throw std::runtime_error{"NYI"}; +} + +void TanhLayer::configure(const operand::Tensor *input, operand::Tensor *output) +{ + _input = input; + _output = output; +} + +void TanhLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + tanhFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + tanhQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/TanhLayer.h b/runtime/onert/backend/cpu/kernel/TanhLayer.h new file mode 100644 index 000000000..8fb621cdb --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/TanhLayer.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_TANHLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_TANHLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class TanhLayer : public ::onert::exec::IFunction +{ +public: + TanhLayer(); + +public: + void tanhFloat32(); + + void tanhQuant8(); + + void configure(const operand::Tensor *input, operand::Tensor *output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_TANHLAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/TransposeLayer.cc b/runtime/onert/backend/cpu/kernel/TransposeLayer.cc new file mode 100644 index 000000000..31b1dd12d --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/TransposeLayer.cc @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2020 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 "TransposeLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Transpose.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +TransposeLayer::TransposeLayer() : _input(nullptr), _output(nullptr), _perm(), _rank(0) +{ + // DO NOTHING +} + +void TransposeLayer::transposeFloat32() +{ + nnfw::cker::TransposeParams param; + param.perm_count = _rank; + for (int32_t i = 0; i < _rank; i++) + { + param.perm[i] = _perm[i]; + } + + nnfw::cker::Transpose( + param, convertTensorToCkerShape(_input), reinterpret_cast<const float *>(_input->buffer()), + convertTensorToCkerShape(_output), reinterpret_cast<float *>(_output->buffer())); +} + +void TransposeLayer::transposeQuant8() +{ + // cker quant8 tanh is not implemented yet + throw std::runtime_error{"NYI"}; +} + +void TransposeLayer::configure(const operand::Tensor *input, operand::Tensor *output, + const std::vector<int> &perm, int32_t rank) +{ + _input = input; + _rank = rank; + _perm = perm; + _output = output; +} + +void TransposeLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + transposeFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + transposeQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/TransposeLayer.h b/runtime/onert/backend/cpu/kernel/TransposeLayer.h new file mode 100644 index 000000000..ffe7c2ae5 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/TransposeLayer.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_TRANSPOSELAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_TRANSPOSELAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class TransposeLayer : public ::onert::exec::IFunction +{ +public: + TransposeLayer(); + +public: + void transposeFloat32(); + + void transposeQuant8(); + + void configure(const operand::Tensor *input, operand::Tensor *output, + const std::vector<int> &perm, int32_t rank); + + void run(); + void runSync() { run(); } + +private: + const operand::Tensor *_input; + operand::Tensor *_output; + std::vector<int> _perm; + int32_t _rank; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_TRANSPOSELAYER_H__ diff --git a/runtime/onert/backend/cpu/kernel/UnpackLayer.cc b/runtime/onert/backend/cpu/kernel/UnpackLayer.cc new file mode 100644 index 000000000..fe07e3e19 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/UnpackLayer.cc @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2020 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 "UnpackLayer.h" + +#include "OperationUtils.h" + +#include <cker/operation/Unpack.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +UnpackLayer::UnpackLayer() : _input(nullptr), _outputs(), _axis(0), _num_output(0) +{ + // DO NOTHING +} + +void UnpackLayer::unpackFloat32() +{ + nnfw::cker::UnpackParams op_params; + op_params.axis = _axis; + op_params.num_split = _num_output; + + std::vector<nnfw::cker::Shape *> outputDimsPtr; + std::vector<nnfw::cker::Shape> outputDims; + outputDimsPtr.reserve(_num_output); + outputDims.reserve(_num_output); + + for (int32_t i = 0; i < _num_output; i++) + { + outputDims.push_back(convertTensorToCkerShape(_outputs[i])); + outputDimsPtr.push_back(&outputDims[i]); + } + + std::vector<float *> outputFloatPtrs; + + for (const auto output : _outputs) + { + outputFloatPtrs.emplace_back(reinterpret_cast<float *>(output->buffer())); + } + + nnfw::cker::Unpack<float>(op_params, convertTensorToCkerShape(_input), + reinterpret_cast<float *>(_input->buffer()), + convertTensorToCkerShape(_outputs[0]), outputFloatPtrs.data()); +} + +void UnpackLayer::unpackQuant8() +{ + // cker quant8 pack is not implemented yet + throw std::runtime_error{"Unpack: NYI quant8 type"}; +} + +void UnpackLayer::configure(const operand::Tensor *input, uint32_t axis, int32_t num, + std::vector<operand::Tensor *> &outputs) +{ + assert(input != nullptr); + assert(outputs.size() > 0); + assert(outputs.size() == (size_t)num); + + _input = input; + _axis = axis; + _num_output = num; + _outputs = outputs; +} + +void UnpackLayer::run() +{ + if (_input->data_type() == OperandType::FLOAT32) + { + unpackFloat32(); + } + else if (_input->data_type() == OperandType::QUANT8_ASYMM) + { + unpackQuant8(); + } + else + { + throw std::runtime_error{"Unpack: Unsupported input type"}; + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert diff --git a/runtime/onert/backend/cpu/kernel/UnpackLayer.h b/runtime/onert/backend/cpu/kernel/UnpackLayer.h new file mode 100644 index 000000000..23d064db2 --- /dev/null +++ b/runtime/onert/backend/cpu/kernel/UnpackLayer.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020 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 __ONERT_BACKEND_CPU_KERNEL_UNPACKLAYER_H__ +#define __ONERT_BACKEND_CPU_KERNEL_UNPACKLAYER_H__ + +#include "../operand/Tensor.h" + +#include <exec/IFunction.h> + +namespace onert +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +class UnpackLayer : public ::onert::exec::IFunction +{ +public: + UnpackLayer(); + +public: + void unpackFloat32(); + + void unpackQuant8(); + + void configure(const operand::Tensor *input, uint32_t axis, int32_t num_output, + std::vector<operand::Tensor *> &output); + + void run(); + void runSync() + { + // this abstract method is used just for profiling and called for + // backend::acl_common::AclFunction + run(); + } + +private: + const operand::Tensor *_input; + std::vector<operand::Tensor *> _outputs; + uint32_t _axis; + int32_t _num_output; +}; + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace onert + +#endif // __ONERT_BACKEND_CPU_KERNEL_UNPACKLAYER_H__ |