ArmNN
 25.11
Loading...
Searching...
No Matches
StackOperator.cpp File Reference
#include "StackOperator.hpp"
Include dependency graph for StackOperator.cpp:

Go to the source code of this file.

Functions

TosaSerializationBasicBlock * ConvertStackToTosaOperator (const Layer *layer, const std::vector< const TensorInfo * > &inputs, const std::vector< const TensorInfo * > &outputs, const StackDescriptor *stackDescriptor)

Function Documentation

◆ ConvertStackToTosaOperator()

TosaSerializationBasicBlock * ConvertStackToTosaOperator ( const Layer * layer,
const std::vector< const TensorInfo * > & inputs,
const std::vector< const TensorInfo * > & outputs,
const StackDescriptor * stackDescriptor )

Definition at line 14 of file StackOperator.cpp.

18{
19 ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(inputs.size() >= 1,
20 "ConvertStackToTosaOperator: Stack must have at least one input");
21
22 ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(outputs.size() == 1,
23 "ConvertStackToTosaOperator: Stack must have only one output");
24
25 ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(inputs[0]->GetShape() != TensorShape(Dimensionality::Scalar),
26 "ConvertStackToTosaOperator: Scalar / Rank 0 input not supported");
27
28 const auto inputTensorRank = inputs[0]->GetNumDimensions();
29
30 ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(inputTensorRank != 0,
31 "ConvertStackToTosaOperator: Scalar / Rank 0 input not supported");
32
33 // Verify axis value
34 if (stackDescriptor->m_Axis > inputTensorRank)
35 {
36 throw armnn::Exception("ConvertStackToTosaOperator: Axis is out of a valid range.");
37 }
38
39 // Verify output rank
40 if (outputs[0]->GetNumDimensions() != inputTensorRank + 1)
41 {
42 throw armnn::Exception("ConvertStackToTosaOperator: Output shape mismatch.");
43 }
44
45 auto inputDType = ArmNNToDType(inputs[0]->GetDataType());
46
47 std::vector<TosaSerializationTensor*> tensors;
48 std::vector<TosaSerializationOperator*> operators;
49
50 std::string outputName = std::string("output0_");
51
52 std::string blockName = std::string("Op_STACK_block_") + GetUniqueTosaMappingID();
53 auto blockOutputShape = GetTosaTensorShape(outputs[0]->GetShape());
54
55 // Create input tensors
56 std::vector<std::string> inputNames;
57 for (unsigned int i = 0; i < inputs.size(); ++i)
58 {
59 if (inputs[i]->GetShape() != stackDescriptor->m_InputShape)
60 {
61 throw armnn::Exception("ConvertStackToTosaOperator: Inputs have mismatched shapes.");
62 }
63
64 std::string inputName = "input_" + std::to_string(i);
65
66 if (layer != nullptr)
67 {
68 inputName = GenerateUniqueInputName(layer->GetInputSlot(i));
69 outputName = GenerateUniqueOutputName(*layer);
70
71 }
72 if(inputName.find("input_") != std::string::npos)
73 {
74 tensors.emplace_back(new TosaSerializationTensor(inputName,
75 GetTosaTensorShape(inputs[i]->GetShape()),
76 inputDType,
77 {}));
78 }
79
80 inputNames.push_back(inputName);
81 }
82
83 // Create output tensor
84
85 tensors.emplace_back(new TosaSerializationTensor(outputName,
86 blockOutputShape,
87 inputDType,
88 {}));
89
90 bool transposeOpNeeded = (stackDescriptor->m_Axis == inputTensorRank);
91
92 // Determine concatenation properties and transpose permutation
93 std::vector<int32_t> permutationOrder;
94 std::vector<int32_t> reshapeOutputShape;
95 uint32_t concatAxis;
96 if (transposeOpNeeded)
97 {
98 concatAxis = 0;
99
100 reshapeOutputShape.push_back(static_cast<int32_t>(blockOutputShape[stackDescriptor->m_Axis]));
101
102 for (unsigned int d = 0; d < inputTensorRank; d++)
103 {
104 permutationOrder.push_back(static_cast<int32_t>(d) + 1);
105 reshapeOutputShape.push_back(static_cast<int32_t>(blockOutputShape[d]));
106 }
107 permutationOrder.push_back(0);
108 }
109 else
110 {
111 concatAxis = stackDescriptor->m_Axis;
112 }
113
114 // Determine concatenated output shape
115 std::vector<int32_t> concatOutputShape;
116 auto inputTensorShape = GetTosaTensorShape(stackDescriptor->m_InputShape);
117 for (unsigned int i = 0; i < inputTensorRank; i++)
118 {
119 concatOutputShape.push_back(inputTensorShape[i]);
120 }
121
122 concatOutputShape[concatAxis] *= static_cast<int>(stackDescriptor->m_NumInputs);
123
124 // Concatenation operator
125 std::string concatOutputName = std::string("layer_intermediate1_concat_") + GetUniqueTosaMappingID();
126
127 TosaAxisAttribute axisAttribute(static_cast<int32_t>(concatAxis));
128
129 auto* concatOp = new TosaSerializationOperator(Op_CONCAT,
130 Attribute_AxisAttribute,
131 &axisAttribute,
132 inputNames,
133 {concatOutputName});
134 operators.push_back(concatOp);
135
136 tensors.emplace_back(new TosaSerializationTensor(concatOutputName,
137 concatOutputShape,
138 inputDType,
139 {}));
140
141 // Reshape operator
142 std::string reshapeOutputName = std::string("layer_intermediate2_reshape_") + GetUniqueTosaMappingID();
143 std::string& reshapeOpOutputName = transposeOpNeeded ? reshapeOutputName : outputName;
144
145 TosaReshapeAttribute reshapeAttribute = transposeOpNeeded ? reshapeOutputShape : blockOutputShape;
146
147 auto* reshapeOp = new TosaSerializationOperator(Op_RESHAPE,
148 Attribute_ReshapeAttribute,
149 &reshapeAttribute,
150 {concatOutputName},
151 {reshapeOpOutputName});
152 operators.push_back(reshapeOp);
153
154 if (transposeOpNeeded)
155 {
156 // Transpose operator
157 tensors.emplace_back(new TosaSerializationTensor(reshapeOutputName,
158 reshapeOutputShape,
159 inputDType,
160 {}));
161
162 TosaTransposeAttribute transposeAttribute(permutationOrder);
163
164 TosaSerializationOperator *transposeOp = new TosaSerializationOperator(Op_TRANSPOSE,
165 Attribute_TransposeAttribute,
166 &transposeAttribute,
167 {reshapeOutputName},
168 {outputName});
169 operators.push_back(transposeOp);
170 }
171
172 // operatorInputNames/operatorOutputNames ends up being the same as
173 // blockInputNames/blockOutputNames for one-to-one ArmNN to TOSA mappings
174 return new TosaSerializationBasicBlock(blockName, // name
175 mainName, // region name
176 operators, // operators
177 tensors, // tensors
178 inputNames, // inputs
179 {outputName}); // outputs
180}
#define ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(_cond, _str)
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)
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
TensorShape m_InputShape
Required shape of all input tensors.
uint32_t m_Axis
0-based axis along which to stack the input tensors.
uint32_t m_NumInputs
Number of input tensors.

References ARMNN_THROW_INVALIDARG_MSG_IF_FALSE, ArmNNToDType(), GenerateUniqueInputName(), GenerateUniqueOutputName(), Layer::GetInputSlot(), GetTosaTensorShape(), GetUniqueTosaMappingID(), StackDescriptor::m_Axis, StackDescriptor::m_InputShape, StackDescriptor::m_NumInputs, and mainName.

Referenced by GetTosaMapping().