blob: e1d65f92957dbca244b938a610aa8a6f0dc6077a [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 }
331 int dataCacheFileAccessMode = fcntl(dataCacheHandle[0]->data[0], F_GETFL) & O_ACCMODE;
332 if (dataCacheFileAccessMode != O_RDWR)
333 {
334 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3(): Invalid Access Mode.");
335 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
336 return V1_3::ErrorStatus::NONE;
337 }
338
339 write(dataCacheHandle[0]->data[0], dataCacheData.data(), dataCacheData.size());
340 hashValue = CacheDataHandlerInstance().Hash(dataCacheData);
Kevin May42477c12020-03-26 13:34:14 +0000341 }
342
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100343 // Cache the model data
344 if (modelCacheHandle.size() > 0)
Kevin May42477c12020-03-26 13:34:14 +0000345 {
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100346 if (modelCacheHandle.size() != numberOfCachedModelFiles)
Kevin May42477c12020-03-26 13:34:14 +0000347 {
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100348 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
349 return V1_3::ErrorStatus::NONE;
Kevin May42477c12020-03-26 13:34:14 +0000350 }
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100351
352 for (uint32_t i = 0; i < modelCacheHandle.size(); ++i)
Kevin May42477c12020-03-26 13:34:14 +0000353 {
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100354 if (modelCacheHandle[i]->numFds == 1)
355 {
356 int modelCacheFileAccessMode = fcntl(modelCacheHandle[i]->data[0], F_GETFL) & O_ACCMODE;
357 if (modelCacheFileAccessMode != O_RDONLY)
358 {
359 struct stat statBuffer;
360 if (fstat(modelCacheHandle[i]->data[0], &statBuffer) == 0)
361 {
362 long modelDataSize = statBuffer.st_size;
363 if (modelDataSize > 0)
364 {
365 std::vector<uint8_t> modelData(modelDataSize);
366 pread(modelCacheHandle[i]->data[0], modelData.data(), modelData.size(), 0);
367 hashValue ^= CacheDataHandlerInstance().Hash(modelData);
368 }
369 }
370 }
371 }
Kevin May42477c12020-03-26 13:34:14 +0000372 }
373 }
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100374 if (hashValue != 0)
375 {
376 CacheDataHandlerInstance().Register(token, hashValue, dataCacheData.size());
377 }
Kevin May42477c12020-03-26 13:34:14 +0000378
379 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100380 return V1_3::ErrorStatus::NONE;
381}
Kevin May42477c12020-03-26 13:34:14 +0000382
Sadik Armagan0a2dfab2021-10-06 16:41:44 +0100383Return<V1_3::ErrorStatus> ArmnnDriverImpl::prepareModelFromCache_1_3(
384 const armnn::IRuntimePtr& runtime,
385 const DriverOptions& options,
386 const android::hardware::hidl_vec<android::hardware::hidl_handle>& modelCacheHandle,
387 const android::hardware::hidl_vec<android::hardware::hidl_handle>& dataCacheHandle,
388 const HidlToken& token,
389 const android::sp<V1_3::IPreparedModelCallback>& cb)
390{
391 ALOGV("ArmnnDriverImpl::prepareModelFromCache_1_3()");
392
393 if (token.size() != ANEURALNETWORKS_BYTE_SIZE_OF_CACHE_TOKEN)
394 {
395 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
396 return V1_3::ErrorStatus::GENERAL_FAILURE;
397 }
398
399 if (cb.get() == nullptr)
400 {
401 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Invalid callback passed to prepareModelFromCache_1_3");
402 return V1_3::ErrorStatus::INVALID_ARGUMENT;
403 }
404
405 if (!runtime)
406 {
407 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Device unavailable");
408 return V1_3::ErrorStatus::DEVICE_UNAVAILABLE;
409 }
410
411 // DataCacheHandle size should always be 1
412 // Arm NN model
413 if (dataCacheHandle.size() != 1)
414 {
415 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
416 return V1_3::ErrorStatus::GENERAL_FAILURE;
417 }
418
419 // Check if model files cached they match the expected value
420 unsigned int numberOfCachedModelFiles = 0;
421 for (auto& backend : options.GetBackends())
422 {
423 numberOfCachedModelFiles += GetNumberOfCacheFiles(backend);
424 }
425 if (modelCacheHandle.size() != numberOfCachedModelFiles)
426 {
427 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
428 return V1_3::ErrorStatus::GENERAL_FAILURE;
429 }
430
431 if (dataCacheHandle[0]->numFds != 1)
432 {
433 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3(): Cannot read from the cache data, numFds != 1.");
434 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
435 return V1_3::ErrorStatus::GENERAL_FAILURE;
436 }
437
438 int dataCacheFileAccessMode = fcntl(dataCacheHandle[0]->data[0], F_GETFL) & O_ACCMODE;
439 if (dataCacheFileAccessMode != O_RDWR)
440 {
441 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
442 return V1_3::ErrorStatus::GENERAL_FAILURE;
443 }
444
445 auto dataSize = CacheDataHandlerInstance().GetCacheSize(token);
446 if (dataSize == 0)
447 {
448 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Invalid data to deserialize!");
449 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
450 return V1_3::ErrorStatus::GENERAL_FAILURE;
451 }
452
453 int offset = 0;
454 {
455 struct stat statBuffer;
456 if (fstat(dataCacheHandle[0]->data[0], &statBuffer) == 0)
457 {
458 unsigned long bufferSize = statBuffer.st_size;
459 if (bufferSize <= 0)
460 {
461 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: Invalid data to deserialize!");
462 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
463 return V1_3::ErrorStatus::GENERAL_FAILURE;
464 }
465 if (bufferSize > dataSize)
466 {
467 offset = bufferSize - dataSize;
468 }
469 }
470 }
471 std::vector<uint8_t> dataCacheData(dataSize);
472 pread(dataCacheHandle[0]->data[0], dataCacheData.data(), dataCacheData.size(), offset);
473 auto hashValue = CacheDataHandlerInstance().Hash(dataCacheData);
474
475 int gpuAccCachedFd = -1;
476 bool saveCachedNetwork = false;
477 if (modelCacheHandle.size() > 0)
478 {
479 unsigned int index = 0;
480 for (auto& backend : options.GetBackends())
481 {
482 // modelCacheHandle size should be equal to numberOfCachedModelFiles
483 // modelCacheHandle vector should be in same order as backends
484 auto numberOfCacheFiles = GetNumberOfCacheFiles(backend);
485 if (numberOfCacheFiles > 0)
486 {
487 if (modelCacheHandle[index]->numFds != 1)
488 {
489 ALOGW(
490 "ArmnnDriverImpl::prepareModelFromCache_1_3(): Cannot read from the model cache, numFds != 1.");
491 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
492 return V1_3::ErrorStatus::GENERAL_FAILURE;
493 }
494 auto cachedFd = modelCacheHandle[index]->data[0];
495
496 int modelCacheFileAccessMode = fcntl(cachedFd, F_GETFL) & O_ACCMODE;
497 if (modelCacheFileAccessMode != O_RDWR)
498 {
499 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
500 return V1_3::ErrorStatus::GENERAL_FAILURE;
501 }
502
503 struct stat statBuffer;
504 if (cachedFd != -1 && fstat(cachedFd, &statBuffer) == 0)
505 {
506 long modelDataSize = statBuffer.st_size;
507 if (modelDataSize > 0)
508 {
509 std::vector<uint8_t> modelData(modelDataSize);
510 pread(cachedFd, modelData.data(), modelData.size(), 0);
511 hashValue ^= CacheDataHandlerInstance().Hash(modelData);
512
513 // For GpuAcc numberOfCachedFiles is 1
514 if (backend == armnn::Compute::GpuAcc)
515 {
516 gpuAccCachedFd = cachedFd;
517 }
518 }
519 }
520 index += numberOfCacheFiles;
521 }
522 }
523 }
524
525 if (!CacheDataHandlerInstance().Validate(token, hashValue))
526 {
527 ALOGW("ArmnnDriverImpl::prepareModelFromCache_1_3: ValidateHash() failed!");
528 cb->notify_1_3(V1_3::ErrorStatus::GENERAL_FAILURE, nullptr);
529 return V1_3::ErrorStatus::GENERAL_FAILURE;
530 }
531
532 // Deserialize the network..
533 auto network = armnnDeserializer::IDeserializer::Create()->CreateNetworkFromBinary(dataCacheData);
534
535 // Optimize the network
536 armnn::IOptimizedNetworkPtr optNet(nullptr, nullptr);
537 armnn::OptimizerOptions OptOptions;
538 OptOptions.m_ReduceFp32ToFp16 = options.GetFp16Enabled();
539 OptOptions.m_ProfilingEnabled = options.IsGpuProfilingEnabled();
540
541 armnn::BackendOptions gpuAcc("GpuAcc",
542 {
543 {"FastMathEnabled", options.IsFastMathEnabled()},
544 {"SaveCachedNetwork", saveCachedNetwork},
545 {"CachedNetworkFilePath", options.GetCachedNetworkFilePath()},
546 {"MLGOTuningFilePath", options.GetClMLGOTunedParametersFile()},
547 {"CachedFileDescriptor", gpuAccCachedFd}
548 });
549
550 armnn::BackendOptions cpuAcc("CpuAcc",
551 {
552 {"FastMathEnabled", options.IsFastMathEnabled()},
553 {"NumberOfThreads", options.GetNumberOfThreads()}
554 });
555 OptOptions.m_ModelOptions.push_back(gpuAcc);
556 OptOptions.m_ModelOptions.push_back(cpuAcc);
557
558 std::vector<std::string> errMessages;
559 try
560 {
561 optNet = armnn::Optimize(*network.get(),
562 options.GetBackends(),
563 runtime->GetDeviceSpec(),
564 OptOptions,
565 errMessages);
566 }
567 catch (std::exception& e)
568 {
569 std::stringstream message;
570 message << "Exception (" << e.what() << ") caught from optimize.";
571 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
572 return V1_3::ErrorStatus::NONE;
573 }
574
575 // Check that the optimized network is valid.
576 if (!optNet)
577 {
578 std::stringstream message;
579 message << "Invalid optimized network";
580 for (const std::string& msg : errMessages)
581 {
582 message << "\n" << msg;
583 }
584 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
585 return V1_3::ErrorStatus::NONE;
586 }
587
588 // Export the optimized network graph to a dot file if an output dump directory
589 // has been specified in the drivers' arguments.
590 std::string dotGraphFileName = ExportNetworkGraphToDotFile(*optNet,
591 options.GetRequestInputsAndOutputsDumpDir());
592
593 // Load it into the runtime.
594 armnn::NetworkId netId = 0;
595 std::string msg;
596 armnn::INetworkProperties networkProperties(options.isAsyncModelExecutionEnabled(),
597 MemorySource::Undefined,
598 MemorySource::Undefined,
599 options.IsGpuProfilingEnabled());
600
601 try
602 {
603 if (runtime->LoadNetwork(netId, move(optNet), msg, networkProperties) != armnn::Status::Success)
604 {
605 return FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, msg, cb);
606 }
607 }
608 catch (std::exception& e)
609 {
610 std::stringstream message;
611 message << "Exception (" << e.what() << ") caught from LoadNetwork.";
612 FailPrepareModel(V1_3::ErrorStatus::GENERAL_FAILURE, message.str(), cb);
613 return V1_3::ErrorStatus::NONE;
614 }
615
616 std::unique_ptr<ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>> preparedModel(
617 new ArmnnPreparedModel_1_3<hal_1_3::HalPolicy>(netId,
618 runtime.get(),
619 options.GetRequestInputsAndOutputsDumpDir(),
620 options.IsGpuProfilingEnabled(),
621 V1_3::Priority::MEDIUM,
622 options.isAsyncModelExecutionEnabled(),
623 options.getNoOfArmnnThreads(),
624 true));
625
626 NotifyCallbackAndCheck(cb, V1_3::ErrorStatus::NONE, preparedModel.release());
Kevin May42477c12020-03-26 13:34:14 +0000627 return V1_3::ErrorStatus::NONE;
628}
629
630Return<void> ArmnnDriverImpl::getCapabilities_1_3(const armnn::IRuntimePtr& runtime,
631 V1_3::IDevice::getCapabilities_1_3_cb cb)
632{
633 ALOGV("hal_1_3::ArmnnDriverImpl::getCapabilities()");
634
635 V1_3::Capabilities capabilities;
636
637 float defaultValue = .1f;
638
639 if (runtime)
640 {
641 capabilities.relaxedFloat32toFloat16PerformanceScalar.execTime =
642 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformanceExecTime, defaultValue);
643
Kevin May2eaa1192020-04-15 16:50:57 +0100644 capabilities.relaxedFloat32toFloat16PerformanceScalar.powerUsage =
645 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformancePowerUsage, defaultValue);
646
647 capabilities.relaxedFloat32toFloat16PerformanceTensor.execTime =
648 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformanceExecTime, defaultValue);
649
Kevin May42477c12020-03-26 13:34:14 +0000650 capabilities.relaxedFloat32toFloat16PerformanceTensor.powerUsage =
651 ParseSystemProperty(g_RelaxedFloat32toFloat16PerformancePowerUsage, defaultValue);
652
Kevin May2eaa1192020-04-15 16:50:57 +0100653 capabilities.ifPerformance.execTime =
654 ParseSystemProperty(g_ifPerformanceExecTime, defaultValue);
655
656 capabilities.ifPerformance.powerUsage =
657 ParseSystemProperty(g_ifPerformancePowerUsage, defaultValue);
658
659 capabilities.whilePerformance.execTime =
660 ParseSystemProperty(g_whilePerformanceExecTime, defaultValue);
661
662 capabilities.whilePerformance.powerUsage =
663 ParseSystemProperty(g_whilePerformancePowerUsage, defaultValue);
664
Kevin May42477c12020-03-26 13:34:14 +0000665 // Set the base value for all operand types
666 capabilities.operandPerformance = nonExtensionOperandPerformance<HalVersion::V1_3>({FLT_MAX, FLT_MAX});
667
668 // Load supported operand types
669 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT32,
670 {
671 .execTime = ParseSystemProperty(g_OperandTypeTensorFloat32PerformanceExecTime, defaultValue),
672 .powerUsage = ParseSystemProperty(g_OperandTypeTensorFloat32PerformancePowerUsage, defaultValue)
673 });
674
675 update(&capabilities.operandPerformance, V1_3::OperandType::FLOAT32,
676 {
677 .execTime = ParseSystemProperty(g_OperandTypeFloat32PerformanceExecTime, defaultValue),
678 .powerUsage = ParseSystemProperty(g_OperandTypeFloat32PerformancePowerUsage, defaultValue)
679 });
680
681 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_FLOAT16,
682 {
683 .execTime = ParseSystemProperty(g_OperandTypeTensorFloat16PerformanceExecTime, defaultValue),
684 .powerUsage = ParseSystemProperty(g_OperandTypeTensorFloat16PerformancePowerUsage, defaultValue)
685 });
686
687 update(&capabilities.operandPerformance, V1_3::OperandType::FLOAT16,
688 {
689 .execTime = ParseSystemProperty(g_OperandTypeFloat16PerformanceExecTime, defaultValue),
690 .powerUsage = ParseSystemProperty(g_OperandTypeFloat16PerformancePowerUsage, defaultValue)
691 });
692
693 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_ASYMM,
694 {
695 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmPerformanceExecTime, defaultValue),
696 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmPerformancePowerUsage, defaultValue)
697 });
698
699 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_SYMM,
700 {
701 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerformanceExecTime, defaultValue),
702 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerformancePowerUsage, defaultValue)
703 });
704 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_ASYMM_SIGNED,
705 {
706 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmSignedPerformanceExecTime,
707 defaultValue),
708 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant8AsymmSignedPerformancePowerUsage,
709 defaultValue)
710 });
711
712 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT16_SYMM,
713 {
714 .execTime = ParseSystemProperty(g_OperandTypeTensorQuant16SymmPerformanceExecTime, defaultValue),
715 .powerUsage = ParseSystemProperty(g_OperandTypeTensorQuant16SymmPerformancePowerUsage, defaultValue)
716 });
717
718 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL,
719 {
720 .execTime =
721 ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerChannelPerformanceExecTime, defaultValue),
722 .powerUsage =
723 ParseSystemProperty(g_OperandTypeTensorQuant8SymmPerChannelPerformancePowerUsage, defaultValue)
724 });
725
726 update(&capabilities.operandPerformance, V1_3::OperandType::TENSOR_INT32,
727 {
728 .execTime = ParseSystemProperty(g_OperandTypeTensorInt32PerformanceExecTime, defaultValue),
729 .powerUsage = ParseSystemProperty(g_OperandTypeTensorInt32PerformancePowerUsage, defaultValue)
730 });
731
732 update(&capabilities.operandPerformance, V1_3::OperandType::INT32,
733 {
734 .execTime = ParseSystemProperty(g_OperandTypeInt32PerformanceExecTime, defaultValue),
735 .powerUsage = ParseSystemProperty(g_OperandTypeInt32PerformancePowerUsage, defaultValue)
736 });
737
738 cb(V1_3::ErrorStatus::NONE, capabilities);
739 }
740 else
741 {
Kevin May2eaa1192020-04-15 16:50:57 +0100742 capabilities.relaxedFloat32toFloat16PerformanceScalar.execTime = 0;
743 capabilities.relaxedFloat32toFloat16PerformanceScalar.powerUsage = 0;
744 capabilities.relaxedFloat32toFloat16PerformanceTensor.execTime = 0;
745 capabilities.relaxedFloat32toFloat16PerformanceTensor.powerUsage = 0;
746 capabilities.ifPerformance.execTime = 0;
747 capabilities.ifPerformance.powerUsage = 0;
748 capabilities.whilePerformance.execTime = 0;
749 capabilities.whilePerformance.powerUsage = 0;
Kevin May42477c12020-03-26 13:34:14 +0000750
751 // Set the base value for all operand types
752 capabilities.operandPerformance = nonExtensionOperandPerformance<HalVersion::V1_3>({0.f, 0.0f});
753
754 cb(V1_3::ErrorStatus::DEVICE_UNAVAILABLE, capabilities);
755 }
756
757 return Void();
758}
759
760} // namespace hal_1_3
761} // namespace armnn_driver