ArmNN
 25.11
Loading...
Searching...
No Matches
SigmoidOperator.cpp
Go to the documentation of this file.
1//
2// Copyright © 2024 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5//
6// Copyright © 2020 The TensorFlow Authors. All Rights Reserved.
7// SPDX-License-Identifier: Apache-2.0
8//
9
10#include "SigmoidOperator.hpp"
11#include "TosaTableUtils.hpp"
12
13// This function is paraphrased from:
14// tensorflow/compiler/mlir/tosa/transforms/legalize_tfl.cc from function ConvertTFLLogisticOp
15TosaSerializationBasicBlock* ConvertSigmoidToTosaOperator(const Layer* layer,
16 const std::vector<const TensorInfo*>& inputs,
17 const std::vector<const TensorInfo*>& outputs,
18 const ActivationDescriptor* desc)
19{
20 if (inputs.size() != 1)
21 {
22 throw armnn::Exception("ConvertSigmoidToTosaOperator: 1 input tensors required.");
23 }
24
25 if (outputs.size() != 1)
26 {
27 throw armnn::Exception("ConvertSigmoidToTosaOperator: 1 output tensor required.");
28 }
29
30 if (desc->m_Function != ActivationFunction::Sigmoid)
31 {
32 throw armnn::Exception("ConvertSigmoidToTosaOperator ActivationDescriptor only supports function Sigmoid.");
33 }
34
35 std::string inputName = std::string("input_");
36 std::string outputName = std::string("output0_");
37 std::string blockName = std::string("Op_SIGMOID_block_") + GetUniqueTosaMappingID();
38 std::string supportedTypes = std::string(" Supported Datatypes: INT8, FLOAT16, FLOAT32");
39
40 // If a layer is present then the block will be used for execution, so input and output names need to be determined
41 // using the previous and following layers so the graph is connected correctly. For validation this doesn't matter.
42 if (layer != nullptr)
43 {
44 inputName = GenerateUniqueInputName(layer->GetInputSlot(0));
45 outputName = GenerateUniqueOutputName(*layer);
46 }
47
48 std::vector<TosaSerializationTensor*> tensors;
49 std::vector<TosaSerializationOperator*> operators;
50
51 // Only add input tensors if connected layer is an input layer.
52 // As intermediate or constant tensors will be created separately.
53 // There also can't be duplicate tensor.
54 std::vector<int32_t> inputShape0;
55 if(inputName.find("input_") != std::string::npos)
56 {
57 inputShape0 = GetTosaTensorShape(inputs[0]->GetShape());
58 DType inputDType0 = ArmNNToDType(inputs[0]->GetDataType());
59 tensors.push_back(new TosaSerializationTensor(inputName, inputShape0, inputDType0, {}));
60 }
61
62 DataType inputDType = inputs[0]->GetDataType();
63
64 bool isInt8 = inputDType == DataType::QAsymmS8 || inputDType == DataType::QSymmS8;
65 if (isInt8)
66 {
67 float inputScale = inputs[0]->GetQuantizationScale();
68 float outputScale = outputs[0]->GetQuantizationScale();
69 int32_t inputZp = inputs[0]->GetQuantizationOffset();
70 int32_t outputZp = outputs[0]->GetQuantizationOffset();
71
72 auto sigmoidFunc = [](float x) -> float
73 {
74 return 1.0f / (1.0f + std::exp(-x));
75 };
76
77 TosaTableAttribute attribute(
78 getTosaConst8bitTable(inputScale, inputZp, outputScale, outputZp, sigmoidFunc));
79 operators.push_back(new TosaSerializationOperator(tosa::Op_TABLE,
80 Attribute_TableAttribute,
81 &attribute,
82 {inputName},
83 {outputName}));
84 }
85 else if (inputDType == DataType::QSymmS16)
86 {
87 throw Exception("ConvertSigmoidToTosaOperator(): INT16 is not implemented." + supportedTypes);
88 }
89 else if (inputDType == DataType::Float16 ||
90 inputDType == DataType::Float32)
91 {
92 operators.push_back(new TosaSerializationOperator(tosa::Op_SIGMOID,
93 Attribute_NONE,
94 nullptr,
95 {inputName},
96 {outputName}));
97 }
98 else
99 {
100 throw Exception("ConvertSigmoidToTosaOperator(): TOSA Spec doesn't support this datatype." + supportedTypes);
101 }
102
103 std::vector<int32_t> outputShape0 = GetTosaTensorShape(outputs[0]->GetShape());
104 DType outputDType0 = ArmNNToDType(outputs[0]->GetDataType());
105 tensors.push_back(new TosaSerializationTensor(outputName, outputShape0, outputDType0, {}));
106
107 // operatorInputNames/operatorOutputNames ends up being the same as
108 // blockInputNames/blockOutputNames for one-to-one ArmNN to Tosa mappings
109 return new TosaSerializationBasicBlock(blockName, // name
110 mainName, // region name
111 operators, // operators
112 tensors, // tensors
113 {inputName}, // inputs
114 {outputName}); // outputs
115}
TosaSerializationBasicBlock * ConvertSigmoidToTosaOperator(const Layer *layer, const std::vector< const TensorInfo * > &inputs, const std::vector< const TensorInfo * > &outputs, const ActivationDescriptor *desc)
std::string GenerateUniqueOutputName(const Layer &layer, uint32_t layerSlot=0)
const std::string mainName
DType ArmNNToDType(const DataType &type)
std::string GenerateUniqueInputName(const armnn::InputSlot &slot)
std::string GetUniqueTosaMappingID()
std::vector< int32_t > GetTosaTensorShape(const TensorShape &shape)
std::vector< int16_t > getTosaConst8bitTable(float input_scale, int32_t input_zp, float output_scale, int32_t output_zp, std::function< float(float)> func)
Base class for all ArmNN exceptions so that users can filter to just those.
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition Layer.hpp:337
DataType
Definition Types.hpp:49
An ActivationDescriptor for the ActivationLayer.
ActivationFunction m_Function
The activation function to use (Sigmoid, TanH, Linear, ReLu, BoundedReLu, SoftReLu,...