diff options
author | Chunseok Lee <chunseok.lee@samsung.com> | 2020-03-05 15:10:09 +0900 |
---|---|---|
committer | Chunseok Lee <chunseok.lee@samsung.com> | 2020-03-05 15:22:53 +0900 |
commit | d91a039e0eda6fd70dcd22672b8ce1817c1ca50e (patch) | |
tree | 62668ec548cf31fadbbf4e99522999ad13434a25 /runtimes/neurun/backend/cpu/kernel/SoftMaxLayer.cc | |
parent | bd11b24234d7d43dfe05a81c520aa01ffad06e42 (diff) | |
download | nnfw-d91a039e0eda6fd70dcd22672b8ce1817c1ca50e.tar.gz nnfw-d91a039e0eda6fd70dcd22672b8ce1817c1ca50e.tar.bz2 nnfw-d91a039e0eda6fd70dcd22672b8ce1817c1ca50e.zip |
catch up to tizen_5.5 and remove unness dir
- update to tizen_5.5
- remove dirs
Diffstat (limited to 'runtimes/neurun/backend/cpu/kernel/SoftMaxLayer.cc')
-rw-r--r-- | runtimes/neurun/backend/cpu/kernel/SoftMaxLayer.cc | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/runtimes/neurun/backend/cpu/kernel/SoftMaxLayer.cc b/runtimes/neurun/backend/cpu/kernel/SoftMaxLayer.cc new file mode 100644 index 000000000..f71a779bd --- /dev/null +++ b/runtimes/neurun/backend/cpu/kernel/SoftMaxLayer.cc @@ -0,0 +1,171 @@ +/* + * 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 <cker/operation/SoftMax.h> + +#include "OperationUtils.h" + +namespace neurun +{ +namespace backend +{ +namespace cpu +{ +namespace kernel +{ + +SoftMaxLayer::SoftMaxLayer() + : _inputData(), _outputData(), _beta(0.0), _inputShape(), _outputShape(), + _inputType(OperandType::FLOAT32) +{ + // DO NOTHING +} + +// Performs softmax along the input of size (input_size * batch_size). +void Softmax(const float *in, const int input_size, const int batch_size, const float beta, + float *out) +{ + 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() +{ + Shape shapeIn4D; + + if (getNumberOfDimensions(_inputShape) == 2) + { + uint32_t batch_size = getSizeOfDimension(_inputShape, 0); + if (batch_size == 0) + throw std::runtime_error("batch_size should not be 0"); + + uint32_t input_size = getNumberOfElements(_inputShape) / batch_size; + Softmax(_inputData.f, input_size, batch_size, _beta, _outputData.f); + } + else if (getNumberOfDimensions(_inputShape) == 4) + { + nnfw::cker::SoftmaxParams op_params; + op_params.beta = _beta; + nnfw::cker::Softmax(op_params, convertShapeToCkerShape(_inputShape), _inputData.f, + convertShapeToCkerShape(_outputShape), _outputData.f); + } + else + { + throw std::runtime_error{"only 2D and 4D tensors supported"}; + } +} + +void SoftMaxLayer::softmaxQuant8() +{ + Shape shapeIn4D = _inputShape; + + if (getNumberOfDimensions(_inputShape) == 2) + { + uint32_t batch_size = getSizeOfDimension(_inputShape, 0); + if (batch_size == 0) + throw std::runtime_error("batch_size should not be 0"); + + uint32_t input_size = getNumberOfElements(_inputShape) / batch_size; + shapeIn4D.dimensions = {batch_size, 1, 1, input_size}; + } + else if (getNumberOfDimensions(_inputShape) == 4) + { + shapeIn4D = _inputShape; + } + else + { + throw std::runtime_error{"only 2D and 4D tensors supported"}; + } + if (_outputShape.offset != 0 || _outputShape.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 * _inputShape.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, convertShapeToCkerShape(shapeIn4D), _inputData.u8, + convertShapeToCkerShape(shapeIn4D), _outputData.u8); +} + +void SoftMaxLayer::configure(uint8_t *inputData, const Shape &inputShape, const float beta, + uint8_t *outputData, const Shape &outputShape) +{ + _inputData.u8 = inputData; + _inputShape = inputShape; + _inputType = inputShape.type; + _outputData.u8 = outputData; + _outputShape = outputShape; + _beta = beta; +} + +void SoftMaxLayer::run() +{ + if (_inputType == OperandType::FLOAT32) + { + softmaxFloat32(); + } + else if (_inputType == OperandType::QUANT8_ASYMM) + { + softmaxQuant8(); + } +} + +} // namespace kernel +} // namespace cpu +} // namespace backend +} // namespace neurun |