blob: 2dc302ed302d4ca229d6082803c45c50c2017458 [file] [log] [blame]
telsoa015307bc12018-03-09 13:51:08 +00001//
Mike Kellye2d611e2021-10-14 12:35:58 +01002// Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
David Beck93e48982018-09-05 13:05:09 +01003// SPDX-License-Identifier: MIT
telsoa015307bc12018-03-09 13:51:08 +00004//
5
6#define LOG_TAG "ArmnnDriver"
7
8#include "ModelToINetworkConverter.hpp"
Kevin May42477c12020-03-26 13:34:14 +00009#include "Utils.hpp"
telsoa015307bc12018-03-09 13:51:08 +000010
11#include <log/log.h>
Kevin May42477c12020-03-26 13:34:14 +000012#include <type_traits>
telsoa01ce3e84a2018-08-31 09:31:35 +010013
Sadik Armagan188675f2021-02-12 17:16:42 +000014#ifdef ARMNN_ANDROID_S
15#include <LegacyUtils.h>
16#endif
17
surmeh0149b9e102018-05-17 14:11:25 +010018namespace armnn_driver
19{
kevmay01bc5f7842018-08-30 12:34:39 +010020
arovir01b0717b52018-09-05 17:03:25 +010021template<typename HalPolicy>
Nattapat Chaimanowongd5fd9762019-04-04 13:33:10 +010022ModelToINetworkConverter<HalPolicy>::ModelToINetworkConverter(const std::vector<armnn::BackendId>& backends,
kevmay01bc5f7842018-08-30 12:34:39 +010023 const HalModel& model,
telsoa015307bc12018-03-09 13:51:08 +000024 const std::set<unsigned int>& forcedUnsupportedOperations)
Nattapat Chaimanowongd5fd9762019-04-04 13:33:10 +010025 : m_Data(backends)
telsoa015307bc12018-03-09 13:51:08 +000026 , m_Model(model)
27 , m_ForcedUnsupportedOperations(forcedUnsupportedOperations)
telsoa015307bc12018-03-09 13:51:08 +000028 , m_ConversionResult(ConversionResult::Success)
29{
30 try
31 {
32 Convert();
33 }
Derek Lambertib9cb8442019-11-28 13:34:48 +000034 catch (std::exception& e)
telsoa015307bc12018-03-09 13:51:08 +000035 {
36 m_ConversionResult = ConversionResult::UnsupportedFeature;
37 ALOGE("%s: Unexpected exception: %s", __func__, e.what());
telsoa015307bc12018-03-09 13:51:08 +000038 }
39}
40
arovir01b0717b52018-09-05 17:03:25 +010041template<typename HalPolicy>
42void ModelToINetworkConverter<HalPolicy>::Convert()
telsoa015307bc12018-03-09 13:51:08 +000043{
Sadik Armagan44bcc022019-06-18 17:21:36 +010044 using HalModel = typename HalPolicy::Model;
45 using HalOperand = typename HalPolicy::Operand;
46 using HalOperandType = typename HalPolicy::OperandType;
Matteo Martincighe48bdff2018-09-03 13:50:50 +010047
arovir01a15dc112018-09-03 17:12:56 +010048 ALOGV("ModelToINetworkConverter::Convert(): %s", GetModelSummary<HalModel>(m_Model).c_str());
telsoa015307bc12018-03-09 13:51:08 +000049
50 // map the memory pool into shared pointers
arovir01b0717b52018-09-05 17:03:25 +010051 m_Data.m_MemPools.clear();
Sadik Armagan188675f2021-02-12 17:16:42 +000052#if !defined(ARMNN_ANDROID_S)
arovir01b0717b52018-09-05 17:03:25 +010053 if (!setRunTimePoolInfosFromHidlMemories(&m_Data.m_MemPools, m_Model.pools))
Sadik Armagan188675f2021-02-12 17:16:42 +000054#else
55 if (!setRunTimePoolInfosFromCanonicalMemories(&m_Data.m_MemPools, uncheckedConvert(m_Model.pools)))
56#endif
telsoa015307bc12018-03-09 13:51:08 +000057 {
58 Fail("%s: Setting of run time pool infos from Hidl Memories has failed.", __func__);
59 m_ConversionResult = ConversionResult::ErrorMappingPools;
60 return;
61 }
62
Sadik Armagan188675f2021-02-12 17:16:42 +000063
telsoa015307bc12018-03-09 13:51:08 +000064 uint32_t totalPoolSize = 0;
65 for (auto&& pool : m_Model.pools)
66 {
67 totalPoolSize += pool.size();
68 }
69
Finn Williamsa4983ce2020-07-23 12:55:12 +010070 using NetworkOptions = std::vector<armnn::BackendOptions>;
71 NetworkOptions networkOptions;
72 armnn::BackendOptions shapeInferenceMethodOption("ShapeInferenceMethod",
73 {
74 { "InferAndValidate", true }
75 });
76
77 networkOptions.push_back(shapeInferenceMethodOption);
78
telsoa015307bc12018-03-09 13:51:08 +000079 // Create armnn::INetwork
Finn Williamsa4983ce2020-07-23 12:55:12 +010080 m_Data.m_Network = armnn::INetwork::Create(networkOptions);
telsoa015307bc12018-03-09 13:51:08 +000081
82 // add operations to it
83 // track which layer outputs each operand
Kevin May42477c12020-03-26 13:34:14 +000084 ALOGV("ModelToINetworkConverter::Convert(): m_OutputSlotForOperand");
85 m_Data.m_OutputSlotForOperand = std::vector<armnn::IOutputSlot*>(getMainModel(m_Model).operands.size(), nullptr);
telsoa015307bc12018-03-09 13:51:08 +000086 try
87 {
Kevin May42477c12020-03-26 13:34:14 +000088 ALOGV("ModelToINetworkConverter::Convert(): for getMainModel(m_Model).inputIndexes.size()");
89 for (uint32_t i = 0; i < getMainModel(m_Model).inputIndexes.size(); i++)
telsoa015307bc12018-03-09 13:51:08 +000090 {
Kevin May42477c12020-03-26 13:34:14 +000091 ALOGV("ModelToINetworkConverter::Convert(): getMainModel(m_Model).inputIndexes[i]");
telsoa015307bc12018-03-09 13:51:08 +000092 // inputs in android nn are represented by operands
Kevin May42477c12020-03-26 13:34:14 +000093 uint32_t inputIndex = getMainModel(m_Model).inputIndexes[i];
94 ALOGV("ModelToINetworkConverter::Convert(): getMainModel(m_Model).operands[inputIndex];");
95 const HalOperand& operand = getMainModel(m_Model).operands[inputIndex];
96 ALOGV("ModelToINetworkConverter::Convert(): GetTensorInfoForOperand(operand)");
Sadik Armaganb3021432021-01-13 15:56:51 +000097 const std::string layerName = "Input_" + std::to_string(i);
98 ALOGV("ModelToINetworkConverter::Convert(): m_Data.m_Network->AddInputLayer(i, layerName.c_str())");
99 armnn::IConnectableLayer* layer = m_Data.m_Network->AddInputLayer(i, layerName.c_str());
telsoa015307bc12018-03-09 13:51:08 +0000100
Kevin May42477c12020-03-26 13:34:14 +0000101 ALOGV("ModelToINetworkConverter::Convert(): layer->GetOutputSlot(0)");
telsoa015307bc12018-03-09 13:51:08 +0000102 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
Kevin May42477c12020-03-26 13:34:14 +0000103 ALOGV("ModelToINetworkConverter::Convert(): outputSlot.SetTensorInfo(GetTensorInfoForOperand(operand))");
telsoa015307bc12018-03-09 13:51:08 +0000104 outputSlot.SetTensorInfo(GetTensorInfoForOperand(operand));
105
Kevin May42477c12020-03-26 13:34:14 +0000106 ALOGV("ModelToINetworkConverter::Convert(): m_Data.m_OutputSlotForOperand[inputIndex] = &outputSlot");
telsoa015307bc12018-03-09 13:51:08 +0000107 // store for later layers
arovir01b0717b52018-09-05 17:03:25 +0100108 m_Data.m_OutputSlotForOperand[inputIndex] = &outputSlot;
telsoa015307bc12018-03-09 13:51:08 +0000109 }
110 }
Sadik Armagan44bcc022019-06-18 17:21:36 +0100111 catch (UnsupportedOperand<HalOperandType>& e)
telsoa015307bc12018-03-09 13:51:08 +0000112 {
113 Fail("%s: Operand type %s not supported in ArmnnDriver", __func__, toString(e.m_type).c_str());
114 m_ConversionResult = ConversionResult::UnsupportedFeature;
115 }
116 catch (const armnn::InvalidArgumentException& e)
117 {
118 Fail("%s: Failed to convert input operand to TensorShape: %s", __func__, e.what());
119 m_ConversionResult = ConversionResult::UnsupportedFeature;
120 }
Finn Williams291a16b2020-08-19 22:54:00 +0100121 bool UnsupportedDynamicOperation = false;
Kevin May42477c12020-03-26 13:34:14 +0000122 for (uint32_t operationIdx = 0; operationIdx < getMainModel(m_Model).operations.size(); operationIdx++)
telsoa015307bc12018-03-09 13:51:08 +0000123 {
Kevin May42477c12020-03-26 13:34:14 +0000124 const auto& operation = getMainModel(m_Model).operations[operationIdx];
telsoa015307bc12018-03-09 13:51:08 +0000125
126 bool ok = true;
127 if (m_ForcedUnsupportedOperations.find(operationIdx) != m_ForcedUnsupportedOperations.end())
128 {
129 Fail("%s: Operation at index %i has been forced to be unsupported.", __func__, operationIdx);
130 ok = false;
131 }
132
133 if (ok)
134 {
135 try
136 {
arovir01b0717b52018-09-05 17:03:25 +0100137 ok = HalPolicy::ConvertOperation(operation, m_Model, m_Data);
telsoa015307bc12018-03-09 13:51:08 +0000138 }
Sadik Armagan44bcc022019-06-18 17:21:36 +0100139 catch (UnsupportedOperand<HalOperandType>& e)
telsoa015307bc12018-03-09 13:51:08 +0000140 {
141 Fail("%s: Operand type %s not supported in ArmnnDriver", __func__, toString(e.m_type).c_str());
142 ok = false;
143 }
144 catch (const armnn::InvalidArgumentException& e)
145 {
146 Fail("%s: Failed to convert operation in %s", __func__, e.what());
147 ok = false;
148 }
149 }
150
151 // Store whether this operation was successfully converted.
152 m_OperationSupported.emplace(operationIdx, ok);
153
154 // Any single operation failing will fail the entire conversion.
155 // We still need to continue and check the other ones.
156 if (!ok)
157 {
Finn Williams291a16b2020-08-19 22:54:00 +0100158 if (m_Data.m_DynamicInputsEncountered)
159 {
160 Fail("%s: The unsupported operation at index %i has dynamic inputs.", __func__, operationIdx);
161 UnsupportedDynamicOperation = true;
162 }
163
telsoa015307bc12018-03-09 13:51:08 +0000164 m_ConversionResult = ConversionResult::UnsupportedFeature;
165 }
Finn Williams291a16b2020-08-19 22:54:00 +0100166 m_Data.m_DynamicInputsEncountered = false;
telsoa015307bc12018-03-09 13:51:08 +0000167 }
Finn Williams291a16b2020-08-19 22:54:00 +0100168
169 // Due to the NNAPI partitioner not supporting partition boundaries of unknown size,
170 // any operations who's outputs connect to an unsupported operation with with dynamic inputs
171 // will cause a failure.
172
173 // The simplest solution to this problem is to not support any operations in a model containing
174 // an unsupported operation with with dynamic inputs.
175 if (UnsupportedDynamicOperation)
176 {
177 Fail("%s: Unsupported operation with dynamic inputs found. Retroactively setting all operations to unsupported",
178 __func__);
179 for (auto& operation : m_OperationSupported)
180 {
181 operation.second = false;
182 }
183 }
184
telsoa015307bc12018-03-09 13:51:08 +0000185 try
186 {
187 if (m_ConversionResult == ConversionResult::Success)
188 {
Kevin May42477c12020-03-26 13:34:14 +0000189 for (uint32_t i = 0; i < getMainModel(m_Model).outputIndexes.size(); i++)
telsoa015307bc12018-03-09 13:51:08 +0000190 {
191 // outputs in android nn are represented by operands
Kevin May42477c12020-03-26 13:34:14 +0000192 uint32_t outputIndex = getMainModel(m_Model).outputIndexes[i];
Sadik Armaganb3021432021-01-13 15:56:51 +0000193 const std::string layerName = "Output_" + std::to_string(i);
194 armnn::IConnectableLayer* layer = m_Data.m_Network->AddOutputLayer(i, layerName.c_str());
telsoa015307bc12018-03-09 13:51:08 +0000195
Mike Kellye2d611e2021-10-14 12:35:58 +0100196 if (!m_Data.m_OutputSlotForOperand[outputIndex])
197 {
198 Fail("%s: OutputSlot %i does not exist", __func__, outputIndex);
199 m_ConversionResult = ConversionResult::UnsupportedFeature;
200 break;
201 }
arovir01b0717b52018-09-05 17:03:25 +0100202 m_Data.m_OutputSlotForOperand[outputIndex]->Connect(layer->GetInputSlot(0));
telsoa015307bc12018-03-09 13:51:08 +0000203 }
204 }
205 }
206 catch (const armnn::InvalidArgumentException& e)
207 {
208 Fail("%s: Failed to convert output operand to TensorShape: %s", __func__, e.what());
209 m_ConversionResult = ConversionResult::UnsupportedFeature;
210 }
211}
212
arovir01b0717b52018-09-05 17:03:25 +0100213template<typename HalPolicy>
214bool ModelToINetworkConverter<HalPolicy>::IsOperationSupported(uint32_t operationIndex) const
telsoa015307bc12018-03-09 13:51:08 +0000215{
216 std::map<uint32_t, bool>::const_iterator it = m_OperationSupported.find(operationIndex);
Mike Kellye2d611e2021-10-14 12:35:58 +0100217 if (it == m_OperationSupported.end())
218 {
219 return Fail("%s: Unrecognised Operation Index: %i", __func__, operationIndex);
220 }
telsoa015307bc12018-03-09 13:51:08 +0000221 return it->second;
222}
223
arovir01b0717b52018-09-05 17:03:25 +0100224///
225/// Class template specializations
226///
telsoa015307bc12018-03-09 13:51:08 +0000227
arovir01b0717b52018-09-05 17:03:25 +0100228template class ModelToINetworkConverter<hal_1_0::HalPolicy>;
229
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100230#ifdef ARMNN_ANDROID_NN_V1_1
arovir01b0717b52018-09-05 17:03:25 +0100231template class ModelToINetworkConverter<hal_1_1::HalPolicy>;
kevmay01bc5f7842018-08-30 12:34:39 +0100232#endif
233
Mike Kellyb5fdf382019-06-11 16:35:25 +0100234#ifdef ARMNN_ANDROID_NN_V1_2
235template class ModelToINetworkConverter<hal_1_1::HalPolicy>;
236template class ModelToINetworkConverter<hal_1_2::HalPolicy>;
237#endif
238
Kevin May42477c12020-03-26 13:34:14 +0000239#ifdef ARMNN_ANDROID_NN_V1_3
240template class ModelToINetworkConverter<hal_1_1::HalPolicy>;
241template class ModelToINetworkConverter<hal_1_2::HalPolicy>;
242template class ModelToINetworkConverter<hal_1_3::HalPolicy>;
243#endif
244
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100245} // armnn_driver