blob: 0b3b9191143d1d1e3d9523cd716c95cc44c473d1 [file] [log] [blame]
telsoa01ce3e84a2018-08-31 09:31:35 +01001//
2// Copyright © 2017 Arm Ltd. All rights reserved.
David Beck93e48982018-09-05 13:05:09 +01003// SPDX-License-Identifier: MIT
telsoa01ce3e84a2018-08-31 09:31:35 +01004//
5
Matteo Martincighe48bdff2018-09-03 13:50:50 +01006#define LOG_TAG "ArmnnDriver"
7
telsoa01ce3e84a2018-08-31 09:31:35 +01008#include "ArmnnDriverImpl.hpp"
telsoa01ce3e84a2018-08-31 09:31:35 +01009#include "ArmnnPreparedModel.hpp"
telsoa01ce3e84a2018-08-31 09:31:35 +010010
Kevin May42477c12020-03-26 13:34:14 +000011#if defined(ARMNN_ANDROID_NN_V1_2) || defined(ARMNN_ANDROID_NN_V1_3) // Using ::android::hardware::neuralnetworks::V1_2
Mike Kellyb5fdf382019-06-11 16:35:25 +010012#include "ArmnnPreparedModel_1_2.hpp"
telsoa01ce3e84a2018-08-31 09:31:35 +010013#endif
14
Kevin May42477c12020-03-26 13:34:14 +000015#ifdef ARMNN_ANDROID_NN_V1_3 // Using ::android::hardware::neuralnetworks::V1_2
16#include "ArmnnPreparedModel_1_3.hpp"
17#endif
18
19#include "Utils.hpp"
20
Mike Kellyb5fdf382019-06-11 16:35:25 +010021#include "ModelToINetworkConverter.hpp"
22#include "SystemPropertiesUtils.hpp"
Colm Donelan08d9a1c2020-09-09 17:56:55 +010023
Mike Kellyb5fdf382019-06-11 16:35:25 +010024#include <ValidateHal.h>
telsoa01ce3e84a2018-08-31 09:31:35 +010025#include <log/log.h>
26
27using namespace std;
28using namespace android;
29using namespace android::nn;
30using namespace android::hardware;
31
32namespace
33{
34
Matthew Bentham912b3622019-05-03 15:49:14 +010035void NotifyCallbackAndCheck(const sp<V1_0::IPreparedModelCallback>& callback,
Kevin Mayec1e5b82020-02-26 17:00:39 +000036 V1_0::ErrorStatus errorStatus,
Matthew Bentham912b3622019-05-03 15:49:14 +010037 const sp<V1_0::IPreparedModel>& preparedModelPtr)
telsoa01ce3e84a2018-08-31 09:31:35 +010038{
39 Return<void> returned = callback->notify(errorStatus, preparedModelPtr);
40 // This check is required, if the callback fails and it isn't checked it will bring down the service
41 if (!returned.isOk())
42 {
Matteo Martincighe48bdff2018-09-03 13:50:50 +010043 ALOGE("ArmnnDriverImpl::prepareModel: hidl callback failed to return properly: %s ",
Mike Kellyb5fdf382019-06-11 16:35:25 +010044 returned.description().c_str());
telsoa01ce3e84a2018-08-31 09:31:35 +010045 }
46}
47
Kevin Mayec1e5b82020-02-26 17:00:39 +000048Return<V1_0::ErrorStatus> FailPrepareModel(V1_0::ErrorStatus error,
49 const string& message,
50 const sp<V1_0::IPreparedModelCallback>& callback)
telsoa01ce3e84a2018-08-31 09:31:35 +010051{
Matteo Martincighe48bdff2018-09-03 13:50:50 +010052 ALOGW("ArmnnDriverImpl::prepareModel: %s", message.c_str());
telsoa01ce3e84a2018-08-31 09:31:35 +010053 NotifyCallbackAndCheck(callback, error, nullptr);
54 return error;
55}
56
57} // namespace
58
59namespace armnn_driver
60{
telsoa01ce3e84a2018-08-31 09:31:35 +010061
arovir01b0717b52018-09-05 17:03:25 +010062template<typename HalPolicy>
Kevin Mayec1e5b82020-02-26 17:00:39 +000063Return<V1_0::ErrorStatus> ArmnnDriverImpl<HalPolicy>::prepareModel(
telsoa01ce3e84a2018-08-31 09:31:35 +010064 const armnn::IRuntimePtr& runtime,
65 const armnn::IGpuAccTunedParametersPtr& clTunedParameters,
66 const DriverOptions& options,
Matteo Martincighe48bdff2018-09-03 13:50:50 +010067 const HalModel& model,
Matthew Bentham912b3622019-05-03 15:49:14 +010068 const sp<V1_0::IPreparedModelCallback>& cb,
Matteo Martincighe48bdff2018-09-03 13:50:50 +010069 bool float32ToFloat16)
telsoa01ce3e84a2018-08-31 09:31:35 +010070{
Matteo Martincighe48bdff2018-09-03 13:50:50 +010071 ALOGV("ArmnnDriverImpl::prepareModel()");
telsoa01ce3e84a2018-08-31 09:31:35 +010072
73 if (cb.get() == nullptr)
74 {
Matteo Martincighe48bdff2018-09-03 13:50:50 +010075 ALOGW("ArmnnDriverImpl::prepareModel: Invalid callback passed to prepareModel");
Kevin Mayec1e5b82020-02-26 17:00:39 +000076 return V1_0::ErrorStatus::INVALID_ARGUMENT;
telsoa01ce3e84a2018-08-31 09:31:35 +010077 }
78
79 if (!runtime)
80 {
Kevin Mayec1e5b82020-02-26 17:00:39 +000081 return FailPrepareModel(V1_0::ErrorStatus::DEVICE_UNAVAILABLE, "Device unavailable", cb);
telsoa01ce3e84a2018-08-31 09:31:35 +010082 }
83
84 if (!android::nn::validateModel(model))
85 {
Kevin Mayec1e5b82020-02-26 17:00:39 +000086 return FailPrepareModel(V1_0::ErrorStatus::INVALID_ARGUMENT, "Invalid model passed as input", cb);
telsoa01ce3e84a2018-08-31 09:31:35 +010087 }
88
89 // Deliberately ignore any unsupported operations requested by the options -
90 // at this point we're being asked to prepare a model that we've already declared support for
91 // and the operation indices may be different to those in getSupportedOperations anyway.
92 set<unsigned int> unsupportedOperations;
Nattapat Chaimanowongd5fd9762019-04-04 13:33:10 +010093 ModelToINetworkConverter<HalPolicy> modelConverter(options.GetBackends(),
94 model,
95 unsupportedOperations);
telsoa01ce3e84a2018-08-31 09:31:35 +010096
97 if (modelConverter.GetConversionResult() != ConversionResult::Success)
98 {
Kevin Mayec1e5b82020-02-26 17:00:39 +000099 FailPrepareModel(V1_0::ErrorStatus::GENERAL_FAILURE, "ModelToINetworkConverter failed", cb);
100 return V1_0::ErrorStatus::NONE;
telsoa01ce3e84a2018-08-31 09:31:35 +0100101 }
102
Sadik Armaganb3021432021-01-13 15:56:51 +0000103 // Serialize the network graph to a .armnn file if an output directory
104 // has been specified in the drivers' arguments.
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100105 std::vector<uint8_t> dataCacheData;
Sadik Armaganb3021432021-01-13 15:56:51 +0000106 auto serializedNetworkFileName =
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100107 SerializeNetwork(*modelConverter.GetINetwork(),
108 options.GetRequestInputsAndOutputsDumpDir(),
109 dataCacheData,
110 false);
Sadik Armaganb3021432021-01-13 15:56:51 +0000111
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100112 // Optimize the network
telsoa01ce3e84a2018-08-31 09:31:35 +0100113 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
114 armnn::OptimizerOptions OptOptions;
115 OptOptions.m_ReduceFp32ToFp16 = float32ToFloat16;
116
Mike Kelly7ed56dd2020-09-30 20:22:56 +0100117 armnn::BackendOptions gpuAcc("GpuAcc",
118 {
Sadik Armaganf36e10b2021-01-11 16:34:01 +0000119 { "FastMathEnabled", options.IsFastMathEnabled() },
120 { "SaveCachedNetwork", options.SaveCachedNetwork() },
Finn Williamsf5ca16c2021-02-12 14:26:23 +0000121 { "CachedNetworkFilePath", options.GetCachedNetworkFilePath() },
122 { "MLGOTuningFilePath", options.GetClMLGOTunedParametersFile() }
123
Mike Kelly7ed56dd2020-09-30 20:22:56 +0100124 });
Finn Williamsf5ca16c2021-02-12 14:26:23 +0000125
Mike Kelly7ed56dd2020-09-30 20:22:56 +0100126 armnn::BackendOptions cpuAcc("CpuAcc",
127 {
Matthew Sloyancd639c92021-02-11 16:57:38 +0000128 { "FastMathEnabled", options.IsFastMathEnabled() },
129 { "NumberOfThreads", options.GetNumberOfThreads() }
Mike Kelly7ed56dd2020-09-30 20:22:56 +0100130 });
131 OptOptions.m_ModelOptions.push_back(gpuAcc);
132 OptOptions.m_ModelOptions.push_back(cpuAcc);
133
jimfly0107dedda2018-10-09 12:29:41 +0100134 std::vector<std::string> errMessages;
telsoa01ce3e84a2018-08-31 09:31:35 +0100135 try
136 {
137 optNet = armnn::Optimize(*modelConverter.GetINetwork(),
Nattapat Chaimanowongd5fd9762019-04-04 13:33:10 +0100138 options.GetBackends(),
telsoa01ce3e84a2018-08-31 09:31:35 +0100139 runtime->GetDeviceSpec(),
jimfly0107dedda2018-10-09 12:29:41 +0100140 OptOptions,
141 errMessages);
telsoa01ce3e84a2018-08-31 09:31:35 +0100142 }
Derek Lambertib9cb8442019-11-28 13:34:48 +0000143 catch (std::exception &e)
telsoa01ce3e84a2018-08-31 09:31:35 +0100144 {
145 stringstream message;
Derek Lambertib9cb8442019-11-28 13:34:48 +0000146 message << "Exception (" << e.what() << ") caught from optimize.";
Kevin Mayec1e5b82020-02-26 17:00:39 +0000147 FailPrepareModel(V1_0::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
148 return V1_0::ErrorStatus::NONE;
telsoa01ce3e84a2018-08-31 09:31:35 +0100149 }
150
151 // Check that the optimized network is valid.
152 if (!optNet)
153 {
jimfly0107dedda2018-10-09 12:29:41 +0100154 stringstream message;
Matteo Martincigh8d50f8f2018-10-25 15:39:33 +0100155 message << "Invalid optimized network";
156 for (const string& msg : errMessages)
157 {
jimfly0107dedda2018-10-09 12:29:41 +0100158 message << "\n" << msg;
159 }
Kevin Mayec1e5b82020-02-26 17:00:39 +0000160 FailPrepareModel(V1_0::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
161 return V1_0::ErrorStatus::NONE;
telsoa01ce3e84a2018-08-31 09:31:35 +0100162 }
163
164 // Export the optimized network graph to a dot file if an output dump directory
165 // has been specified in the drivers' arguments.
Jim Flynn829ad302019-12-13 14:43:24 +0000166 std::string dotGraphFileName = ExportNetworkGraphToDotFile(*optNet, options.GetRequestInputsAndOutputsDumpDir());
telsoa01ce3e84a2018-08-31 09:31:35 +0100167
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100168 // Load it into the runtime.
telsoa01ce3e84a2018-08-31 09:31:35 +0100169 armnn::NetworkId netId = 0;
Finn Williamsd8fb5402021-05-19 20:52:00 +0100170 std::string msg;
171 armnn::INetworkProperties networkProperties(options.isAsyncModelExecutionEnabled(),
172 armnn::MemorySource::Undefined,
Finn Williamsca3a3e02021-06-11 15:04:02 +0100173 armnn::MemorySource::Undefined);
Finn Williamsd8fb5402021-05-19 20:52:00 +0100174
telsoa01ce3e84a2018-08-31 09:31:35 +0100175 try
176 {
Finn Williamsd8fb5402021-05-19 20:52:00 +0100177 if (runtime->LoadNetwork(netId, move(optNet), msg, networkProperties) != armnn::Status::Success)
telsoa01ce3e84a2018-08-31 09:31:35 +0100178 {
Kevin Mayec1e5b82020-02-26 17:00:39 +0000179 return FailPrepareModel(V1_0::ErrorStatus::GENERAL_FAILURE, "Network could not be loaded", cb);
telsoa01ce3e84a2018-08-31 09:31:35 +0100180 }
181 }
Derek Lambertib9cb8442019-11-28 13:34:48 +0000182 catch (std::exception& e)
telsoa01ce3e84a2018-08-31 09:31:35 +0100183 {
184 stringstream message;
Derek Lambertib9cb8442019-11-28 13:34:48 +0000185 message << "Exception (" << e.what()<< ") caught from LoadNetwork.";
Kevin Mayec1e5b82020-02-26 17:00:39 +0000186 FailPrepareModel(V1_0::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
187 return V1_0::ErrorStatus::NONE;
telsoa01ce3e84a2018-08-31 09:31:35 +0100188 }
189
Sadik Armaganb3021432021-01-13 15:56:51 +0000190 // Now that we have a networkId for the graph rename the exported files to use it
191 // so that we can associate the graph file and the input/output tensor exported files
192 RenameExportedFiles(serializedNetworkFileName,
193 dotGraphFileName,
194 options.GetRequestInputsAndOutputsDumpDir(),
195 netId);
Jim Flynn829ad302019-12-13 14:43:24 +0000196
Kevin Mayd5e94652019-11-07 14:02:14 +0000197 sp<ArmnnPreparedModel<HalPolicy>> preparedModel(
Mike Kellyb5fdf382019-06-11 16:35:25 +0100198 new ArmnnPreparedModel<HalPolicy>(
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100199 netId,
200 runtime.get(),
201 model,
202 options.GetRequestInputsAndOutputsDumpDir(),
Finn Williamsd8fb5402021-05-19 20:52:00 +0100203 options.IsGpuProfilingEnabled(),
Finn Williamsca3a3e02021-06-11 15:04:02 +0100204 options.isAsyncModelExecutionEnabled(),
205 options.getNoOfArmnnThreads()));
telsoa01ce3e84a2018-08-31 09:31:35 +0100206
207 // Run a single 'dummy' inference of the model. This means that CL kernels will get compiled (and tuned if
208 // this is enabled) before the first 'real' inference which removes the overhead of the first inference.
Matthew Bentham16196e22019-04-01 17:17:58 +0100209 if (!preparedModel->ExecuteWithDummyInputs())
210 {
Kevin Mayec1e5b82020-02-26 17:00:39 +0000211 return FailPrepareModel(V1_0::ErrorStatus::GENERAL_FAILURE, "Network could not be executed", cb);
Matthew Bentham16196e22019-04-01 17:17:58 +0100212 }
telsoa01ce3e84a2018-08-31 09:31:35 +0100213
214 if (clTunedParameters &&
215 options.GetClTunedParametersMode() == armnn::IGpuAccTunedParameters::Mode::UpdateTunedParameters)
216 {
217 // Now that we've done one inference the CL kernel parameters will have been tuned, so save the updated file.
218 try
219 {
220 clTunedParameters->Save(options.GetClTunedParametersFile().c_str());
221 }
Derek Lambertib9cb8442019-11-28 13:34:48 +0000222 catch (std::exception& error)
telsoa01ce3e84a2018-08-31 09:31:35 +0100223 {
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100224 ALOGE("ArmnnDriverImpl::prepareModel: Failed to save CL tuned parameters file '%s': %s",
Matteo Martincigh8d50f8f2018-10-25 15:39:33 +0100225 options.GetClTunedParametersFile().c_str(), error.what());
telsoa01ce3e84a2018-08-31 09:31:35 +0100226 }
227 }
228
Kevin Mayec1e5b82020-02-26 17:00:39 +0000229 NotifyCallbackAndCheck(cb, V1_0::ErrorStatus::NONE, preparedModel);
telsoa01ce3e84a2018-08-31 09:31:35 +0100230
Kevin Mayec1e5b82020-02-26 17:00:39 +0000231 return V1_0::ErrorStatus::NONE;
telsoa01ce3e84a2018-08-31 09:31:35 +0100232}
233
arovir01b0717b52018-09-05 17:03:25 +0100234template<typename HalPolicy>
Mike Kellyb5fdf382019-06-11 16:35:25 +0100235Return<void> ArmnnDriverImpl<HalPolicy>::getSupportedOperations(const armnn::IRuntimePtr& runtime,
236 const DriverOptions& options,
237 const HalModel& model,
238 HalGetSupportedOperations_cb cb)
239{
Jim Flynn829ad302019-12-13 14:43:24 +0000240 std::stringstream ss;
241 ss << "ArmnnDriverImpl::getSupportedOperations()";
242 std::string fileName;
243 std::string timestamp;
244 if (!options.GetRequestInputsAndOutputsDumpDir().empty())
245 {
Colm Donelan08d9a1c2020-09-09 17:56:55 +0100246 ss << " : "
247 << options.GetRequestInputsAndOutputsDumpDir()
248 << "/"
249 << GetFileTimestamp()
250 << "_getSupportedOperations.txt";
Jim Flynn829ad302019-12-13 14:43:24 +0000251 }
252 ALOGV(ss.str().c_str());
253
254 if (!options.GetRequestInputsAndOutputsDumpDir().empty())
255 {
256 //dump the marker file
257 std::ofstream fileStream;
258 fileStream.open(fileName, std::ofstream::out | std::ofstream::trunc);
259 if (fileStream.good())
260 {
261 fileStream << timestamp << std::endl;
262 }
263 fileStream.close();
264 }
Mike Kellyb5fdf382019-06-11 16:35:25 +0100265
266 vector<bool> result;
267
268 if (!runtime)
269 {
Kevin May42477c12020-03-26 13:34:14 +0000270 cb(HalErrorStatus::DEVICE_UNAVAILABLE, result);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100271 return Void();
272 }
273
274 // Run general model validation, if this doesn't pass we shouldn't analyse the model anyway.
275 if (!android::nn::validateModel(model))
276 {
Kevin May42477c12020-03-26 13:34:14 +0000277 cb(HalErrorStatus::INVALID_ARGUMENT, result);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100278 return Void();
279 }
280
281 // Attempt to convert the model to an ArmNN input network (INetwork).
282 ModelToINetworkConverter<HalPolicy> modelConverter(options.GetBackends(),
283 model,
284 options.GetForcedUnsupportedOperations());
285
286 if (modelConverter.GetConversionResult() != ConversionResult::Success
287 && modelConverter.GetConversionResult() != ConversionResult::UnsupportedFeature)
288 {
Kevin May42477c12020-03-26 13:34:14 +0000289 cb(HalErrorStatus::GENERAL_FAILURE, result);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100290 return Void();
291 }
292
293 // Check each operation if it was converted successfully and copy the flags
294 // into the result (vector<bool>) that we need to return to Android.
Kevin May42477c12020-03-26 13:34:14 +0000295 result.reserve(getMainModel(model).operations.size());
296 for (uint32_t operationIdx = 0;
297 operationIdx < getMainModel(model).operations.size();
298 ++operationIdx)
Mike Kellyb5fdf382019-06-11 16:35:25 +0100299 {
300 bool operationSupported = modelConverter.IsOperationSupported(operationIdx);
301 result.push_back(operationSupported);
302 }
303
Kevin May42477c12020-03-26 13:34:14 +0000304 cb(HalErrorStatus::NONE, result);
Mike Kellyb5fdf382019-06-11 16:35:25 +0100305 return Void();
306}
307
308template<typename HalPolicy>
Sadik Armagan188675f2021-02-12 17:16:42 +0000309Return<V1_0::DeviceStatus> ArmnnDriverImpl<HalPolicy>::getStatus()
telsoa01ce3e84a2018-08-31 09:31:35 +0100310{
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100311 ALOGV("ArmnnDriver::getStatus()");
telsoa01ce3e84a2018-08-31 09:31:35 +0100312
Sadik Armagan188675f2021-02-12 17:16:42 +0000313 return V1_0::DeviceStatus::AVAILABLE;
telsoa01ce3e84a2018-08-31 09:31:35 +0100314}
315
arovir01b0717b52018-09-05 17:03:25 +0100316///
317/// Class template specializations
318///
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100319
arovir01b0717b52018-09-05 17:03:25 +0100320template class ArmnnDriverImpl<hal_1_0::HalPolicy>;
321
Matteo Martincigh8b287c22018-09-07 09:25:10 +0100322#ifdef ARMNN_ANDROID_NN_V1_1
arovir01b0717b52018-09-05 17:03:25 +0100323template class ArmnnDriverImpl<hal_1_1::HalPolicy>;
Matteo Martincighe48bdff2018-09-03 13:50:50 +0100324#endif
325
Mike Kellyb5fdf382019-06-11 16:35:25 +0100326#ifdef ARMNN_ANDROID_NN_V1_2
327template class ArmnnDriverImpl<hal_1_1::HalPolicy>;
328template class ArmnnDriverImpl<hal_1_2::HalPolicy>;
329#endif
330
Kevin May42477c12020-03-26 13:34:14 +0000331#ifdef ARMNN_ANDROID_NN_V1_3
332template class ArmnnDriverImpl<hal_1_1::HalPolicy>;
333template class ArmnnDriverImpl<hal_1_2::HalPolicy>;
334template class ArmnnDriverImpl<hal_1_3::HalPolicy>;
335#endif
336
Matteo Martincigh8d50f8f2018-10-25 15:39:33 +0100337} // namespace armnn_driver