blob: c8b1d96870729a8fe0bdd835988dbad0ea2606ae [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(),
284 options.getNoOfArmnnThreads()));
Kevin May42477c12020-03-26 13:34:14 +0000285
286 // Run a single 'dummy' inference of the model. This means that CL kernels will get compiled (and tuned if
287 // this is enabled) before the first 'real' inference which removes the overhead of the first inference.
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100288 // Only run this if the GpuAcc backend has been added to options
289 if (std::find(options.GetBackends().begin(),
290 options.GetBackends().end(),
291 armnn::Compute::GpuAcc) != options.GetBackends().end())
Kevin May42477c12020-03-26 13:34:14 +0000292 {
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100293 if (!preparedModel->ExecuteWithDummyInputs(numInputs, numOutputs))
294 {
295 return FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, "Network could not be executed", cb);
296 }
297
298 if (clTunedParameters &&
299 options.GetClTunedParametersMode() == armnn::IGpuAccTunedParameters::Mode::UpdateTunedParameters)
300 {
301 // Now that we've done one inference the CL kernel parameters will have been tuned,
302 // so save the updated file.
303 try
304 {
305 clTunedParameters->Save(options.GetClTunedParametersFile().c_str());
306 }
307 catch (std::exception& error)
308 {
309 ALOGE("ArmnnDriverImpl::prepareModel: Failed to save CL tuned parameters file '%s': %s",
310 options.GetClTunedParametersFile().c_str(), error.what());
311 }
312 }
313 }
314 size_t hashValue = 0;
315 // Cache the model
316 if (dataCacheHandle.size() > 0)
317 {
318 // Cache the Arm NN model
319 if (dataCacheHandle.size() != 1)
320 {
321 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
322 return V1_3::ErrorStatus::NONE;
323 }
324
325 if (dataCacheHandle[0]->numFds != 1)
326 {
327 ALOGW("ArmnnDriverImpl::prepareArmnnModel_1_3: Cannot cache the data, numFds != 1.");
328 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
329 return V1_3::ErrorStatus::NONE;
330 }
Sadik Armaganee6818b2021-11-05 14:41:52 +0000331
332 if (dataCacheHandle[0]->data[0] < 0)
333 {
334 ALOGW("ArmnnDriverImpl::prepareArmnnModel_1_3: Cannot cache the data, fd < 0");
335 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
336 return V1_3::ErrorStatus::NONE;
337 }
338
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100339 int dataCacheFileAccessMode = fcntl(dataCacheHandle[0]->data[0], F_GETFL) & O_ACCMODE;
340 if (dataCacheFileAccessMode != O_RDWR)
341 {
342 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3(): Invalid Access Mode.");
343 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
344 return V1_3::ErrorStatus::NONE;
345 }
346
347 write(dataCacheHandle[0]->data[0], dataCacheData.data(), dataCacheData.size());
348 hashValue = CacheDataHandlerInstance().Hash(dataCacheData);
Kevin May42477c12020-03-26 13:34:14 +0000349 }
350
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100351 // Cache the model data
352 if (modelCacheHandle.size() > 0)
Kevin May42477c12020-03-26 13:34:14 +0000353 {
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100354 if (modelCacheHandle.size() != numberOfCachedModelFiles)
Kevin May42477c12020-03-26 13:34:14 +0000355 {
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100356 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
357 return V1_3::ErrorStatus::NONE;
Kevin May42477c12020-03-26 13:34:14 +0000358 }
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100359
360 for (uint32_t i = 0; i < modelCacheHandle.size(); ++i)
Kevin May42477c12020-03-26 13:34:14 +0000361 {
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100362 if (modelCacheHandle[i]->numFds == 1)
363 {
364 int modelCacheFileAccessMode = fcntl(modelCacheHandle[i]->data[0], F_GETFL) & O_ACCMODE;
365 if (modelCacheFileAccessMode != O_RDONLY)
366 {
367 struct stat statBuffer;
368 if (fstat(modelCacheHandle[i]->data[0], &statBuffer) == 0)
369 {
370 long modelDataSize = statBuffer.st_size;
371 if (modelDataSize > 0)
372 {
373 std::vector<uint8_t> modelData(modelDataSize);
374 pread(modelCacheHandle[i]->data[0], modelData.data(), modelData.size(), 0);
375 hashValue ^= CacheDataHandlerInstance().Hash(modelData);
376 }
377 }
378 }
379 }
Kevin May42477c12020-03-26 13:34:14 +0000380 }
381 }
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100382 if (hashValue != 0)
383 {
384 CacheDataHandlerInstance().Register(token, hashValue, dataCacheData.size());
385 }
Kevin May42477c12020-03-26 13:34:14 +0000386
387 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100388 return V1_3::ErrorStatus::NONE;
389}
Kevin May42477c12020-03-26 13:34:14 +0000390
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100391Return<V1_3::ErrorStatus> ArmnnDriverImpl::prepareModelFromCache_1_3(
392 const armnn::IRuntimePtr& runtime,
393 const DriverOptions& options,
394 const android::hardware::hidl_vec<android::hardware::hidl_handle>& modelCacheHandle,
395 const android::hardware::hidl_vec<android::hardware::hidl_handle>& dataCacheHandle,
396 const HidlToken& token,
397 const android::sp<V1_3::IPreparedModelCallback>& cb)
398{
399 ALOGV("ArmnnDriverImpl::prepareModelFromCache_1_3()");
400
401 if (token.size() != ANEURALNETWORKS_BYTE_SIZE_OF_CACHE_TOKEN)
402 {
403 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
404 return V1_3::ErrorStatus::GENERAL_FAILURE;
405 }
406
407 if (cb.get() == nullptr)
408 {
409 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Invalid callback passed to prepareModelFromCache_1_3");
410 return V1_3::ErrorStatus::INVALID_ARGUMENT;
411 }
412
413 if (!runtime)
414 {
415 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Device unavailable");
416 return V1_3::ErrorStatus::DEVICE_UNAVAILABLE;
417 }
418
419 // DataCacheHandle size should always be 1
420 // Arm NN model
421 if (dataCacheHandle.size() != 1)
422 {
423 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
424 return V1_3::ErrorStatus::GENERAL_FAILURE;
425 }
426
427 // Check if model files cached they match the expected value
428 unsigned int numberOfCachedModelFiles = 0;
429 for (auto& backend : options.GetBackends())
430 {
431 numberOfCachedModelFiles += GetNumberOfCacheFiles(backend);
432 }
433 if (modelCacheHandle.size() != numberOfCachedModelFiles)
434 {
435 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
436 return V1_3::ErrorStatus::GENERAL_FAILURE;
437 }
438
439 if (dataCacheHandle[0]->numFds != 1)
440 {
441 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3(): Cannot read from the cache data, numFds != 1.");
442 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
443 return V1_3::ErrorStatus::GENERAL_FAILURE;
444 }
445
Sadik Armaganee6818b2021-11-05 14:41:52 +0000446 if (dataCacheHandle[0]->data[0] < 0)
447 {
448 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3(): Cannot read from the cache data, fd < 0");
449 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
450 return V1_3::ErrorStatus::GENERAL_FAILURE;
451 }
452
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100453 int dataCacheFileAccessMode = fcntl(dataCacheHandle[0]->data[0], F_GETFL) & O_ACCMODE;
454 if (dataCacheFileAccessMode != O_RDWR)
455 {
456 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
457 return V1_3::ErrorStatus::GENERAL_FAILURE;
458 }
459
460 auto dataSize = CacheDataHandlerInstance().GetCacheSize(token);
461 if (dataSize == 0)
462 {
463 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Invalid data to deserialize!");
464 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
465 return V1_3::ErrorStatus::GENERAL_FAILURE;
466 }
467
468 int offset = 0;
469 {
470 struct stat statBuffer;
471 if (fstat(dataCacheHandle[0]->data[0], &statBuffer) == 0)
472 {
473 unsigned long bufferSize = statBuffer.st_size;
Sadik Armaganee6818b2021-11-05 14:41:52 +0000474 if (bufferSize != dataSize)
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100475 {
476 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Invalid data to deserialize!");
477 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
478 return V1_3::ErrorStatus::GENERAL_FAILURE;
479 }
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100480 }
481 }
482 std::vector<uint8_t> dataCacheData(dataSize);
483 pread(dataCacheHandle[0]->data[0], dataCacheData.data(), dataCacheData.size(), offset);
484 auto hashValue = CacheDataHandlerInstance().Hash(dataCacheData);
485
486 int gpuAccCachedFd = -1;
487 bool saveCachedNetwork = false;
488 if (modelCacheHandle.size() > 0)
489 {
490 unsigned int index = 0;
491 for (auto& backend : options.GetBackends())
492 {
493 // modelCacheHandle size should be equal to numberOfCachedModelFiles
494 // modelCacheHandle vector should be in same order as backends
495 auto numberOfCacheFiles = GetNumberOfCacheFiles(backend);
496 if (numberOfCacheFiles > 0)
497 {
498 if (modelCacheHandle[index]->numFds != 1)
499 {
500 ALOGW(
501 "ArmnnDriverImpl::prepareModelFromCache_1_3(): Cannot read from the model cache, numFds != 1.");
502 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
503 return V1_3::ErrorStatus::GENERAL_FAILURE;
504 }
505 auto cachedFd = modelCacheHandle[index]->data[0];
506
507 int modelCacheFileAccessMode = fcntl(cachedFd, F_GETFL) & O_ACCMODE;
508 if (modelCacheFileAccessMode != O_RDWR)
509 {
510 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
511 return V1_3::ErrorStatus::GENERAL_FAILURE;
512 }
513
514 struct stat statBuffer;
515 if (cachedFd != -1 && fstat(cachedFd, &statBuffer) == 0)
516 {
517 long modelDataSize = statBuffer.st_size;
Sadik Armaganee6818b2021-11-05 14:41:52 +0000518 if (modelDataSize <= 0)
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100519 {
Sadik Armaganee6818b2021-11-05 14:41:52 +0000520 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3(): Wrong cached model size!");
521 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
522 return V1_3::ErrorStatus::NONE;
523 }
524 std::vector<uint8_t> modelData(modelDataSize);
525 pread(cachedFd, modelData.data(), modelData.size(), 0);
526 hashValue ^= CacheDataHandlerInstance().Hash(modelData);
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100527
Sadik Armaganee6818b2021-11-05 14:41:52 +0000528 // For GpuAcc numberOfCachedFiles is 1
529 if (backend == armnn::Compute::GpuAcc)
530 {
531 gpuAccCachedFd = cachedFd;
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100532 }
533 }
534 index += numberOfCacheFiles;
535 }
536 }
537 }
538
Sadik Armaganee6818b2021-11-05 14:41:52 +0000539 if (!CacheDataHandlerInstance().Validate(token, hashValue, dataCacheData.size()))
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100540 {
541 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: ValidateHash() failed!");
542 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
543 return V1_3::ErrorStatus::GENERAL_FAILURE;
544 }
545
546 // Deserialize the network..
Sadik Armaganee6818b2021-11-05 14:41:52 +0000547 armnn::INetworkPtr network = armnn::INetworkPtr(nullptr, [](armnn::INetwork*){});
548 try
549 {
550 network = armnnDeserializer::IDeserializer::Create()->CreateNetworkFromBinary(dataCacheData);
551 }
552 catch (std::exception&)
553 {
554 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Exception caught from Deserializer!");
555 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
556 return V1_3::ErrorStatus::GENERAL_FAILURE;
557 }
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100558
559 // Optimize the network
560 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
561 armnn::OptimizerOptions OptOptions;
562 OptOptions.m_ReduceFp32ToFp16 = options.GetFp16Enabled();
563 OptOptions.m_ProfilingEnabled = options.IsGpuProfilingEnabled();
564
565 armnn::BackendOptions gpuAcc("GpuAcc",
566 {
567 {"FastMathEnabled", options.IsFastMathEnabled()},
568 {"SaveCachedNetwork", saveCachedNetwork},
569 {"CachedNetworkFilePath", options.GetCachedNetworkFilePath()},
570 {"MLGOTuningFilePath", options.GetClMLGOTunedParametersFile()},
571 {"CachedFileDescriptor", gpuAccCachedFd}
572 });
573
574 armnn::BackendOptions cpuAcc("CpuAcc",
575 {
576 {"FastMathEnabled", options.IsFastMathEnabled()},
577 {"NumberOfThreads", options.GetNumberOfThreads()}
578 });
579 OptOptions.m_ModelOptions.push_back(gpuAcc);
580 OptOptions.m_ModelOptions.push_back(cpuAcc);
581
582 std::vector<std::string> errMessages;
583 try
584 {
585 optNet = armnn::Optimize(*network.get(),
586 options.GetBackends(),
587 runtime->GetDeviceSpec(),
588 OptOptions,
589 errMessages);
590 }
591 catch (std::exception& e)
592 {
593 std::stringstream message;
594 message << "Exception (" << e.what() << ") caught from optimize.";
595 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
596 return V1_3::ErrorStatus::NONE;
597 }
598
599 // Check that the optimized network is valid.
600 if (!optNet)
601 {
602 std::stringstream message;
603 message << "Invalid optimized network";
604 for (const std::string& msg : errMessages)
605 {
606 message << "\n" << msg;
607 }
608 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
609 return V1_3::ErrorStatus::NONE;
610 }
611
612 // Export the optimized network graph to a dot file if an output dump directory
613 // has been specified in the drivers' arguments.
614 std::string dotGraphFileName = ExportNetworkGraphToDotFile(*optNet,
615 options.GetRequestInputsAndOutputsDumpDir());
616
617 // Load it into the runtime.
618 armnn::NetworkId netId = 0;
619 std::string msg;
620 armnn::INetworkProperties networkProperties(options.isAsyncModelExecutionEnabled(),
621 MemorySource::Undefined,
622 MemorySource::Undefined,
623 options.IsGpuProfilingEnabled());
624
625 try
626 {
627 if (runtime->LoadNetwork(netId, move(optNet), msg, networkProperties) != armnn::Status::Success)
628 {
629 return FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, msg, cb);
630 }
631 }
632 catch (std::exception& e)
633 {
634 std::stringstream message;
635 message << "Exception (" << e.what() << ") caught from LoadNetwork.";
636 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
637 return V1_3::ErrorStatus::NONE;
638 }
639
640 std::unique_ptr<ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>> preparedModel(
641 new ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>(netId,
642 runtime.get(),
643 options.GetRequestInputsAndOutputsDumpDir(),
644 options.IsGpuProfilingEnabled(),
645 V1_3::Priority::MEDIUM,
646 options.isAsyncModelExecutionEnabled(),
647 options.getNoOfArmnnThreads(),
648 true));
649
650 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
Kevin May42477c12020-03-26 13:34:14 +0000651 return V1_3::ErrorStatus::NONE;
652}
653
654Return<void> ArmnnDriverImpl::getCapabilities_1_3(const armnn::IRuntimePtr& runtime,
655 V1_3::IDevice::getCapabilities_1_3_cb cb)
656{
657 ALOGV("hal_1_3::ArmnnDriverImpl::getCapabilities()");
658
659 V1_3::Capabilities capabilities;
660
661 float defaultValue = .1f;
662
663 if (runtime)
664 {
665 capabilities.relaxedFloat32toFloat16PerformanceScalar.execTime =
666 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformanceExecTime, defaultValue);
667
Kevin May2eaa1192020-04-15 16:50:57 +0100668 capabilities.relaxedFloat32toFloat16PerformanceScalar.powerUsage =
669 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformancePowerUsage, defaultValue);
670
671 capabilities.relaxedFloat32toFloat16PerformanceTensor.execTime =
672 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformanceExecTime, defaultValue);
673
Kevin May42477c12020-03-26 13:34:14 +0000674 capabilities.relaxedFloat32toFloat16PerformanceTensor.powerUsage =
675 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformancePowerUsage, defaultValue);
676
Kevin May2eaa1192020-04-15 16:50:57 +0100677 capabilities.ifPerformance.execTime =
678 ParseSystemProperty(g_ifPerformanceExecTime, defaultValue);
679
680 capabilities.ifPerformance.powerUsage =
681 ParseSystemProperty(g_ifPerformancePowerUsage, defaultValue);
682
683 capabilities.whilePerformance.execTime =
684 ParseSystemProperty(g_whilePerformanceExecTime, defaultValue);
685
686 capabilities.whilePerformance.powerUsage =
687 ParseSystemProperty(g_whilePerformancePowerUsage, defaultValue);
688
Kevin May42477c12020-03-26 13:34:14 +0000689 // Set the base value for all operand types
690 capabilities.operandPerformance = nonExtensionOperandPerformance<HalVersion::V1_3>({FLT_MAX, FLT_MAX});
691
692 // Load supported operand types
693 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT32,
694 {
695 .execTime = ParseSystemProperty(g_OperandTypeTensorFloat32PerformanceExecTime, defaultValue),
696 .powerUsage = ParseSystemProperty(g_OperandTypeTensorFloat32PerformancePowerUsage, defaultValue)
697 });
698
699 update(&capabilities.operandPerformance, V1_3::OperandType::FLOAT32,
700 {
701 .execTime = ParseSystemProperty(g_OperandTypeFloat32PerformanceExecTime, defaultValue),
702 .powerUsage = ParseSystemProperty(g_OperandTypeFloat32PerformancePowerUsage, defaultValue)
703 });
704
705 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT16,
706 {
707 .execTime = ParseSystemProperty(g_OperandTypeTensorFloat16PerformanceExecTime, defaultValue),
708 .powerUsage = ParseSystemProperty(g_OperandTypeTensorFloat16PerformancePowerUsage, defaultValue)
709 });
710
711 update(&capabilities.operandPerformance, V1_3::OperandType::FLOAT16,
712 {
713 .execTime = ParseSystemProperty(g_OperandTypeFloat16PerformanceExecTime, defaultValue),
714 .powerUsage = ParseSystemProperty(g_OperandTypeFloat16PerformancePowerUsage, defaultValue)
715 });
716
717 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_ASYMM,
718 {
719 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmPerformanceExecTime, defaultValue),
720 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmPerformancePowerUsage, defaultValue)
721 });
722
723 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_SYMM,
724 {
725 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerformanceExecTime, defaultValue),
726 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerformancePowerUsage, defaultValue)
727 });
728 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_ASYMM_SIGNED,
729 {
730 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmSignedPerformanceExecTime,
731 defaultValue),
732 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmSignedPerformancePowerUsage,
733 defaultValue)
734 });
735
736 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT16_SYMM,
737 {
738 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant16SymmPerformanceExecTime, defaultValue),
739 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant16SymmPerformancePowerUsage, defaultValue)
740 });
741
742 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL,
743 {
744 .execTime =
745 ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerChannelPerformanceExecTime, defaultValue),
746 .powerUsage =
747 ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerChannelPerformancePowerUsage, defaultValue)
748 });
749
750 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_INT32,
751 {
752 .execTime = ParseSystemProperty(g_OperandTypeTensorInt32PerformanceExecTime, defaultValue),
753 .powerUsage = ParseSystemProperty(g_OperandTypeTensorInt32PerformancePowerUsage, defaultValue)
754 });
755
756 update(&capabilities.operandPerformance, V1_3::OperandType::INT32,
757 {
758 .execTime = ParseSystemProperty(g_OperandTypeInt32PerformanceExecTime, defaultValue),
759 .powerUsage = ParseSystemProperty(g_OperandTypeInt32PerformancePowerUsage, defaultValue)
760 });
761
762 cb(V1_3::ErrorStatus::NONE, capabilities);
763 }
764 else
765 {
Kevin May2eaa1192020-04-15 16:50:57 +0100766 capabilities.relaxedFloat32toFloat16PerformanceScalar.execTime = 0;
767 capabilities.relaxedFloat32toFloat16PerformanceScalar.powerUsage = 0;
768 capabilities.relaxedFloat32toFloat16PerformanceTensor.execTime = 0;
769 capabilities.relaxedFloat32toFloat16PerformanceTensor.powerUsage = 0;
770 capabilities.ifPerformance.execTime = 0;
771 capabilities.ifPerformance.powerUsage = 0;
772 capabilities.whilePerformance.execTime = 0;
773 capabilities.whilePerformance.powerUsage = 0;
Kevin May42477c12020-03-26 13:34:14 +0000774
775 // Set the base value for all operand types
776 capabilities.operandPerformance = nonExtensionOperandPerformance<HalVersion::V1_3>({0.f, 0.0f});
777
778 cb(V1_3::ErrorStatus::DEVICE_UNAVAILABLE, capabilities);
779 }
780
781 return Void();
782}
783
784} // namespace hal_1_3
785} // namespace armnn_driver