• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright 2022 Huawei Technologies Co., Ltd
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/litert/delegate/nnapi/nnapi_implementation.h"
18 #include <dlfcn.h>
19 #include <fcntl.h>
20 #include <sys/mman.h>
21 #include <sys/stat.h>
22 #include <sys/system_properties.h>
23 #include <unistd.h>
24 #include <string>
25 #include <algorithm>
26 #include <cstdlib>
27 #include "src/common/log_adapter.h"
28 #include "include/errorcode.h"
29 
30 namespace mindspore {
31 namespace lite {
32 namespace {
GetAndroidSdkVersion()33 int32_t GetAndroidSdkVersion() {
34   const char *sdk_prop = "ro.build.version.sdk";
35   char prop_value[PROP_VALUE_MAX];
36   (void)__system_property_get(sdk_prop, prop_value);
37   std::function<bool(const std::string)> is_valid_num = [](const std::string &str) {
38     return !str.empty() && std::all_of(str.begin(), str.end(), ::isdigit);
39   };
40   int sdk_version = 0;
41   if (is_valid_num(std::string(prop_value))) {
42     sdk_version = std::stoi(std::string(prop_value));
43   }
44   return sdk_version;
45 }
46 
LoadNNAPIFunction(void * handle,const char * name,bool optional)47 void *LoadNNAPIFunction(void *handle, const char *name, bool optional) {
48   if (handle == nullptr) {
49     return nullptr;
50   }
51   void *fn = dlsym(handle, name);
52   if (fn == nullptr && !optional) {
53     MS_LOG(ERROR) << "Load NNAPI function failed: " << name;
54   }
55   return fn;
56 }
57 
58 #define LOAD_NNAPI_FUNCTION(handle, name) \
59   nnapi.name = reinterpret_cast<name##_fn>(LoadNNAPIFunction(handle, #name, false));
60 
61 #define LOAD_NNAPI_FUNCTION_OPTIONAL(handle, name) \
62   nnapi.name = reinterpret_cast<name##_fn>(LoadNNAPIFunction(handle, #name, true));
63 
LoadNNAPI()64 const NNAPI LoadNNAPI() {
65   NNAPI nnapi = {};
66   nnapi.android_sdk_version = 0;
67 
68   void *libneuralnetworks = nullptr;
69   // instances of nn api RT
70   auto get_dl_error = []() -> std::string {
71     auto error = dlerror();
72     return error == nullptr ? "" : error;
73   };
74   static const char nnapi_library_name[] = "libneuralnetworks.so";
75   libneuralnetworks = dlopen(nnapi_library_name, RTLD_LAZY | RTLD_LOCAL);
76   if (libneuralnetworks == nullptr) {
77     auto error = get_dl_error();
78     MS_LOG(ERROR) << "dlopen " << nnapi_library_name << " failed, error: " << error;
79     nnapi.nnapi_exists = false;
80     return nnapi;
81   }
82   nnapi.nnapi_exists = true;
83   nnapi.android_sdk_version = GetAndroidSdkVersion();
84   if (nnapi.android_sdk_version < ANEURALNETWORKS_FEATURE_LEVEL_1) {
85     MS_LOG(ERROR) << "Android NNAPI requires android sdk version to be at least 27";
86     nnapi.nnapi_exists = false;
87     return nnapi;
88   }
89 
90   // NNAPI level 1 (API 27) methods.
91   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_createFromFd);
92   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksMemory_free);
93   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_create);
94   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_free);
95   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_finish);
96   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperand);
97   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_setOperandValue);
98   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_setOperandValueFromMemory);
99   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperation);
100   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksModel_identifyInputsAndOutputs);
101   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_create);
102   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_free);
103   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_setPreference);
104   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_finish);
105   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_create);
106   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_free);
107   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInput);
108   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInputFromMemory);
109   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setOutput);
110   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setOutputFromMemory);
111   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_startCompute);
112   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_wait);
113   LOAD_NNAPI_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_free);
114 
115   // NNAPI level 2 (API 28) methods.
116   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_relaxComputationFloat32toFloat16);
117 
118   // NNAPI level 3 (API 29) methods.
119   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getDeviceCount);
120   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getDevice);
121   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getName);
122   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getType);
123   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getVersion);
124   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_getFeatureLevel);
125   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_getSupportedOperationsForDevices);
126   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_createForDevices);
127   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_setCaching);
128   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_compute);
129   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_getOutputOperandRank);
130   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_getOutputOperandDimensions);
131   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksBurst_create);
132   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksBurst_free);
133   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_burstCompute);
134   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemory_createFromAHardwareBuffer);
135   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setMeasureTiming);
136   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_getDuration);
137   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_setOperandSymmPerChannelQuantParams);
138 
139   // NNAPI level 4 (API 30) methods.
140   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_create);
141   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_free);
142   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_addInputRole);
143   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_addOutputRole);
144   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_setDimensions);
145   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemoryDesc_finish);
146   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemory_createFromDesc);
147   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksMemory_copy);
148   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksDevice_wait);
149   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_setOperandValueFromModel);
150   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_setPriority);
151   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_setTimeout);
152   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setTimeout);
153   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setLoopTimeout);
154   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getDefaultLoopTimeout);
155   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getMaximumLoopTimeout);
156   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksEvent_createFromSyncFenceFd);
157   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksEvent_getSyncFenceFd);
158   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_startComputeWithDependencies);
159 
160   // NNAPI level 5 (API 31) methods.
161   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworks_getRuntimeFeatureLevel);
162   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_enableInputAndOutputPadding);
163   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_getPreferredMemoryAlignmentForInput);
164   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_getPreferredMemoryPaddingForInput);
165   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_getPreferredMemoryAlignmentForOutput);
166   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksCompilation_getPreferredMemoryPaddingForOutput);
167   LOAD_NNAPI_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksExecution_setReusable);
168 
169   return nnapi;
170 }
171 }  // namespace
172 
NNAPIImplementation()173 const NNAPI *NNAPIImplementation() {
174   static const NNAPI nnapi = LoadNNAPI();
175   return &nnapi;
176 }
177 }  // namespace lite
178 }  // namespace mindspore
179