1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/lite/tools/evaluation/utils.h"
17
18 #include "tensorflow/lite/tools/delegates/delegate_provider.h"
19 #if defined(__APPLE__)
20 #include "TargetConditionals.h"
21 #if (TARGET_OS_IPHONE && !TARGET_IPHONE_SIMULATOR) || \
22 (TARGET_OS_OSX && TARGET_CPU_ARM64)
23 // Only enable coreml delegate when using a real iPhone device or Apple Silicon.
24 #define REAL_IPHONE_DEVICE
25 #include "tensorflow/lite/delegates/coreml/coreml_delegate.h"
26 #endif
27 #endif
28
29 #if !defined(_WIN32)
30 #include <dirent.h>
31 #endif
32 #include <sys/stat.h>
33
34 #include <algorithm>
35 #include <fstream>
36 #include <memory>
37 #include <string>
38
39 namespace tflite {
40 namespace evaluation {
41
StripTrailingSlashes(const std::string & path)42 std::string StripTrailingSlashes(const std::string& path) {
43 int end = path.size();
44 while (end > 0 && path[end - 1] == '/') {
45 end--;
46 }
47 return path.substr(0, end);
48 }
49
ReadFileLines(const std::string & file_path,std::vector<std::string> * lines_output)50 bool ReadFileLines(const std::string& file_path,
51 std::vector<std::string>* lines_output) {
52 if (!lines_output) {
53 return false;
54 }
55 std::ifstream stream(file_path.c_str());
56 if (!stream) {
57 return false;
58 }
59 std::string line;
60 while (std::getline(stream, line)) {
61 lines_output->push_back(line);
62 }
63 return true;
64 }
65
66 #if !defined(_WIN32)
GetSortedFileNames(const std::string & directory,std::vector<std::string> * result,const std::unordered_set<std::string> & extensions)67 TfLiteStatus GetSortedFileNames(
68 const std::string& directory, std::vector<std::string>* result,
69 const std::unordered_set<std::string>& extensions) {
70 DIR* dir;
71 struct dirent* ent;
72 if (result == nullptr) {
73 return kTfLiteError;
74 }
75 result->clear();
76 std::string dir_path = StripTrailingSlashes(directory);
77 if ((dir = opendir(dir_path.c_str())) != nullptr) {
78 while ((ent = readdir(dir)) != nullptr) {
79 if (ent->d_type == DT_DIR) continue;
80 std::string filename(std::string(ent->d_name));
81 size_t lastdot = filename.find_last_of('.');
82 std::string ext = lastdot != std::string::npos ? filename.substr(lastdot)
83 : std::string();
84 std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
85 if (!extensions.empty() && extensions.find(ext) == extensions.end()) {
86 continue;
87 }
88 result->emplace_back(dir_path + "/" + filename);
89 }
90 closedir(dir);
91 } else {
92 return kTfLiteError;
93 }
94 std::sort(result->begin(), result->end());
95 return kTfLiteOk;
96 }
97 #endif
98
CreateNNAPIDelegate()99 TfLiteDelegatePtr CreateNNAPIDelegate() {
100 #if defined(__ANDROID__)
101 return TfLiteDelegatePtr(
102 NnApiDelegate(),
103 // NnApiDelegate() returns a singleton, so provide a no-op deleter.
104 [](TfLiteDelegate*) {});
105 #else
106 return tools::CreateNullDelegate();
107 #endif // defined(__ANDROID__)
108 }
109
CreateNNAPIDelegate(StatefulNnApiDelegate::Options options)110 TfLiteDelegatePtr CreateNNAPIDelegate(StatefulNnApiDelegate::Options options) {
111 #if defined(__ANDROID__)
112 return TfLiteDelegatePtr(
113 new StatefulNnApiDelegate(options), [](TfLiteDelegate* delegate) {
114 delete reinterpret_cast<StatefulNnApiDelegate*>(delegate);
115 });
116 #else
117 return tools::CreateNullDelegate();
118 #endif // defined(__ANDROID__)
119 }
120
121 #if TFLITE_SUPPORTS_GPU_DELEGATE
CreateGPUDelegate(TfLiteGpuDelegateOptionsV2 * options)122 TfLiteDelegatePtr CreateGPUDelegate(TfLiteGpuDelegateOptionsV2* options) {
123 return TfLiteDelegatePtr(TfLiteGpuDelegateV2Create(options),
124 &TfLiteGpuDelegateV2Delete);
125 }
126 #endif // TFLITE_SUPPORTS_GPU_DELEGATE
127
CreateGPUDelegate()128 TfLiteDelegatePtr CreateGPUDelegate() {
129 #if TFLITE_SUPPORTS_GPU_DELEGATE
130 TfLiteGpuDelegateOptionsV2 options = TfLiteGpuDelegateOptionsV2Default();
131 options.inference_priority1 = TFLITE_GPU_INFERENCE_PRIORITY_MIN_LATENCY;
132 options.inference_preference =
133 TFLITE_GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED;
134
135 return CreateGPUDelegate(&options);
136 #else
137 return tools::CreateNullDelegate();
138 #endif // TFLITE_SUPPORTS_GPU_DELEGATE
139 }
140
CreateHexagonDelegate(const std::string & library_directory_path,bool profiling)141 TfLiteDelegatePtr CreateHexagonDelegate(
142 const std::string& library_directory_path, bool profiling) {
143 #if TFLITE_ENABLE_HEXAGON
144 TfLiteHexagonDelegateOptions options = {0};
145 options.print_graph_profile = profiling;
146 return CreateHexagonDelegate(&options, library_directory_path);
147 #else
148 return tools::CreateNullDelegate();
149 #endif // TFLITE_ENABLE_HEXAGON
150 }
151
152 #if TFLITE_ENABLE_HEXAGON
CreateHexagonDelegate(const TfLiteHexagonDelegateOptions * options,const std::string & library_directory_path)153 TfLiteDelegatePtr CreateHexagonDelegate(
154 const TfLiteHexagonDelegateOptions* options,
155 const std::string& library_directory_path) {
156 if (library_directory_path.empty()) {
157 TfLiteHexagonInit();
158 } else {
159 TfLiteHexagonInitWithPath(library_directory_path.c_str());
160 }
161
162 TfLiteDelegate* delegate = TfLiteHexagonDelegateCreate(options);
163 if (!delegate) {
164 TfLiteHexagonTearDown();
165 return tools::CreateNullDelegate();
166 }
167 return TfLiteDelegatePtr(delegate, [](TfLiteDelegate* delegate) {
168 TfLiteHexagonDelegateDelete(delegate);
169 TfLiteHexagonTearDown();
170 });
171 }
172 #endif
173
174 #if defined(__s390x__) || defined(TFLITE_WITHOUT_XNNPACK)
CreateXNNPACKDelegate(int num_threads)175 TfLiteDelegatePtr CreateXNNPACKDelegate(int num_threads) {
176 return tools::CreateNullDelegate();
177 }
178 #else
CreateXNNPACKDelegate()179 TfLiteDelegatePtr CreateXNNPACKDelegate() {
180 TfLiteXNNPackDelegateOptions xnnpack_options =
181 TfLiteXNNPackDelegateOptionsDefault();
182 return CreateXNNPACKDelegate(&xnnpack_options);
183 }
184
CreateXNNPACKDelegate(const TfLiteXNNPackDelegateOptions * xnnpack_options)185 TfLiteDelegatePtr CreateXNNPACKDelegate(
186 const TfLiteXNNPackDelegateOptions* xnnpack_options) {
187 auto xnnpack_delegate = TfLiteXNNPackDelegateCreate(xnnpack_options);
188 return TfLiteDelegatePtr(xnnpack_delegate, [](TfLiteDelegate* delegate) {
189 TfLiteXNNPackDelegateDelete(delegate);
190 });
191 }
192
CreateXNNPACKDelegate(int num_threads)193 TfLiteDelegatePtr CreateXNNPACKDelegate(int num_threads) {
194 auto opts = TfLiteXNNPackDelegateOptionsDefault();
195 // Note that we don't want to use the thread pool for num_threads == 1.
196 opts.num_threads = num_threads > 1 ? num_threads : 0;
197 return CreateXNNPACKDelegate(&opts);
198 }
199
CreateCoreMlDelegate()200 TfLiteDelegatePtr CreateCoreMlDelegate() {
201 #ifdef REAL_IPHONE_DEVICE
202 TfLiteCoreMlDelegateOptions coreml_options = {
203 .enabled_devices = TfLiteCoreMlDelegateAllDevices};
204 TfLiteDelegate* delegate = TfLiteCoreMlDelegateCreate(&coreml_options);
205 if (!delegate) {
206 return tools::CreateNullDelegate();
207 }
208 return TfLiteDelegatePtr(delegate, &TfLiteCoreMlDelegateDelete);
209 #else
210 return tools::CreateNullDelegate();
211 #endif
212 }
213
214 #endif
215 } // namespace evaluation
216 } // namespace tflite
217