blob: 41716b0fcea6f841076f137945a9d0538756ca2c [file] [log] [blame]
telsoa015307bc12018-03-09 13:51:08 +00001//
2// Copyright © 2017 Arm Ltd. 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());
38 assert(false);
39 }
40}
41
arovir01b0717b52018-09-05 17:03:25 +010042template<typename HalPolicy>
43void ModelToINetworkConverter<HalPolicy>::Convert()
telsoa015307bc12018-03-09 13:51:08 +000044{
Sadik Armagan44bcc022019-06-18 17:21:36 +010045 using HalModel = typename HalPolicy::Model;
46 using HalOperand = typename HalPolicy::Operand;
47 using HalOperandType = typename HalPolicy::OperandType;
Matteo Martincighe48bdff2018-09-03 13:50:50 +010048
arovir01a15dc112018-09-03 17:12:56 +010049 ALOGV("ModelToINetworkConverter::Convert(): %s", GetModelSummary<HalModel>(m_Model).c_str());
telsoa015307bc12018-03-09 13:51:08 +000050
51 // map the memory pool into shared pointers
arovir01b0717b52018-09-05 17:03:25 +010052 m_Data.m_MemPools.clear();
Sadik Armagan188675f2021-02-12 17:16:42 +000053#if !defined(ARMNN_ANDROID_S)
arovir01b0717b52018-09-05 17:03:25 +010054 if (!setRunTimePoolInfosFromHidlMemories(&m_Data.m_MemPools, m_Model.pools))
Sadik Armagan188675f2021-02-12 17:16:42 +000055#else
56 if (!setRunTimePoolInfosFromCanonicalMemories(&m_Data.m_MemPools, uncheckedConvert(m_Model.pools)))
57#endif
telsoa015307bc12018-03-09 13:51:08 +000058 {
59 Fail("%s: Setting of run time pool infos from Hidl Memories has failed.", __func__);
60 m_ConversionResult = ConversionResult::ErrorMappingPools;
61 return;
62 }
63
Sadik Armagan188675f2021-02-12 17:16:42 +000064
telsoa015307bc12018-03-09 13:51:08 +000065 uint32_t totalPoolSize = 0;
66 for (auto&& pool : m_Model.pools)
67 {
68 totalPoolSize += pool.size();
69 }
70
Finn Williamsa4983ce2020-07-23 12:55:12 +010071 using NetworkOptions = std::vector<armnn::BackendOptions>;
72 NetworkOptions networkOptions;
73 armnn::BackendOptions shapeInferenceMethodOption("ShapeInferenceMethod",
74 {
75 { "InferAndValidate", true }
76 });
77
78 networkOptions.push_back(shapeInferenceMethodOption);
79
telsoa015307bc12018-03-09 13:51:08 +000080 // Create armnn::INetwork
Finn Williamsa4983ce2020-07-23 12:55:12 +010081 m_Data.m_Network = armnn::INetwork::Create(networkOptions);
telsoa015307bc12018-03-09 13:51:08 +000082
83 // add operations to it
84 // track which layer outputs each operand
Kevin May42477c12020-03-26 13:34:14 +000085 ALOGV("ModelToINetworkConverter::Convert(): m_OutputSlotForOperand");
86 m_Data.m_OutputSlotForOperand = std::vector<armnn::IOutputSlot*>(getMainModel(m_Model).operands.size(), nullptr);
telsoa015307bc12018-03-09 13:51:08 +000087 try
88 {
Kevin May42477c12020-03-26 13:34:14 +000089 ALOGV("ModelToINetworkConverter::Convert(): for getMainModel(m_Model).inputIndexes.size()");
90 for (uint32_t i = 0; i < getMainModel(m_Model).inputIndexes.size(); i++)
telsoa015307bc12018-03-09 13:51:08 +000091 {
Kevin May42477c12020-03-26 13:34:14 +000092 ALOGV("ModelToINetworkConverter::Convert(): getMainModel(m_Model).inputIndexes[i]");
telsoa015307bc12018-03-09 13:51:08 +000093 // inputs in android nn are represented by operands
Kevin May42477c12020-03-26 13:34:14 +000094 uint32_t inputIndex = getMainModel(m_Model).inputIndexes[i];
95 ALOGV("ModelToINetworkConverter::Convert(): getMainModel(m_Model).operands[inputIndex];");
96 const HalOperand& operand = getMainModel(m_Model).operands[inputIndex];
97 ALOGV("ModelToINetworkConverter::Convert(): GetTensorInfoForOperand(operand)");
telsoa015307bc12018-03-09 13:51:08 +000098 const armnn::TensorInfo& tensor = GetTensorInfoForOperand(operand);
Sadik Armaganb3021432021-01-13 15:56:51 +000099 const std::string layerName = "Input_" + std::to_string(i);
100 ALOGV("ModelToINetworkConverter::Convert(): m_Data.m_Network->AddInputLayer(i, layerName.c_str())");
101 armnn::IConnectableLayer* layer = m_Data.m_Network->AddInputLayer(i, layerName.c_str());
telsoa015307bc12018-03-09 13:51:08 +0000102
Kevin May42477c12020-03-26 13:34:14 +0000103 ALOGV("ModelToINetworkConverter::Convert(): layer->GetOutputSlot(0)");
telsoa015307bc12018-03-09 13:51:08 +0000104 armnn::IOutputSlot& outputSlot = layer->GetOutputSlot(0);
Kevin May42477c12020-03-26 13:34:14 +0000105 ALOGV("ModelToINetworkConverter::Convert(): outputSlot.SetTensorInfo(GetTensorInfoForOperand(operand))");
telsoa015307bc12018-03-09 13:51:08 +0000106 outputSlot.SetTensorInfo(GetTensorInfoForOperand(operand));
107
Kevin May42477c12020-03-26 13:34:14 +0000108 ALOGV("ModelToINetworkConverter::Convert(): m_Data.m_OutputSlotForOperand[inputIndex] = &outputSlot");
telsoa015307bc12018-03-09 13:51:08 +0000109 // store for later layers
arovir01b0717b52018-09-05 17:03:25 +0100110 m_Data.m_OutputSlotForOperand[inputIndex] = &outputSlot;
telsoa015307bc12018-03-09 13:51:08 +0000111 }
112 }
Sadik Armagan44bcc022019-06-18 17:21:36 +0100113 catch (UnsupportedOperand<HalOperandType>& e)
telsoa015307bc12018-03-09 13:51:08 +0000114 {
115 Fail("%s: Operand type %s not supported in ArmnnDriver", __func__, toString(e.m_type).c_str());
116 m_ConversionResult = ConversionResult::UnsupportedFeature;
117 }
118 catch (const armnn::InvalidArgumentException& e)
119 {
120 Fail("%s: Failed to convert input operand to TensorShape: %s", __func__, e.what());
121 m_ConversionResult = ConversionResult::UnsupportedFeature;
122 }
Finn Williams291a16b2020-08-19 22:54:00 +0100123 bool UnsupportedDynamicOperation = false;
Kevin May42477c12020-03-26 13:34:14 +0000124 for (uint32_t operationIdx = 0; operationIdx < getMainModel(m_Model).operations.size(); operationIdx++)
telsoa015307bc12018-03-09 13:51:08 +0000125 {
Kevin May42477c12020-03-26 13:34:14 +0000126 const auto& operation = getMainModel(m_Model).operations[operationIdx];
telsoa015307bc12018-03-09 13:51:08 +0000127
128 bool ok = true;
129 if (m_ForcedUnsupportedOperations.find(operationIdx) != m_ForcedUnsupportedOperations.end())
130 {
131 Fail("%s: Operation at index %i has been forced to be unsupported.", __func__, operationIdx);
132 ok = false;
133 }
134
135 if (ok)
136 {
137 try
138 {
arovir01b0717b52018-09-05 17:03:25 +0100139 ok = HalPolicy::ConvertOperation(operation, m_Model, m_Data);
telsoa015307bc12018-03-09 13:51:08 +0000140 }
Sadik Armagan44bcc022019-06-18 17:21:36 +0100141 catch (UnsupportedOperand<HalOperandType>& e)
telsoa015307bc12018-03-09 13:51:08 +0000142 {
143 Fail("%s: Operand type %s not supported in ArmnnDriver", __func__, toString(e.m_type).c_str());
144 ok = false;
145 }
146 catch (const armnn::InvalidArgumentException& e)
147 {
148 Fail("%s: Failed to convert operation in %s", __func__, e.what());
149 ok = false;
150 }
151 }
152
153 // Store whether this operation was successfully converted.
154 m_OperationSupported.emplace(operationIdx, ok);
155
156 // Any single operation failing will fail the entire conversion.
157 // We still need to continue and check the other ones.
158 if (!ok)
159 {
Finn Williams291a16b2020-08-19 22:54:00 +0100160 if (m_Data.m_DynamicInputsEncountered)
161 {
162 Fail("%s: The unsupported operation at index %i has dynamic inputs.", __func__, operationIdx);
163 UnsupportedDynamicOperation = true;
164 }
165
telsoa015307bc12018-03-09 13:51:08 +0000166 m_ConversionResult = ConversionResult::UnsupportedFeature;
167 }
Finn Williams291a16b2020-08-19 22:54:00 +0100168 m_Data.m_DynamicInputsEncountered = false;
telsoa015307bc12018-03-09 13:51:08 +0000169 }
Finn Williams291a16b2020-08-19 22:54:00 +0100170
171 // Due to the NNAPI partitioner not supporting partition boundaries of unknown size,
172 // any operations who's outputs connect to an unsupported operation with with dynamic inputs
173 // will cause a failure.
174
175 // The simplest solution to this problem is to not support any operations in a model containing
176 // an unsupported operation with with dynamic inputs.
177 if (UnsupportedDynamicOperation)
178 {
179 Fail("%s: Unsupported operation with dynamic inputs found. Retroactively setting all operations to unsupported",
180 __func__);
181 for (auto& operation : m_OperationSupported)
182 {
183 operation.second = false;
184 }
185 }
186
telsoa015307bc12018-03-09 13:51:08 +0000187 try
188 {
189 if (m_ConversionResult == ConversionResult::Success)
190 {
Kevin May42477c12020-03-26 13:34:14 +0000191 for (uint32_t i = 0; i < getMainModel(m_Model).outputIndexes.size(); i++)
telsoa015307bc12018-03-09 13:51:08 +0000192 {
193 // outputs in android nn are represented by operands
Kevin May42477c12020-03-26 13:34:14 +0000194 uint32_t outputIndex = getMainModel(m_Model).outputIndexes[i];
195 const HalOperand& operand = getMainModel(m_Model).operands[outputIndex];
telsoa015307bc12018-03-09 13:51:08 +0000196 const armnn::TensorInfo& tensor = GetTensorInfoForOperand(operand);
Sadik Armaganb3021432021-01-13 15:56:51 +0000197 const std::string layerName = "Output_" + std::to_string(i);
198 armnn::IConnectableLayer* layer = m_Data.m_Network->AddOutputLayer(i, layerName.c_str());
telsoa015307bc12018-03-09 13:51:08 +0000199
arovir01b0717b52018-09-05 17:03:25 +0100200 assert(m_Data.m_OutputSlotForOperand[outputIndex]);
201 m_Data.m_OutputSlotForOperand[outputIndex]->Connect(layer->GetInputSlot(0));
telsoa015307bc12018-03-09 13:51:08 +0000202 }
203 }
204 }
205 catch (const armnn::InvalidArgumentException& e)
206 {
207 Fail("%s: Failed to convert output operand to TensorShape: %s", __func__, e.what());
208 m_ConversionResult = ConversionResult::UnsupportedFeature;
209 }
210}
211
arovir01b0717b52018-09-05 17:03:25 +0100212template<typename HalPolicy>
213bool ModelToINetworkConverter<HalPolicy>::IsOperationSupported(uint32_t operationIndex) const
telsoa015307bc12018-03-09 13:51:08 +0000214{
215 std::map<uint32_t, bool>::const_iterator it = m_OperationSupported.find(operationIndex);
216 assert(it != m_OperationSupported.end());
217 return it->second;
218}
219
arovir01b0717b52018-09-05 17:03:25 +0100220///
221/// Class template specializations
222///
telsoa015307bc12018-03-09 13:51:08 +0000223
arovir01b0717b52018-09-05 17:03:25 +0100224template class ModelToINetworkConverter<hal_1_0::HalPolicy>;
225
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100226#ifdef ARMNN_ANDROID_NN_V1_1
arovir01b0717b52018-09-05 17:03:25 +0100227template class ModelToINetworkConverter<hal_1_1::HalPolicy>;
kevmay01bc5f7842018-08-30 12:34:39 +0100228#endif
229
Mike Kellyb5fdf382019-06-11 16:35:25 +0100230#ifdef ARMNN_ANDROID_NN_V1_2
231template class ModelToINetworkConverter<hal_1_1::HalPolicy>;
232template class ModelToINetworkConverter<hal_1_2::HalPolicy>;
233#endif
234
Kevin May42477c12020-03-26 13:34:14 +0000235#ifdef ARMNN_ANDROID_NN_V1_3
236template class ModelToINetworkConverter<hal_1_1::HalPolicy>;
237template class ModelToINetworkConverter<hal_1_2::HalPolicy>;
238template class ModelToINetworkConverter<hal_1_3::HalPolicy>;
239#endif
240
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100241} // armnn_driver