ArmNN
 25.11
Loading...
Searching...
No Matches
LeakyReluOperator.cpp File Reference
Include dependency graph for LeakyReluOperator.cpp:

Go to the source code of this file.

Functions

TosaSerializationBasicBlock * ConvertLeakyReluToTosaOperator (const Layer *layer, const std::vector< const TensorInfo * > &inputs, const std::vector< const TensorInfo * > &outputs, const ActivationDescriptor *activationDescriptor)

Function Documentation

◆ ConvertLeakyReluToTosaOperator()

TosaSerializationBasicBlock * ConvertLeakyReluToTosaOperator ( const Layer * layer,
const std::vector< const TensorInfo * > & inputs,
const std::vector< const TensorInfo * > & outputs,
const ActivationDescriptor * activationDescriptor )

Definition at line 17 of file LeakyReluOperator.cpp.

21{
22 if (inputs.size() != 1)
23 {
24 throw armnn::Exception("ConvertLeakyReluToTosaOperator: 1 input tensors required.");
25 }
26
27 if (outputs.size() != 1)
28 {
29 throw armnn::Exception("ConvertLeakyReluToTosaOperator: 1 output tensor required.");
30 }
31
32 std::string inputName = std::string("input_");
33 std::string outputNameAlpha = std::string("constant0_") + GetUniqueTosaMappingID();
34 std::string outputNameMul = std::string("layer_intermediate1_") + GetUniqueTosaMappingID();
35 std::string outputName = std::string("output0_");
36 std::string blockName = std::string("Op_LEAKY_RELU_block_") + GetUniqueTosaMappingID();
37
38 // If a layer is present then the block will be used for execution, so input and output names need to be determined
39 // using the previous and following layers so the graph is connected correctly. For validation this doesn't matter.
40 if (layer != nullptr)
41 {
42 inputName = GenerateUniqueInputName(layer->GetInputSlot(0));
43 outputName = GenerateUniqueOutputName(*layer);
44 }
45
46 std::vector<TosaSerializationTensor*> tensors;
47
48 // Only add input tensors if connected layer is an input layer.
49 // As intermediate or constant tensors will be created separately.
50 // There also can't be duplicate tensor.
51 std::vector<int32_t> inputShape0;
52 DType inputDType0 = ArmNNToDType(inputs[0]->GetDataType());
53 if(inputName.find("input_") != std::string::npos)
54 {
55 inputShape0 = GetTosaTensorShape(inputs[0]->GetShape());
56 tensors.push_back(new TosaSerializationTensor(inputName, inputShape0, inputDType0, {}));
57 }
58
59 std::vector<int32_t> outputShape0 = GetTosaTensorShape(outputs[0]->GetShape());
60 DType outputDType0 = ArmNNToDType(outputs[0]->GetDataType());
61 tensors.push_back(new TosaSerializationTensor(outputName, outputShape0, outputDType0, {}));
62
63 if (inputDType0 == DType::DType_FP32 ||
64 inputDType0 == DType::DType_FP16)
65 {
66 // const_alpha
67 TosaSerializationOperator* alphaOp = nullptr;
68 TosaSerializationTensor* alphaTensor = nullptr;
69 CreateConstTosaOperator<float>(outputNameAlpha,
70 activationDescriptor->m_A,
71 inputDType0,
72 inputShape0,
73 alphaOp,
74 alphaTensor);
75 tensors.push_back(alphaTensor);
76
77 // mul
78 int32_t shift = 0;
79 TosaMulAttribute mulAttribute(shift);
80 TosaSerializationOperator* mulOp = new TosaSerializationOperator(Op_MUL,
81 Attribute_MulAttribute,
82 &mulAttribute,
83 {inputName, outputNameAlpha},
84 {outputNameMul});
85 tensors.push_back(new TosaSerializationTensor(outputNameMul, inputShape0, inputDType0, {}));
86
87 TosaSerializationOperator* op = nullptr;
88 if (activationDescriptor->m_A <= 1.0)
89 {
90 op = new TosaSerializationOperator(Op_MAXIMUM,
91 Attribute_NONE,
92 nullptr,
93 {inputName, outputNameMul},
94 {outputName});
95 }
96 else
97 {
98 op = new TosaSerializationOperator(Op_MINIMUM,
99 Attribute_NONE,
100 nullptr,
101 {inputName, outputNameMul},
102 {outputName});
103
104 }
105
106 // operatorInputNames/operatorOutputNames ends up being the same as
107 // blockInputNames/blockOutputNames for one-to-one ArmNN to Tosa mappings
108 return new TosaSerializationBasicBlock(blockName, // name
109 mainName, // region name
110 {alphaOp, mulOp, op}, // operators
111 tensors, // tensors
112 {inputName}, // inputs
113 {outputName}); // outputs
114 }
115 else
116 {
117 std::string outputNameRescaleAlpha = std::string("layer_intermediate2_") + GetUniqueTosaMappingID();
118 std::string outputNameRescaleIdentity = std::string("layer_intermediate3_") + GetUniqueTosaMappingID();
119 std::string outputNameRescaleMaxMin = std::string("layer_intermediate4_") + GetUniqueTosaMappingID();
120
121 DType rescale_type = DType::DType_INT32;
122 float alpha = activationDescriptor->m_A;
123 double scale_alpha = inputs[0]->GetQuantizationScale() * alpha / outputs[0]->GetQuantizationScale();
124 double scale_identity = inputs[0]->GetQuantizationScale() / outputs[0]->GetQuantizationScale();
125 int32_t input_zp = inputs[0]->GetQuantizationOffset();
126 int32_t output_zp = outputs[0]->GetQuantizationOffset();
127
128 // Value op_rescale_alpha_in =
129 // buildRescale(rewriter, op, rescale_type, input, scale_alpha,
130 // input_qtype.getZeroPoint(), 0, true, true);
131 TosaSerializationOperator* rescaleAlphaOp = nullptr;
133 outputNameRescaleAlpha,
134 scale_alpha,
135 input_zp,
136 0,
137 false,
138 false,
139 true,
140 true,
141 &rescaleAlphaOp);
142 tensors.push_back(new TosaSerializationTensor(outputNameRescaleAlpha,
143 GetTosaTensorShape(inputs[0]->GetShape()),
144 rescale_type, {}));
145 // Value op_rescale_identity_in =
146 // buildRescale(rewriter, op, rescale_type, input, scale_identity,
147 // input_qtype.getZeroPoint(), 0, true, true);
148 TosaSerializationOperator* rescaleIdentityOp = nullptr;
150 outputNameRescaleIdentity,
151 scale_identity,
152 input_zp,
153 0,
154 false,
155 false,
156 true,
157 true,
158 &rescaleIdentityOp);
159 tensors.push_back(new TosaSerializationTensor(outputNameRescaleIdentity,
160 GetTosaTensorShape(inputs[0]->GetShape()),
161 rescale_type, {}));
162 // Value result_int32;
163 // if (alpha <= 1.0) {
164 // auto max_op = CreateOpAndInfer<tosa::MaximumOp>(
165 // rewriter, op->getLoc(), rescale_type, op_rescale_identity_in,
166 // op_rescale_alpha_in);
167 // result_int32 = max_op.getResult();
168 // } else {
169 // auto min_op = CreateOpAndInfer<tosa::MinimumOp>(
170 // rewriter, op->getLoc(), rescale_type, op_rescale_identity_in,
171 // op_rescale_alpha_in);
172 // result_int32 = min_op.getResult();
173 // }
174 TosaSerializationOperator* op = nullptr;
175 if (alpha <= 1.0)
176 {
177 op = new TosaSerializationOperator(Op_MAXIMUM,
178 Attribute_NONE,
179 nullptr,
180 {outputNameRescaleAlpha, outputNameRescaleIdentity},
181 {outputNameRescaleMaxMin});
182 }
183 else
184 {
185 op = new TosaSerializationOperator(Op_MINIMUM,
186 Attribute_NONE,
187 nullptr,
188 {outputNameRescaleAlpha, outputNameRescaleIdentity},
189 {outputNameRescaleMaxMin});
190
191 }
192 tensors.push_back(new TosaSerializationTensor(outputNameRescaleMaxMin,
193 GetTosaTensorShape(inputs[0]->GetShape()),
194 rescale_type, {}));
195
196 // Value output = buildRescaleFromInt32(rewriter, op, output_type, result_int32,
197 // 1.0, output_qtype.getZeroPoint());
198 TosaSerializationOperator* rescaleOutputOp = nullptr;
199 CreateRescaleTosaOperator(outputNameRescaleMaxMin,
200 outputName,
201 1.0,
202 0,
203 output_zp,
204 false,
205 false,
206 true,
207 true,
208 &rescaleOutputOp);
209
210 // operatorInputNames/operatorOutputNames ends up being the same as
211 // blockInputNames/blockOutputNames for one-to-one ArmNN to Tosa mappings
212 return new TosaSerializationBasicBlock(blockName, // name
213 mainName, // region name
214 {rescaleAlphaOp, rescaleIdentityOp, op, rescaleOutputOp}, // operators
215 tensors, // tensors
216 {inputName}, // inputs
217 {outputName}); // outputs
218 }
219}
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)
void CreateConstTosaOperator(const std::string &outputName, const T value, DType dtype, const std::vector< int32_t > &shape, TosaSerializationOperator *&op, TosaSerializationTensor *&tensor)
void CreateRescaleTosaOperator(const std::string &inputName, const std::string &outputName, double scale, int32_t input_zp, int32_t output_zp, bool input_unsigned, bool output_unsigned, bool double_round, bool scale32, TosaSerializationOperator **op)
Creates a Tosa rescale operator.
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
float m_A
Alpha upper bound value used by the activation functions. (BoundedReLu, Linear, TanH,...

References ArmNNToDType(), CreateConstTosaOperator(), CreateRescaleTosaOperator(), GenerateUniqueInputName(), GenerateUniqueOutputName(), Layer::GetInputSlot(), GetTosaTensorShape(), GetUniqueTosaMappingID(), ActivationDescriptor::m_A, and mainName.

Referenced by GetTosaMapping().