18 const std::vector<const TensorInfo*>& inputs,
19 const std::vector<const TensorInfo*>& outputs,
25 throw armnn::Exception(
"ConvertReduceOperator: Must provide a valid input tensor.");
28 if (inputs[0]->IsQuantized() ^ outputs[0]->IsQuantized())
31 "Both input and output tensors must be either quantised or non-quantised data types.");
34 if (reduceDescriptor->
m_vAxis.size() > 1)
36 throw armnn::Exception(
"ConvertReduceOperator: Reduce Operation with multiple axes not implemented.");
39 if (reduceDescriptor->
m_vAxis.empty())
41 throw armnn::Exception(
"ConvertReduceOperator: Reduce Operation with empty axis not implemented.");
44 auto axis =
static_cast<int32_t
>(reduceDescriptor->
m_vAxis[0]);
45 auto rank =
static_cast<int32_t
>(inputs[0]->GetNumDimensions());
47 if (axis < 0 || axis >= rank)
53 std::string inputName =
"input_";
60 std::string outputName =
"output0_";
74 std::vector<TosaSerializationTensor*> tensors;
75 std::vector<std::string> inputNames{inputName};
77 DType inputType =
ArmNNToDType(inputs[0]->GetDataType());
79 if (inputName.substr(0, 6) ==
"input_")
81 tensors.emplace_back(
new TosaSerializationTensor(inputName,
87 int32_t input_shift = 20;
89 double input_scale =
static_cast<double>(1 << input_shift) * inputs[0]->GetQuantizationScale();
90 double output_scale = 1.0 / (outputs[0]->GetQuantizationScale() *
static_cast<double>(1 << input_shift));
93 int32_t output_zp = 0;
95 std::vector<TosaSerializationOperator*> operators;
98 if (inputs[0]->IsQuantized())
100 TosaSerializationOperator* rescaleOp1 =
nullptr;
111 operators.emplace_back(rescaleOp1);
113 tensors.emplace_back(
new TosaSerializationTensor(outputNameRescale1,
120 TosaAxisAttribute reduceAttribute(axis);
124 case ReduceOperation::Sum:
125 case ReduceOperation::Mean:
126 operators.emplace_back(
new TosaSerializationOperator(Op_REDUCE_SUM,
127 Attribute_AxisAttribute,
129 { tensors.back()->GetName() },
130 { outputNameReduce }));
133 throw armnn::Exception(
"ConvertReduceOperator: Reduce Operation not implemented.");
136 std::vector<int32_t> outputShapeReduce = inputShape;
137 outputShapeReduce[reduceDescriptor->
m_vAxis[0]] = 1;
139 tensors.emplace_back(
new TosaSerializationTensor(outputNameReduce,
141 tensors.back()->GetDtype(),
145 auto numElemsOnReducedAxis = inputShape[
static_cast<unsigned long>(axis)];
146 float divScale = 1.0f /
static_cast<float>(numElemsOnReducedAxis);
147 if (inputs[0]->IsQuantized())
153 output_scale *= divScale;
156 TosaSerializationOperator* rescaleOp2 =
nullptr;
167 operators.push_back(rescaleOp2);
169 tensors.emplace_back(
new TosaSerializationTensor(outputNameRescale2,
181 inputNames.emplace_back(divConstantName);
183 operators.push_back(
new TosaSerializationOperator(Op_CONST,
189 std::vector<uint8_t> uint8DivScale;
193 TosaSerializationHandler::ConvertF16toU8({divScale}, uint8DivScale);
196 TosaSerializationHandler::ConvertF32toU8({divScale}, uint8DivScale);
202 std::vector<int32_t> divConstantShape (outputShapeReduce.size(), 1);
203 tensors.push_back(
new TosaSerializationTensor(divConstantName,
210 TosaMulAttribute mulAttribute(shift);
212 operators.emplace_back(
new TosaSerializationOperator(Op_MUL,
213 Attribute_MulAttribute,
215 {divConstantName, outputNameReduce},
217 tensors.push_back(
new TosaSerializationTensor(outputNameMul,
227 operators.emplace_back(
new TosaSerializationOperator(Op_RESHAPE,
228 Attribute_ReshapeAttribute,
230 { tensors.back()->GetName() },
233 tensors.emplace_back(
new TosaSerializationTensor(outputName,
238 return new TosaSerializationBasicBlock(blockName,