ONE - On-device Neural Engine
Loading...
Searching...
No Matches
SoftmaxLayer.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 Samsung Electronics Co., Ltd. All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "SoftmaxLayer.h"
18
19#include "OperationUtils.h"
20#include "../KernelGenerator.h"
21#include "../Validator.h"
22
24
25namespace onert::backend::cpu
26{
27
28void Validator::visit(const ir::operation::Softmax &) { _supported = true; }
29
30void KernelGenerator::visit(const ir::operation::Softmax &node)
31{
32 const auto output_index{node.getOutputs().at(0)};
33 const auto input_index{node.getInputs().at(ir::operation::Softmax::Input::INPUT)};
34
35 const auto beta = node.param().beta;
36
37 auto output_tensor = _tensor_reg->getPortableTensor(output_index);
38 auto input_tensor = _tensor_reg->getPortableTensor(input_index);
39
40 auto fn = std::make_unique<ops::SoftMaxLayer>();
41
42 fn->configure(input_tensor, beta, output_tensor);
43
44 _return_fn = std::move(fn);
45}
46
47} // namespace onert::backend::cpu
48
50{
51
52SoftMaxLayer::SoftMaxLayer() : _input(nullptr), _output(nullptr), _beta(0.0)
53{
54 // DO NOTHING
55}
56
58{
60 {
61 uint32_t input_size = getNumberOfElements(_input);
62 nnfw::cker::Softmax(getBuffer<float>(_input), input_size, 1, _beta, getBuffer<float>(_output));
63 }
64 else if (getNumberOfDimensions(_input) == 2)
65 {
66 uint32_t batch_size = getSizeOfDimension(_input, 0);
67 if (batch_size == 0)
68 throw std::runtime_error("batch_size should not be 0");
69
70 uint32_t input_size = getNumberOfElements(_input) / batch_size;
71 nnfw::cker::Softmax(getBuffer<float>(_input), input_size, batch_size, _beta,
72 getBuffer<float>(_output));
73 }
74 else if (getNumberOfDimensions(_input) == 4)
75 {
77 op_params.beta = _beta;
78 nnfw::cker::Softmax(op_params, getShape(_input), getBuffer<float>(_input), getShape(_output),
79 getBuffer<float>(_output));
80 }
81 else
82 {
84 op_params.beta = _beta;
85 nnfw::cker::reference::Softmax(op_params, getShape(_input), getBuffer<float>(_input),
86 getShape(_output), getBuffer<float>(_output));
87 }
88}
89
90template <typename T> void SoftMaxLayer::softmaxQuant8()
91{
93 op_params.scale = _output->data_scale();
94 op_params.zero_point = _output->data_zero_point();
95 op_params.uint8_table1 = _uint8_table1;
96 op_params.uint8_table2 = _uint8_table2;
97 op_params.table = _table;
98
99#ifdef TFLITE_SOFTMAX_USE_UINT16_LUT
100 nnfw::cker::SoftmaxInt8LUT<T, T>(op_params, getShape(_input), getBuffer<T>(_input),
101 getShape(_output), getBuffer<T>(_output));
102#else
103 nnfw::cker::Softmax<T, T>(op_params, getShape(_input), getBuffer<T>(_input), getShape(_output),
104 getBuffer<T>(_output));
105#endif
106}
107
108void SoftMaxLayer::configure(const IPortableTensor *input, const float beta,
109 IPortableTensor *output)
110{
111 _input = input;
112 _output = output;
113 _beta = beta;
114
115 if (_input->data_type() == OperandType::QUANT_UINT8_ASYMM ||
116 _input->data_type() == OperandType::QUANT_INT8_ASYMM)
117 {
118#ifdef TFLITE_SOFTMAX_USE_UINT16_LUT
119 // Only apply when both input & output are uint8/int8 & build with clang
120 // on aarch64.
121 nnfw::cker::PopulateSoftmaxUInt8LookupTable(_uint8_table1, _uint8_table2, _input->data_scale(),
122 _beta);
123#else
125#endif
126 }
127}
128
130{
131 switch (_input->data_type())
132 {
133 case OperandType::FLOAT32:
135 break;
136 case OperandType::QUANT_UINT8_ASYMM:
137 softmaxQuant8<uint8_t>();
138 break;
139 case OperandType::QUANT_INT8_ASYMM:
140 softmaxQuant8<int8_t>();
141 break;
142 default:
143 throw std::runtime_error{"SoftMax: unsupported data type"};
144 }
145}
146
147} // namespace onert::backend::cpu::ops
A tensor class that is portable for other backends.
float data_scale() const override final
int32_t data_zero_point() const override final
ir::DataType data_type() const override final
std::unique_ptr< exec::IFunction > _return_fn
void configure(const IPortableTensor *input, const float beta, IPortableTensor *output)
uint32_t getNumberOfElements(const Shape &shape)
Definition Shape.cpp:48
uint32_t getSizeOfDimension(const Shape &shape, uint32_t dimensionIdx)
Definition Shape.cpp:60
uint32_t getNumberOfDimensions(const Shape &shape)
Definition Shape.cpp:58
void Softmax(const SoftmaxParams &params, const Shape &input_shape, const float *input_data, const Shape &output_shape, float *output_data)
Definition SoftMax.h:43
void Softmax(const float *in, const int input_size, const int batch_size, const float beta, float *out)
Definition SoftMax.h:79
void PopulateSoftmaxLookupTable(float *table, float input_scale, float beta)
Definition SoftMax.h:148
nnfw::cker::Shape getShape(const IPortableTensor *tensor)