blob: 474e1c1ff1d4c8e56343700b26d0ccd5fddced83 [file] [log] [blame]
Kevin May42477c12020-03-26 13:34:14 +00001//
2// Copyright © 2020 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "ArmnnDriverImpl.hpp"
7#include "../ArmnnPreparedModel_1_3.hpp"
8#include "../ModelToINetworkConverter.hpp"
9#include "../SystemPropertiesUtils.hpp"
10
Sadik Armagan0a2dfab2021-10-06 16:41:44 +010011#include <armnnDeserializer/IDeserializer.hpp>
12
Kevin May42477c12020-03-26 13:34:14 +000013#include <log/log.h>
14
Sadik Armagan0a2dfab2021-10-06 16:41:44 +010015#include <sys/stat.h>
16
Kevin May42477c12020-03-26 13:34:14 +000017namespace
18{
Kevin May42477c12020-03-26 13:34:14 +000019const char *g_RelaxedFloat32toFloat16PerformanceExecTime = "ArmNN.relaxedFloat32toFloat16Performance.execTime";
20const char *g_RelaxedFloat32toFloat16PerformancePowerUsage = "ArmNN.relaxedFloat32toFloat16Performance.powerUsage";
21
Kevin May2eaa1192020-04-15 16:50:57 +010022const char *g_ifPerformanceExecTime = "ArmNN.ifPerformance.execTime";
23const char *g_ifPerformancePowerUsage = "ArmNN.ifPerformance.powerUsage";
24
25const char *g_whilePerformanceExecTime = "ArmNN.whilePerformance.execTime";
26const char *g_whilePerformancePowerUsage = "ArmNN.whilePerformance.powerUsage";
27
Kevin May42477c12020-03-26 13:34:14 +000028const char *g_OperandTypeTensorFloat32PerformanceExecTime = "Armnn.operandTypeTensorFloat32Performance.execTime";
29const char *g_OperandTypeTensorFloat32PerformancePowerUsage = "Armnn.operandTypeTensorFloat32Performance.powerUsage";
30
31const char *g_OperandTypeFloat32PerformanceExecTime = "Armnn.operandTypeFloat32Performance.execTime";
32const char *g_OperandTypeFloat32PerformancePowerUsage = "Armnn.operandTypeFloat32Performance.powerUsage";
33
34const char *g_OperandTypeTensorFloat16PerformanceExecTime = "Armnn.operandTypeTensorFloat16Performance.execTime";
35const char *g_OperandTypeTensorFloat16PerformancePowerUsage = "Armnn.operandTypeTensorFloat16Performance.powerUsage";
36
37const char *g_OperandTypeFloat16PerformanceExecTime = "Armnn.operandTypeFloat16Performance.execTime";
38const char *g_OperandTypeFloat16PerformancePowerUsage = "Armnn.operandTypeFloat16Performance.powerUsage";
39
40const char *g_OperandTypeTensorQuant8AsymmPerformanceExecTime =
41 "Armnn.operandTypeTensorQuant8AsymmPerformance.execTime";
42const char *g_OperandTypeTensorQuant8AsymmPerformancePowerUsage =
43 "Armnn.operandTypeTensorQuant8AsymmPerformance.powerUsage";
44
45const char *g_OperandTypeTensorQuant8AsymmSignedPerformanceExecTime =
46 "Armnn.operandTypeTensorQuant8AsymmSignedPerformance.execTime";
47const char *g_OperandTypeTensorQuant8AsymmSignedPerformancePowerUsage =
48 "Armnn.operandTypeTensorQuant8AsymmSignedPerformance.powerUsage";
49
50const char *g_OperandTypeTensorQuant16SymmPerformanceExecTime =
51 "Armnn.operandTypeTensorQuant16SymmPerformance.execTime";
52const char *g_OperandTypeTensorQuant16SymmPerformancePowerUsage =
53 "Armnn.operandTypeTensorQuant16SymmPerformance.powerUsage";
54
55const char *g_OperandTypeTensorQuant8SymmPerformanceExecTime =
56 "Armnn.operandTypeTensorQuant8SymmPerformance.execTime";
57const char *g_OperandTypeTensorQuant8SymmPerformancePowerUsage =
58 "Armnn.operandTypeTensorQuant8SymmPerformance.powerUsage";
59
60const char *g_OperandTypeTensorQuant8SymmPerChannelPerformanceExecTime =
61 "Armnn.operandTypeTensorQuant8SymmPerChannelPerformance.execTime";
62const char *g_OperandTypeTensorQuant8SymmPerChannelPerformancePowerUsage =
63 "Armnn.operandTypeTensorQuant8SymmPerChannelPerformance.powerUsage";
64
65
66const char *g_OperandTypeTensorInt32PerformanceExecTime = "Armnn.operandTypeTensorInt32Performance.execTime";
67const char *g_OperandTypeTensorInt32PerformancePowerUsage = "Armnn.operandTypeTensorInt32Performance.powerUsage";
68
69const char *g_OperandTypeInt32PerformanceExecTime = "Armnn.operandTypeInt32Performance.execTime";
70const char *g_OperandTypeInt32PerformancePowerUsage = "Armnn.operandTypeInt32Performance.powerUsage";
71
72
Sadik Armagan188675f2021-02-12 17:16:42 +000073void NotifyCallbackAndCheck(const android::sp<V1_3::IPreparedModelCallback>& callback,
Kevin May42477c12020-03-26 13:34:14 +000074 V1_3::ErrorStatus errorStatus,
Sadik Armagan188675f2021-02-12 17:16:42 +000075 const android::sp<V1_3::IPreparedModel>& preparedModelPtr)
Kevin May42477c12020-03-26 13:34:14 +000076{
77 Return<void> returned = callback->notify_1_3(errorStatus, preparedModelPtr);
78 // This check is required, if the callback fails and it isn't checked it will bring down the service
79 if (!returned.isOk())
80 {
81 ALOGE("ArmnnDriverImpl::prepareModel: hidl callback failed to return properly: %s ",
82 returned.description().c_str());
83 }
84}
85
86Return<V1_3::ErrorStatus> FailPrepareModel(V1_3::ErrorStatus error,
87 const std::string& message,
Sadik Armagan188675f2021-02-12 17:16:42 +000088 const android::sp<V1_3::IPreparedModelCallback>& callback)
Kevin May42477c12020-03-26 13:34:14 +000089{
90 ALOGW("ArmnnDriverImpl::prepareModel: %s", message.c_str());
91 NotifyCallbackAndCheck(callback, error, nullptr);
92 return error;
93}
94
95} // anonymous namespace
96
97namespace armnn_driver
98{
99namespace hal_1_3
100{
101
102Return<V1_3::ErrorStatus> ArmnnDriverImpl::prepareArmnnModel_1_3(
103 const armnn::IRuntimePtr& runtime,
104 const armnn::IGpuAccTunedParametersPtr& clTunedParameters,
105 const DriverOptions& options,
106 const V1_3::Model& model,
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100107 const android::hardware::hidl_vec<android::hardware::hidl_handle>& modelCacheHandle,
108 const android::hardware::hidl_vec<android::hardware::hidl_handle>& dataCacheHandle,
109 const HidlToken& token,
Sadik Armagan188675f2021-02-12 17:16:42 +0000110 const android::sp<V1_3::IPreparedModelCallback>& cb,
Narumol Prangnawaratcad4e912020-06-02 12:07:43 +0100111 bool float32ToFloat16,
112 V1_3::Priority priority)
Kevin May42477c12020-03-26 13:34:14 +0000113{
114 ALOGV("ArmnnDriverImpl::prepareArmnnModel_1_3()");
115
116 if (cb.get() == nullptr)
117 {
118 ALOGW("ArmnnDriverImpl::prepareModel: Invalid callback passed to prepareModel");
119 return V1_3::ErrorStatus::INVALID_ARGUMENT;
120 }
121
122 if (!runtime)
123 {
124 return FailPrepareModel(V1_3::ErrorStatus::DEVICE_UNAVAILABLE, "Device unavailable", cb);
125 }
126
127 if (!android::nn::validateModel(model))
128 {
129 return FailPrepareModel(V1_3::ErrorStatus::INVALID_ARGUMENT, "Invalid model passed as input", cb);
130 }
131
132 // Deliberately ignore any unsupported operations requested by the options -
133 // at this point we're being asked to prepare a model that we've already declared support for
134 // and the operation indices may be different to those in getSupportedOperations anyway.
135 std::set<unsigned int> unsupportedOperations;
136 ModelToINetworkConverter<HalPolicy> modelConverter(options.GetBackends(),
137 model,
138 unsupportedOperations);
139
140 if (modelConverter.GetConversionResult() != ConversionResult::Success)
141 {
142 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, "ModelToINetworkConverter failed", cb);
143 return V1_3::ErrorStatus::NONE;
144 }
145
Sadik Armaganb3021432021-01-13 15:56:51 +0000146 // Serialize the network graph to a .armnn file if an output directory
147 // has been specified in the drivers' arguments.
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100148 std::vector<uint8_t> dataCacheData;
149 bool serializeToFile = dataCacheHandle.size() < 1 ? false : true;
Sadik Armaganb3021432021-01-13 15:56:51 +0000150 auto serializedNetworkFileName =
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100151 SerializeNetwork(*modelConverter.GetINetwork(),
152 options.GetRequestInputsAndOutputsDumpDir(),
153 dataCacheData,
154 serializeToFile);
Sadik Armaganb3021432021-01-13 15:56:51 +0000155
Kevin May42477c12020-03-26 13:34:14 +0000156 // Optimize the network
157 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
158 armnn::OptimizerOptions OptOptions;
159 OptOptions.m_ReduceFp32ToFp16 = float32ToFloat16;
Kevin Maydaf7dd02021-10-22 11:57:30 +0100160 OptOptions.m_ProfilingEnabled = options.IsGpuProfilingEnabled();
Kevin May42477c12020-03-26 13:34:14 +0000161
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100162 int cachedFd = -1;
163 bool saveCachedNetwork = options.SaveCachedNetwork();
164
165 unsigned int numberOfCachedModelFiles = 0;
166 if (modelCacheHandle.size() > 0)
167 {
168 unsigned int index = 0;
169 for (auto& backend : options.GetBackends())
170 {
171 // modelCacheHandle size should be equal to numberOfCachedModelFiles
172 // modelCacheHandle vector should be in same order as backends
173 auto numberOfCacheFiles = GetNumberOfCacheFiles(backend);
174 if (numberOfCacheFiles > 0)
175 {
176 numberOfCachedModelFiles += numberOfCacheFiles;
177 if (modelCacheHandle[index]->numFds == 1)
178 {
179 // For GpuAcc numberOfCachedFiles is 1
180 if (backend == armnn::Compute::GpuAcc)
181 {
182 cachedFd = modelCacheHandle[index]->data[0];
183 saveCachedNetwork = true;
184 }
185 }
186 index += numberOfCachedModelFiles;
187 }
188 }
189 }
190
Mike Kelly7ed56dd2020-09-30 20:22:56 +0100191 armnn::BackendOptions gpuAcc("GpuAcc",
192 {
Sadik Armaganf36e10b2021-01-11 16:34:01 +0000193 { "FastMathEnabled", options.IsFastMathEnabled() },
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100194 { "SaveCachedNetwork", saveCachedNetwork },
Finn Williamsf5ca16c2021-02-12 14:26:23 +0000195 { "CachedNetworkFilePath", options.GetCachedNetworkFilePath() },
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100196 { "MLGOTuningFilePath", options.GetClMLGOTunedParametersFile() },
197 { "CachedFileDescriptor", cachedFd }
Mike Kelly7ed56dd2020-09-30 20:22:56 +0100198 });
Finn Williamsf5ca16c2021-02-12 14:26:23 +0000199
Mike Kelly7ed56dd2020-09-30 20:22:56 +0100200 armnn::BackendOptions cpuAcc("CpuAcc",
201 {
Matthew Sloyancd639c92021-02-11 16:57:38 +0000202 { "FastMathEnabled", options.IsFastMathEnabled() },
203 { "NumberOfThreads", options.GetNumberOfThreads() }
Mike Kelly7ed56dd2020-09-30 20:22:56 +0100204 });
205 OptOptions.m_ModelOptions.push_back(gpuAcc);
206 OptOptions.m_ModelOptions.push_back(cpuAcc);
207
Kevin May42477c12020-03-26 13:34:14 +0000208 std::vector<std::string> errMessages;
209 try
210 {
211 optNet = armnn::Optimize(*modelConverter.GetINetwork(),
212 options.GetBackends(),
213 runtime->GetDeviceSpec(),
214 OptOptions,
215 errMessages);
216 }
217 catch (std::exception& e)
218 {
219 std::stringstream message;
220 message << "Exception (" << e.what() << ") caught from optimize.";
221 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
222 return V1_3::ErrorStatus::NONE;
223 }
224
225 // Check that the optimized network is valid.
226 if (!optNet)
227 {
228 std::stringstream message;
229 message << "Invalid optimized network";
230 for (const std::string& msg : errMessages)
231 {
232 message << "\n" << msg;
233 }
234 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
235 return V1_3::ErrorStatus::NONE;
236 }
237
238 // Export the optimized network graph to a dot file if an output dump directory
239 // has been specified in the drivers' arguments.
240 std::string dotGraphFileName = ExportNetworkGraphToDotFile(*optNet,
241 options.GetRequestInputsAndOutputsDumpDir());
242
243 // Load it into the runtime.
244 armnn::NetworkId netId = 0;
Finn Williamsd8fb5402021-05-19 20:52:00 +0100245 std::string msg;
246 armnn::INetworkProperties networkProperties(options.isAsyncModelExecutionEnabled(),
247 MemorySource::Undefined,
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100248 MemorySource::Undefined,
249 options.IsGpuProfilingEnabled());
250
251 auto numInputs = getMainModel(model).inputIndexes.size();
252 auto numOutputs = getMainModel(model).outputIndexes.size();
Kevin May42477c12020-03-26 13:34:14 +0000253 try
254 {
Finn Williamsd8fb5402021-05-19 20:52:00 +0100255 if (runtime->LoadNetwork(netId, move(optNet), msg, networkProperties) != armnn::Status::Success)
Kevin May42477c12020-03-26 13:34:14 +0000256 {
257 return FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, "Network could not be loaded", cb);
258 }
259 }
260 catch (std::exception& e)
261 {
262 std::stringstream message;
263 message << "Exception (" << e.what()<< ") caught from LoadNetwork.";
264 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
265 return V1_3::ErrorStatus::NONE;
266 }
267
Sadik Armaganb3021432021-01-13 15:56:51 +0000268 // Now that we have a networkId for the graph rename the exported files to use it
269 // so that we can associate the graph file and the input/output tensor exported files
270 RenameExportedFiles(serializedNetworkFileName,
271 dotGraphFileName,
272 options.GetRequestInputsAndOutputsDumpDir(),
273 netId);
Kevin May42477c12020-03-26 13:34:14 +0000274
275 std::unique_ptr<ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>> preparedModel(
276 new ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>(
277 netId,
278 runtime.get(),
279 model,
280 options.GetRequestInputsAndOutputsDumpDir(),
Narumol Prangnawaratcad4e912020-06-02 12:07:43 +0100281 options.IsGpuProfilingEnabled(),
Finn Williamsd8fb5402021-05-19 20:52:00 +0100282 priority,
Finn Williamsca3a3e02021-06-11 15:04:02 +0100283 options.isAsyncModelExecutionEnabled(),
Narumol Prangnawaratd1a947f2022-02-07 13:12:24 +0000284 options.getNoOfArmnnThreads(),
285 options.isImportEnabled(),
286 options.isExportEnabled()));
Kevin May42477c12020-03-26 13:34:14 +0000287
288 // Run a single 'dummy' inference of the model. This means that CL kernels will get compiled (and tuned if
289 // this is enabled) before the first 'real' inference which removes the overhead of the first inference.
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100290 // Only run this if the GpuAcc backend has been added to options
291 if (std::find(options.GetBackends().begin(),
292 options.GetBackends().end(),
293 armnn::Compute::GpuAcc) != options.GetBackends().end())
Kevin May42477c12020-03-26 13:34:14 +0000294 {
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100295 if (!preparedModel->ExecuteWithDummyInputs(numInputs, numOutputs))
296 {
297 return FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, "Network could not be executed", cb);
298 }
299
300 if (clTunedParameters &&
301 options.GetClTunedParametersMode() == armnn::IGpuAccTunedParameters::Mode::UpdateTunedParameters)
302 {
303 // Now that we've done one inference the CL kernel parameters will have been tuned,
304 // so save the updated file.
305 try
306 {
307 clTunedParameters->Save(options.GetClTunedParametersFile().c_str());
308 }
309 catch (std::exception& error)
310 {
311 ALOGE("ArmnnDriverImpl::prepareModel: Failed to save CL tuned parameters file '%s': %s",
312 options.GetClTunedParametersFile().c_str(), error.what());
313 }
314 }
315 }
316 size_t hashValue = 0;
317 // Cache the model
318 if (dataCacheHandle.size() > 0)
319 {
320 // Cache the Arm NN model
321 if (dataCacheHandle.size() != 1)
322 {
323 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
324 return V1_3::ErrorStatus::NONE;
325 }
326
327 if (dataCacheHandle[0]->numFds != 1)
328 {
329 ALOGW("ArmnnDriverImpl::prepareArmnnModel_1_3: Cannot cache the data, numFds != 1.");
330 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
331 return V1_3::ErrorStatus::NONE;
332 }
Sadik Armaganee6818b2021-11-05 14:41:52 +0000333
334 if (dataCacheHandle[0]->data[0] < 0)
335 {
336 ALOGW("ArmnnDriverImpl::prepareArmnnModel_1_3: Cannot cache the data, fd < 0");
337 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
338 return V1_3::ErrorStatus::NONE;
339 }
340
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100341 int dataCacheFileAccessMode = fcntl(dataCacheHandle[0]->data[0], F_GETFL) & O_ACCMODE;
342 if (dataCacheFileAccessMode != O_RDWR)
343 {
344 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3(): Invalid Access Mode.");
345 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
346 return V1_3::ErrorStatus::NONE;
347 }
348
349 write(dataCacheHandle[0]->data[0], dataCacheData.data(), dataCacheData.size());
350 hashValue = CacheDataHandlerInstance().Hash(dataCacheData);
Kevin May42477c12020-03-26 13:34:14 +0000351 }
352
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100353 // Cache the model data
354 if (modelCacheHandle.size() > 0)
Kevin May42477c12020-03-26 13:34:14 +0000355 {
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100356 if (modelCacheHandle.size() != numberOfCachedModelFiles)
Kevin May42477c12020-03-26 13:34:14 +0000357 {
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100358 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
359 return V1_3::ErrorStatus::NONE;
Kevin May42477c12020-03-26 13:34:14 +0000360 }
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100361
362 for (uint32_t i = 0; i < modelCacheHandle.size(); ++i)
Kevin May42477c12020-03-26 13:34:14 +0000363 {
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100364 if (modelCacheHandle[i]->numFds == 1)
365 {
366 int modelCacheFileAccessMode = fcntl(modelCacheHandle[i]->data[0], F_GETFL) & O_ACCMODE;
367 if (modelCacheFileAccessMode != O_RDONLY)
368 {
369 struct stat statBuffer;
370 if (fstat(modelCacheHandle[i]->data[0], &statBuffer) == 0)
371 {
372 long modelDataSize = statBuffer.st_size;
373 if (modelDataSize > 0)
374 {
375 std::vector<uint8_t> modelData(modelDataSize);
376 pread(modelCacheHandle[i]->data[0], modelData.data(), modelData.size(), 0);
377 hashValue ^= CacheDataHandlerInstance().Hash(modelData);
378 }
379 }
380 }
381 }
Kevin May42477c12020-03-26 13:34:14 +0000382 }
383 }
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100384 if (hashValue != 0)
385 {
386 CacheDataHandlerInstance().Register(token, hashValue, dataCacheData.size());
387 }
Kevin May42477c12020-03-26 13:34:14 +0000388
389 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100390 return V1_3::ErrorStatus::NONE;
391}
Kevin May42477c12020-03-26 13:34:14 +0000392
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100393Return<V1_3::ErrorStatus> ArmnnDriverImpl::prepareModelFromCache_1_3(
394 const armnn::IRuntimePtr& runtime,
395 const DriverOptions& options,
396 const android::hardware::hidl_vec<android::hardware::hidl_handle>& modelCacheHandle,
397 const android::hardware::hidl_vec<android::hardware::hidl_handle>& dataCacheHandle,
398 const HidlToken& token,
399 const android::sp<V1_3::IPreparedModelCallback>& cb)
400{
401 ALOGV("ArmnnDriverImpl::prepareModelFromCache_1_3()");
402
403 if (token.size() != ANEURALNETWORKS_BYTE_SIZE_OF_CACHE_TOKEN)
404 {
405 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
406 return V1_3::ErrorStatus::GENERAL_FAILURE;
407 }
408
409 if (cb.get() == nullptr)
410 {
411 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Invalid callback passed to prepareModelFromCache_1_3");
412 return V1_3::ErrorStatus::INVALID_ARGUMENT;
413 }
414
415 if (!runtime)
416 {
417 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Device unavailable");
418 return V1_3::ErrorStatus::DEVICE_UNAVAILABLE;
419 }
420
421 // DataCacheHandle size should always be 1
422 // Arm NN model
423 if (dataCacheHandle.size() != 1)
424 {
425 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
426 return V1_3::ErrorStatus::GENERAL_FAILURE;
427 }
428
429 // Check if model files cached they match the expected value
430 unsigned int numberOfCachedModelFiles = 0;
431 for (auto& backend : options.GetBackends())
432 {
433 numberOfCachedModelFiles += GetNumberOfCacheFiles(backend);
434 }
435 if (modelCacheHandle.size() != numberOfCachedModelFiles)
436 {
437 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
438 return V1_3::ErrorStatus::GENERAL_FAILURE;
439 }
440
441 if (dataCacheHandle[0]->numFds != 1)
442 {
443 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3(): Cannot read from the cache data, numFds != 1.");
444 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
445 return V1_3::ErrorStatus::GENERAL_FAILURE;
446 }
447
Sadik Armaganee6818b2021-11-05 14:41:52 +0000448 if (dataCacheHandle[0]->data[0] < 0)
449 {
450 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3(): Cannot read from the cache data, fd < 0");
451 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
452 return V1_3::ErrorStatus::GENERAL_FAILURE;
453 }
454
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100455 int dataCacheFileAccessMode = fcntl(dataCacheHandle[0]->data[0], F_GETFL) & O_ACCMODE;
456 if (dataCacheFileAccessMode != O_RDWR)
457 {
458 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
459 return V1_3::ErrorStatus::GENERAL_FAILURE;
460 }
461
462 auto dataSize = CacheDataHandlerInstance().GetCacheSize(token);
463 if (dataSize == 0)
464 {
465 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Invalid data to deserialize!");
466 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
467 return V1_3::ErrorStatus::GENERAL_FAILURE;
468 }
469
470 int offset = 0;
471 {
472 struct stat statBuffer;
473 if (fstat(dataCacheHandle[0]->data[0], &statBuffer) == 0)
474 {
475 unsigned long bufferSize = statBuffer.st_size;
Sadik Armaganee6818b2021-11-05 14:41:52 +0000476 if (bufferSize != dataSize)
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100477 {
478 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Invalid data to deserialize!");
479 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
480 return V1_3::ErrorStatus::GENERAL_FAILURE;
481 }
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100482 }
483 }
484 std::vector<uint8_t> dataCacheData(dataSize);
485 pread(dataCacheHandle[0]->data[0], dataCacheData.data(), dataCacheData.size(), offset);
486 auto hashValue = CacheDataHandlerInstance().Hash(dataCacheData);
487
488 int gpuAccCachedFd = -1;
489 bool saveCachedNetwork = false;
490 if (modelCacheHandle.size() > 0)
491 {
492 unsigned int index = 0;
493 for (auto& backend : options.GetBackends())
494 {
495 // modelCacheHandle size should be equal to numberOfCachedModelFiles
496 // modelCacheHandle vector should be in same order as backends
497 auto numberOfCacheFiles = GetNumberOfCacheFiles(backend);
498 if (numberOfCacheFiles > 0)
499 {
500 if (modelCacheHandle[index]->numFds != 1)
501 {
502 ALOGW(
503 "ArmnnDriverImpl::prepareModelFromCache_1_3(): Cannot read from the model cache, numFds != 1.");
504 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
505 return V1_3::ErrorStatus::GENERAL_FAILURE;
506 }
507 auto cachedFd = modelCacheHandle[index]->data[0];
508
509 int modelCacheFileAccessMode = fcntl(cachedFd, F_GETFL) & O_ACCMODE;
510 if (modelCacheFileAccessMode != O_RDWR)
511 {
512 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
513 return V1_3::ErrorStatus::GENERAL_FAILURE;
514 }
515
516 struct stat statBuffer;
517 if (cachedFd != -1 && fstat(cachedFd, &statBuffer) == 0)
518 {
519 long modelDataSize = statBuffer.st_size;
Sadik Armaganee6818b2021-11-05 14:41:52 +0000520 if (modelDataSize <= 0)
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100521 {
Sadik Armaganee6818b2021-11-05 14:41:52 +0000522 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3(): Wrong cached model size!");
523 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
524 return V1_3::ErrorStatus::NONE;
525 }
526 std::vector<uint8_t> modelData(modelDataSize);
527 pread(cachedFd, modelData.data(), modelData.size(), 0);
528 hashValue ^= CacheDataHandlerInstance().Hash(modelData);
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100529
Sadik Armaganee6818b2021-11-05 14:41:52 +0000530 // For GpuAcc numberOfCachedFiles is 1
531 if (backend == armnn::Compute::GpuAcc)
532 {
533 gpuAccCachedFd = cachedFd;
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100534 }
535 }
536 index += numberOfCacheFiles;
537 }
538 }
539 }
540
Sadik Armaganee6818b2021-11-05 14:41:52 +0000541 if (!CacheDataHandlerInstance().Validate(token, hashValue, dataCacheData.size()))
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100542 {
543 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: ValidateHash() failed!");
544 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
545 return V1_3::ErrorStatus::GENERAL_FAILURE;
546 }
547
548 // Deserialize the network..
Sadik Armaganee6818b2021-11-05 14:41:52 +0000549 armnn::INetworkPtr network = armnn::INetworkPtr(nullptr, [](armnn::INetwork*){});
550 try
551 {
552 network = armnnDeserializer::IDeserializer::Create()->CreateNetworkFromBinary(dataCacheData);
553 }
554 catch (std::exception&)
555 {
556 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Exception caught from Deserializer!");
557 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
558 return V1_3::ErrorStatus::GENERAL_FAILURE;
559 }
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100560
561 // Optimize the network
562 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
563 armnn::OptimizerOptions OptOptions;
564 OptOptions.m_ReduceFp32ToFp16 = options.GetFp16Enabled();
565 OptOptions.m_ProfilingEnabled = options.IsGpuProfilingEnabled();
566
567 armnn::BackendOptions gpuAcc("GpuAcc",
568 {
569 {"FastMathEnabled", options.IsFastMathEnabled()},
570 {"SaveCachedNetwork", saveCachedNetwork},
571 {"CachedNetworkFilePath", options.GetCachedNetworkFilePath()},
572 {"MLGOTuningFilePath", options.GetClMLGOTunedParametersFile()},
573 {"CachedFileDescriptor", gpuAccCachedFd}
574 });
575
576 armnn::BackendOptions cpuAcc("CpuAcc",
577 {
578 {"FastMathEnabled", options.IsFastMathEnabled()},
579 {"NumberOfThreads", options.GetNumberOfThreads()}
580 });
581 OptOptions.m_ModelOptions.push_back(gpuAcc);
582 OptOptions.m_ModelOptions.push_back(cpuAcc);
583
584 std::vector<std::string> errMessages;
585 try
586 {
587 optNet = armnn::Optimize(*network.get(),
588 options.GetBackends(),
589 runtime->GetDeviceSpec(),
590 OptOptions,
591 errMessages);
592 }
593 catch (std::exception& e)
594 {
595 std::stringstream message;
596 message << "Exception (" << e.what() << ") caught from optimize.";
597 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
598 return V1_3::ErrorStatus::NONE;
599 }
600
601 // Check that the optimized network is valid.
602 if (!optNet)
603 {
604 std::stringstream message;
605 message << "Invalid optimized network";
606 for (const std::string& msg : errMessages)
607 {
608 message << "\n" << msg;
609 }
610 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
611 return V1_3::ErrorStatus::NONE;
612 }
613
614 // Export the optimized network graph to a dot file if an output dump directory
615 // has been specified in the drivers' arguments.
616 std::string dotGraphFileName = ExportNetworkGraphToDotFile(*optNet,
617 options.GetRequestInputsAndOutputsDumpDir());
618
619 // Load it into the runtime.
620 armnn::NetworkId netId = 0;
621 std::string msg;
622 armnn::INetworkProperties networkProperties(options.isAsyncModelExecutionEnabled(),
623 MemorySource::Undefined,
624 MemorySource::Undefined,
625 options.IsGpuProfilingEnabled());
626
627 try
628 {
629 if (runtime->LoadNetwork(netId, move(optNet), msg, networkProperties) != armnn::Status::Success)
630 {
631 return FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, msg, cb);
632 }
633 }
634 catch (std::exception& e)
635 {
636 std::stringstream message;
637 message << "Exception (" << e.what() << ") caught from LoadNetwork.";
638 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
639 return V1_3::ErrorStatus::NONE;
640 }
641
642 std::unique_ptr<ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>> preparedModel(
643 new ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>(netId,
644 runtime.get(),
645 options.GetRequestInputsAndOutputsDumpDir(),
646 options.IsGpuProfilingEnabled(),
647 V1_3::Priority::MEDIUM,
648 options.isAsyncModelExecutionEnabled(),
649 options.getNoOfArmnnThreads(),
Narumol Prangnawaratd1a947f2022-02-07 13:12:24 +0000650 options.isImportEnabled(),
651 options.isExportEnabled(),
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100652 true));
653
654 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
Kevin May42477c12020-03-26 13:34:14 +0000655 return V1_3::ErrorStatus::NONE;
656}
657
658Return<void> ArmnnDriverImpl::getCapabilities_1_3(const armnn::IRuntimePtr& runtime,
659 V1_3::IDevice::getCapabilities_1_3_cb cb)
660{
661 ALOGV("hal_1_3::ArmnnDriverImpl::getCapabilities()");
662
663 V1_3::Capabilities capabilities;
664
665 float defaultValue = .1f;
666
667 if (runtime)
668 {
669 capabilities.relaxedFloat32toFloat16PerformanceScalar.execTime =
670 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformanceExecTime, defaultValue);
671
Kevin May2eaa1192020-04-15 16:50:57 +0100672 capabilities.relaxedFloat32toFloat16PerformanceScalar.powerUsage =
673 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformancePowerUsage, defaultValue);
674
675 capabilities.relaxedFloat32toFloat16PerformanceTensor.execTime =
676 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformanceExecTime, defaultValue);
677
Kevin May42477c12020-03-26 13:34:14 +0000678 capabilities.relaxedFloat32toFloat16PerformanceTensor.powerUsage =
679 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformancePowerUsage, defaultValue);
680
Kevin May2eaa1192020-04-15 16:50:57 +0100681 capabilities.ifPerformance.execTime =
682 ParseSystemProperty(g_ifPerformanceExecTime, defaultValue);
683
684 capabilities.ifPerformance.powerUsage =
685 ParseSystemProperty(g_ifPerformancePowerUsage, defaultValue);
686
687 capabilities.whilePerformance.execTime =
688 ParseSystemProperty(g_whilePerformanceExecTime, defaultValue);
689
690 capabilities.whilePerformance.powerUsage =
691 ParseSystemProperty(g_whilePerformancePowerUsage, defaultValue);
692
Kevin May42477c12020-03-26 13:34:14 +0000693 // Set the base value for all operand types
694 capabilities.operandPerformance = nonExtensionOperandPerformance<HalVersion::V1_3>({FLT_MAX, FLT_MAX});
695
696 // Load supported operand types
697 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT32,
698 {
699 .execTime = ParseSystemProperty(g_OperandTypeTensorFloat32PerformanceExecTime, defaultValue),
700 .powerUsage = ParseSystemProperty(g_OperandTypeTensorFloat32PerformancePowerUsage, defaultValue)
701 });
702
703 update(&capabilities.operandPerformance, V1_3::OperandType::FLOAT32,
704 {
705 .execTime = ParseSystemProperty(g_OperandTypeFloat32PerformanceExecTime, defaultValue),
706 .powerUsage = ParseSystemProperty(g_OperandTypeFloat32PerformancePowerUsage, defaultValue)
707 });
708
709 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT16,
710 {
711 .execTime = ParseSystemProperty(g_OperandTypeTensorFloat16PerformanceExecTime, defaultValue),
712 .powerUsage = ParseSystemProperty(g_OperandTypeTensorFloat16PerformancePowerUsage, defaultValue)
713 });
714
715 update(&capabilities.operandPerformance, V1_3::OperandType::FLOAT16,
716 {
717 .execTime = ParseSystemProperty(g_OperandTypeFloat16PerformanceExecTime, defaultValue),
718 .powerUsage = ParseSystemProperty(g_OperandTypeFloat16PerformancePowerUsage, defaultValue)
719 });
720
721 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_ASYMM,
722 {
723 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmPerformanceExecTime, defaultValue),
724 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmPerformancePowerUsage, defaultValue)
725 });
726
727 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_SYMM,
728 {
729 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerformanceExecTime, defaultValue),
730 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerformancePowerUsage, defaultValue)
731 });
732 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_ASYMM_SIGNED,
733 {
734 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmSignedPerformanceExecTime,
735 defaultValue),
736 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmSignedPerformancePowerUsage,
737 defaultValue)
738 });
739
740 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT16_SYMM,
741 {
742 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant16SymmPerformanceExecTime, defaultValue),
743 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant16SymmPerformancePowerUsage, defaultValue)
744 });
745
746 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL,
747 {
748 .execTime =
749 ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerChannelPerformanceExecTime, defaultValue),
750 .powerUsage =
751 ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerChannelPerformancePowerUsage, defaultValue)
752 });
753
754 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_INT32,
755 {
756 .execTime = ParseSystemProperty(g_OperandTypeTensorInt32PerformanceExecTime, defaultValue),
757 .powerUsage = ParseSystemProperty(g_OperandTypeTensorInt32PerformancePowerUsage, defaultValue)
758 });
759
760 update(&capabilities.operandPerformance, V1_3::OperandType::INT32,
761 {
762 .execTime = ParseSystemProperty(g_OperandTypeInt32PerformanceExecTime, defaultValue),
763 .powerUsage = ParseSystemProperty(g_OperandTypeInt32PerformancePowerUsage, defaultValue)
764 });
765
766 cb(V1_3::ErrorStatus::NONE, capabilities);
767 }
768 else
769 {
Kevin May2eaa1192020-04-15 16:50:57 +0100770 capabilities.relaxedFloat32toFloat16PerformanceScalar.execTime = 0;
771 capabilities.relaxedFloat32toFloat16PerformanceScalar.powerUsage = 0;
772 capabilities.relaxedFloat32toFloat16PerformanceTensor.execTime = 0;
773 capabilities.relaxedFloat32toFloat16PerformanceTensor.powerUsage = 0;
774 capabilities.ifPerformance.execTime = 0;
775 capabilities.ifPerformance.powerUsage = 0;
776 capabilities.whilePerformance.execTime = 0;
777 capabilities.whilePerformance.powerUsage = 0;
Kevin May42477c12020-03-26 13:34:14 +0000778
779 // Set the base value for all operand types
780 capabilities.operandPerformance = nonExtensionOperandPerformance<HalVersion::V1_3>({0.f, 0.0f});
781
782 cb(V1_3::ErrorStatus::DEVICE_UNAVAILABLE, capabilities);
783 }
784
785 return Void();
786}
787
788} // namespace hal_1_3
789} // namespace armnn_driver