1 /* Copyright 2020 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 #include "tensorflow/lite/experimental/acceleration/configuration/proto_to_flatbuffer.h"
16
17 #include <cstdint>
18
19 #include "flatbuffers/flatbuffers.h" // from @flatbuffers
20 #include "tensorflow/lite/experimental/acceleration/configuration/configuration.pb.h"
21 #include "tensorflow/lite/experimental/acceleration/configuration/configuration_generated.h"
22 #include "tensorflow/lite/minimal_logging.h"
23
24 namespace tflite {
25
26 using ::flatbuffers::FlatBufferBuilder;
27 using ::flatbuffers::Offset;
28 using ::flatbuffers::String;
29 using ::flatbuffers::Vector;
30
ConvertExecutionPreference(proto::ExecutionPreference preference)31 ExecutionPreference ConvertExecutionPreference(
32 proto::ExecutionPreference preference) {
33 switch (preference) {
34 case proto::ExecutionPreference::ANY:
35 return ExecutionPreference_ANY;
36 case proto::ExecutionPreference::LOW_LATENCY:
37 return ExecutionPreference_LOW_LATENCY;
38 case proto::ExecutionPreference::LOW_POWER:
39 return ExecutionPreference_LOW_POWER;
40 case proto::ExecutionPreference::FORCE_CPU:
41 return ExecutionPreference_FORCE_CPU;
42 }
43 TFLITE_LOG_PROD(TFLITE_LOG_ERROR,
44 "Unexpected value for ExecutionPreference: %d", preference);
45 return ExecutionPreference_ANY;
46 }
47
ConvertDelegate(proto::Delegate delegate)48 Delegate ConvertDelegate(proto::Delegate delegate) {
49 switch (delegate) {
50 case proto::Delegate::NONE:
51 return Delegate_NONE;
52 case proto::Delegate::NNAPI:
53 return Delegate_NNAPI;
54 case proto::Delegate::GPU:
55 return Delegate_GPU;
56 case proto::Delegate::HEXAGON:
57 return Delegate_HEXAGON;
58 case proto::Delegate::XNNPACK:
59 return Delegate_XNNPACK;
60 case proto::Delegate::EDGETPU:
61 return Delegate_EDGETPU;
62 case proto::Delegate::EDGETPU_CORAL:
63 return Delegate_EDGETPU_CORAL;
64 case proto::Delegate::CORE_ML:
65 return Delegate_CORE_ML;
66 }
67 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Unexpected value for Delegate: %d",
68 delegate);
69 return Delegate_NONE;
70 }
71
ConvertNNAPIExecutionPreference(proto::NNAPIExecutionPreference preference)72 NNAPIExecutionPreference ConvertNNAPIExecutionPreference(
73 proto::NNAPIExecutionPreference preference) {
74 switch (preference) {
75 case proto::NNAPIExecutionPreference::UNDEFINED:
76 return NNAPIExecutionPreference_UNDEFINED;
77 case proto::NNAPIExecutionPreference::NNAPI_LOW_POWER:
78 return NNAPIExecutionPreference_NNAPI_LOW_POWER;
79 case proto::NNAPIExecutionPreference::NNAPI_FAST_SINGLE_ANSWER:
80 return NNAPIExecutionPreference_NNAPI_FAST_SINGLE_ANSWER;
81 case proto::NNAPIExecutionPreference::NNAPI_SUSTAINED_SPEED:
82 return NNAPIExecutionPreference_NNAPI_SUSTAINED_SPEED;
83 }
84 TFLITE_LOG_PROD(TFLITE_LOG_ERROR,
85 "Unexpected value for NNAPIExecutionPreference: %d",
86 preference);
87 return NNAPIExecutionPreference_UNDEFINED;
88 }
89
ConvertNNAPIExecutionPriority(proto::NNAPIExecutionPriority priority)90 NNAPIExecutionPriority ConvertNNAPIExecutionPriority(
91 proto::NNAPIExecutionPriority priority) {
92 switch (priority) {
93 case proto::NNAPIExecutionPriority::NNAPI_PRIORITY_UNDEFINED:
94 return NNAPIExecutionPriority_NNAPI_PRIORITY_UNDEFINED;
95 case proto::NNAPIExecutionPriority::NNAPI_PRIORITY_LOW:
96 return NNAPIExecutionPriority_NNAPI_PRIORITY_LOW;
97 case proto::NNAPIExecutionPriority::NNAPI_PRIORITY_MEDIUM:
98 return NNAPIExecutionPriority_NNAPI_PRIORITY_MEDIUM;
99 case proto::NNAPIExecutionPriority::NNAPI_PRIORITY_HIGH:
100 return NNAPIExecutionPriority_NNAPI_PRIORITY_HIGH;
101 }
102 TFLITE_LOG_PROD(TFLITE_LOG_ERROR,
103 "Unexpected value for NNAPIExecutionPriority: %d", priority);
104 return NNAPIExecutionPriority_NNAPI_PRIORITY_UNDEFINED;
105 }
106
ConvertGPUBackend(proto::GPUBackend backend)107 GPUBackend ConvertGPUBackend(proto::GPUBackend backend) {
108 switch (backend) {
109 case proto::GPUBackend::UNSET:
110 return GPUBackend_UNSET;
111 case proto::GPUBackend::OPENCL:
112 return GPUBackend_OPENCL;
113 case proto::GPUBackend::OPENGL:
114 return GPUBackend_OPENGL;
115 }
116 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Unexpected value for GPUBackend: %d",
117 backend);
118 return GPUBackend_UNSET;
119 }
120
ConvertGPUInferenceUsage(proto::GPUInferenceUsage preference)121 GPUInferenceUsage ConvertGPUInferenceUsage(
122 proto::GPUInferenceUsage preference) {
123 switch (preference) {
124 case proto::GPUInferenceUsage::GPU_INFERENCE_PREFERENCE_FAST_SINGLE_ANSWER:
125 return GPUInferenceUsage_GPU_INFERENCE_PREFERENCE_FAST_SINGLE_ANSWER;
126 case proto::GPUInferenceUsage::GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED:
127 return GPUInferenceUsage_GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED;
128 }
129 TFLITE_LOG_PROD(TFLITE_LOG_ERROR,
130 "Unexpected value for GPUInferenceUsage: %d", preference);
131 return GPUInferenceUsage_GPU_INFERENCE_PREFERENCE_FAST_SINGLE_ANSWER;
132 }
133
ConvertGPUInferencePriority(proto::GPUInferencePriority priority)134 GPUInferencePriority ConvertGPUInferencePriority(
135 proto::GPUInferencePriority priority) {
136 switch (priority) {
137 case proto::GPUInferencePriority::GPU_PRIORITY_AUTO:
138 return GPUInferencePriority_GPU_PRIORITY_AUTO;
139 case proto::GPUInferencePriority::GPU_PRIORITY_MAX_PRECISION:
140 return GPUInferencePriority_GPU_PRIORITY_MAX_PRECISION;
141 case proto::GPUInferencePriority::GPU_PRIORITY_MIN_LATENCY:
142 return GPUInferencePriority_GPU_PRIORITY_MIN_LATENCY;
143 case proto::GPUInferencePriority::GPU_PRIORITY_MIN_MEMORY_USAGE:
144 return GPUInferencePriority_GPU_PRIORITY_MIN_MEMORY_USAGE;
145 }
146 TFLITE_LOG_PROD(TFLITE_LOG_ERROR,
147 "Unexpected value for GPUInferencePriority: %d", priority);
148 return GPUInferencePriority_GPU_PRIORITY_AUTO;
149 }
150
ConvertEdgeTpuPowerState(proto::EdgeTpuPowerState state)151 EdgeTpuPowerState ConvertEdgeTpuPowerState(proto::EdgeTpuPowerState state) {
152 switch (state) {
153 case proto::EdgeTpuPowerState::UNDEFINED_POWERSTATE:
154 return EdgeTpuPowerState_UNDEFINED_POWERSTATE;
155 case proto::EdgeTpuPowerState::TPU_CORE_OFF:
156 return EdgeTpuPowerState_TPU_CORE_OFF;
157 case proto::EdgeTpuPowerState::READY:
158 return EdgeTpuPowerState_READY;
159 case proto::EdgeTpuPowerState::ACTIVE_MIN_POWER:
160 return EdgeTpuPowerState_ACTIVE_MIN_POWER;
161 case proto::EdgeTpuPowerState::ACTIVE_VERY_LOW_POWER:
162 return EdgeTpuPowerState_ACTIVE_VERY_LOW_POWER;
163 case proto::EdgeTpuPowerState::ACTIVE_LOW_POWER:
164 return EdgeTpuPowerState_ACTIVE_LOW_POWER;
165 case proto::EdgeTpuPowerState::ACTIVE:
166 return EdgeTpuPowerState_ACTIVE;
167 case proto::EdgeTpuPowerState::OVER_DRIVE:
168 return EdgeTpuPowerState_OVER_DRIVE;
169 }
170 TFLITE_LOG_PROD(TFLITE_LOG_ERROR,
171 "Unexpected value for EdgeTpuSettings::PowerState: %d",
172 state);
173 return EdgeTpuPowerState_UNDEFINED_POWERSTATE;
174 }
175
ConvertFallbackSettings(const proto::FallbackSettings & settings,FlatBufferBuilder * builder)176 Offset<FallbackSettings> ConvertFallbackSettings(
177 const proto::FallbackSettings& settings, FlatBufferBuilder* builder) {
178 return CreateFallbackSettings(
179 *builder, /*allow_automatic_fallback_on_compilation_error=*/
180 settings.allow_automatic_fallback_on_compilation_error(),
181 /*allow_automatic_fallback_on_execution_error=*/
182 settings.allow_automatic_fallback_on_execution_error());
183 }
184
ConvertNNAPISettings(const proto::NNAPISettings & settings,FlatBufferBuilder * builder)185 Offset<NNAPISettings> ConvertNNAPISettings(const proto::NNAPISettings& settings,
186 FlatBufferBuilder* builder) {
187 return CreateNNAPISettings(
188 *builder,
189 /*accelerator_name=*/builder->CreateString(settings.accelerator_name()),
190 /*cache_directory=*/builder->CreateString(settings.cache_directory()),
191 /*model_token=*/builder->CreateString(settings.model_token()),
192 ConvertNNAPIExecutionPreference(settings.execution_preference()),
193 /*no_of_nnapi_instances_to_cache=*/
194 settings.no_of_nnapi_instances_to_cache(),
195 ConvertFallbackSettings(settings.fallback_settings(), builder),
196 /*allow_nnapi_cpu_on_android_10_plus=*/
197 settings.allow_nnapi_cpu_on_android_10_plus(),
198 ConvertNNAPIExecutionPriority(settings.execution_priority()),
199 /*allow_dynamic_dimensions=*/
200 settings.allow_dynamic_dimensions(),
201 /*allow_fp16_precision_for_fp32=*/
202 settings.allow_fp16_precision_for_fp32(),
203 /*use_burst_computation=*/
204 settings.use_burst_computation(),
205 /*support_library_handle=*/
206 settings.support_library_handle());
207 }
208
ConvertGPUSettings(const proto::GPUSettings & settings,FlatBufferBuilder * builder)209 Offset<GPUSettings> ConvertGPUSettings(const proto::GPUSettings& settings,
210 FlatBufferBuilder* builder) {
211 return CreateGPUSettings(
212 *builder,
213 /*is_precision_loss_allowed=*/settings.is_precision_loss_allowed(),
214 /*enable_quantized_inference=*/settings.enable_quantized_inference(),
215 ConvertGPUBackend(settings.force_backend()),
216 ConvertGPUInferencePriority(settings.inference_priority1()),
217 ConvertGPUInferencePriority(settings.inference_priority2()),
218 ConvertGPUInferencePriority(settings.inference_priority3()),
219 ConvertGPUInferenceUsage(settings.inference_preference()),
220 /*cache_directory=*/builder->CreateString(settings.cache_directory()),
221 /*model_token=*/builder->CreateString(settings.model_token()));
222 }
223
ConvertHexagonSettings(const proto::HexagonSettings & settings,FlatBufferBuilder * builder)224 Offset<HexagonSettings> ConvertHexagonSettings(
225 const proto::HexagonSettings& settings, FlatBufferBuilder* builder) {
226 return CreateHexagonSettings(
227 *builder,
228 /*debug_level=*/settings.debug_level(),
229 /*powersave_level=*/settings.powersave_level(),
230 /*print_graph_profile=*/settings.print_graph_profile(),
231 /*print_graph_debug=*/settings.print_graph_debug());
232 }
233
ConvertXNNPackSettings(const proto::XNNPackSettings & settings,FlatBufferBuilder * builder)234 Offset<XNNPackSettings> ConvertXNNPackSettings(
235 const proto::XNNPackSettings& settings, FlatBufferBuilder* builder) {
236 return CreateXNNPackSettings(
237 *builder,
238 /*num_threads=*/settings.num_threads(),
239 /*flags=*/tflite::XNNPackFlags(settings.flags()));
240 }
241
ConvertCoreMLSettings(const proto::CoreMLSettings & settings,FlatBufferBuilder * builder)242 Offset<CoreMLSettings> ConvertCoreMLSettings(
243 const proto::CoreMLSettings& settings, FlatBufferBuilder* builder) {
244 tflite::CoreMLSettings_::EnabledDevices enabled_devices =
245 tflite::CoreMLSettings_::EnabledDevices_DEVICES_ALL;
246 switch (settings.enabled_devices()) {
247 case proto::CoreMLSettings::DEVICES_ALL:
248 enabled_devices = tflite::CoreMLSettings_::EnabledDevices_DEVICES_ALL;
249 break;
250 case proto::CoreMLSettings::DEVICES_WITH_NEURAL_ENGINE:
251 enabled_devices =
252 tflite::CoreMLSettings_::EnabledDevices_DEVICES_WITH_NEURAL_ENGINE;
253 break;
254 default:
255 TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Invalid devices enum: %d",
256 settings.enabled_devices());
257 }
258
259 return CreateCoreMLSettings(
260 *builder, enabled_devices, settings.coreml_version(),
261 settings.max_delegated_partitions(), settings.min_nodes_per_partition());
262 }
263
ConvertCPUSettings(const proto::CPUSettings & settings,FlatBufferBuilder * builder)264 Offset<CPUSettings> ConvertCPUSettings(const proto::CPUSettings& settings,
265 FlatBufferBuilder* builder) {
266 return CreateCPUSettings(*builder,
267 /*num_threads=*/settings.num_threads());
268 }
269
ConvertEdgeTpuDeviceSpec(FlatBufferBuilder * builder,const proto::EdgeTpuDeviceSpec & device_spec)270 Offset<tflite::EdgeTpuDeviceSpec> ConvertEdgeTpuDeviceSpec(
271 FlatBufferBuilder* builder, const proto::EdgeTpuDeviceSpec& device_spec) {
272 Offset<Vector<Offset<String>>> device_paths_fb = 0;
273 if (device_spec.device_paths_size() > 0) {
274 std::vector<Offset<String>> device_paths;
275 for (const auto& device_path : device_spec.device_paths()) {
276 auto device_path_fb = builder->CreateString(device_path);
277 device_paths.push_back(device_path_fb);
278 }
279 device_paths_fb = builder->CreateVector(device_paths);
280 }
281
282 return tflite::CreateEdgeTpuDeviceSpec(
283 *builder,
284 static_cast<tflite::EdgeTpuDeviceSpec_::PlatformType>(
285 device_spec.platform_type()),
286 device_spec.num_chips(), device_paths_fb, device_spec.chip_family());
287 }
288
ConvertEdgeTpuSettings(const proto::EdgeTpuSettings & settings,FlatBufferBuilder * builder)289 Offset<EdgeTpuSettings> ConvertEdgeTpuSettings(
290 const proto::EdgeTpuSettings& settings, FlatBufferBuilder* builder) {
291 Offset<Vector<Offset<tflite::EdgeTpuInactivePowerConfig>>>
292 inactive_power_configs = 0;
293
294 // Uses std vector to first construct the list and creates the flatbuffer
295 // offset from it later.
296 std::vector<Offset<tflite::EdgeTpuInactivePowerConfig>>
297 inactive_power_configs_std;
298 if (settings.inactive_power_configs_size() > 0) {
299 for (const auto& config : settings.inactive_power_configs()) {
300 inactive_power_configs_std.push_back(
301 tflite::CreateEdgeTpuInactivePowerConfig(
302 *builder,
303 static_cast<tflite::EdgeTpuPowerState>(
304 config.inactive_power_state()),
305 config.inactive_timeout_us()));
306 }
307
308 inactive_power_configs =
309 builder->CreateVector<Offset<tflite::EdgeTpuInactivePowerConfig>>(
310 inactive_power_configs_std);
311 }
312
313 Offset<tflite::EdgeTpuDeviceSpec> edgetpu_device_spec = 0;
314 if (settings.has_edgetpu_device_spec()) {
315 edgetpu_device_spec =
316 ConvertEdgeTpuDeviceSpec(builder, settings.edgetpu_device_spec());
317 }
318
319 Offset<String> model_token = 0;
320 if (settings.has_model_token()) {
321 model_token = builder->CreateString(settings.model_token());
322 }
323
324 return CreateEdgeTpuSettings(
325 *builder, ConvertEdgeTpuPowerState(settings.inference_power_state()),
326 inactive_power_configs, settings.inference_priority(),
327 edgetpu_device_spec, model_token,
328 static_cast<tflite::EdgeTpuSettings_::FloatTruncationType>(
329 settings.float_truncation_type()),
330 static_cast<tflite::EdgeTpuSettings_::QosClass>(settings.qos_class()));
331 }
332
ConvertCoralSettings(const proto::CoralSettings & settings,FlatBufferBuilder * builder)333 Offset<CoralSettings> ConvertCoralSettings(const proto::CoralSettings& settings,
334 FlatBufferBuilder* builder) {
335 return CreateCoralSettings(
336 *builder, builder->CreateString(settings.device()),
337 static_cast<tflite::CoralSettings_::Performance>(settings.performance()),
338 settings.usb_always_dfu(), settings.usb_max_bulk_in_queue_length());
339 }
340
ConvertTfliteSettings(const proto::TFLiteSettings & settings,FlatBufferBuilder * builder)341 Offset<TFLiteSettings> ConvertTfliteSettings(
342 const proto::TFLiteSettings& settings, FlatBufferBuilder* builder) {
343 return CreateTFLiteSettings(
344 *builder, ConvertDelegate(settings.delegate()),
345 ConvertNNAPISettings(settings.nnapi_settings(), builder),
346 ConvertGPUSettings(settings.gpu_settings(), builder),
347 ConvertHexagonSettings(settings.hexagon_settings(), builder),
348 ConvertXNNPackSettings(settings.xnnpack_settings(), builder),
349 ConvertCoreMLSettings(settings.coreml_settings(), builder),
350 ConvertCPUSettings(settings.cpu_settings(), builder),
351 /*max_delegated_partitions=*/settings.max_delegated_partitions(),
352 ConvertEdgeTpuSettings(settings.edgetpu_settings(), builder),
353 ConvertCoralSettings(settings.coral_settings(), builder),
354 ConvertFallbackSettings(settings.fallback_settings(), builder),
355 settings.disable_default_delegates());
356 }
357
ConvertModelFile(const proto::ModelFile & model_file,FlatBufferBuilder * builder)358 Offset<ModelFile> ConvertModelFile(const proto::ModelFile& model_file,
359 FlatBufferBuilder* builder) {
360 return CreateModelFile(*builder, builder->CreateString(model_file.filename()),
361 model_file.fd(), model_file.offset(),
362 model_file.length());
363 }
364
ConvertBenchmarkStoragePaths(const proto::BenchmarkStoragePaths & storage_paths,FlatBufferBuilder * builder)365 Offset<BenchmarkStoragePaths> ConvertBenchmarkStoragePaths(
366 const proto::BenchmarkStoragePaths& storage_paths,
367 FlatBufferBuilder* builder) {
368 return CreateBenchmarkStoragePaths(
369 *builder, builder->CreateString(storage_paths.storage_file_path()),
370 builder->CreateString(storage_paths.data_directory_path()));
371 }
372
ConvertMinibenchmarkSettings(const proto::MinibenchmarkSettings & settings,FlatBufferBuilder * builder)373 Offset<MinibenchmarkSettings> ConvertMinibenchmarkSettings(
374 const proto::MinibenchmarkSettings& settings, FlatBufferBuilder* builder) {
375 Offset<Vector<Offset<TFLiteSettings>>> settings_to_test = 0;
376 std::vector<Offset<TFLiteSettings>> settings_to_test_vec;
377 if (settings.settings_to_test_size() > 0) {
378 for (const auto& one : settings.settings_to_test()) {
379 settings_to_test_vec.push_back(ConvertTfliteSettings(one, builder));
380 }
381 settings_to_test =
382 builder->CreateVector<Offset<TFLiteSettings>>(settings_to_test_vec);
383 }
384
385 return CreateMinibenchmarkSettings(
386 *builder, settings_to_test,
387 ConvertModelFile(settings.model_file(), builder),
388 ConvertBenchmarkStoragePaths(settings.storage_paths(), builder));
389 }
390
ConvertFromProto(const proto::ComputeSettings & proto_settings,FlatBufferBuilder * builder)391 const ComputeSettings* ConvertFromProto(
392 const proto::ComputeSettings& proto_settings, FlatBufferBuilder* builder) {
393 auto settings = CreateComputeSettings(
394 *builder, ConvertExecutionPreference(proto_settings.preference()),
395 ConvertTfliteSettings(proto_settings.tflite_settings(), builder),
396 builder->CreateString(proto_settings.model_namespace_for_statistics()),
397 builder->CreateString(proto_settings.model_identifier_for_statistics()),
398 ConvertMinibenchmarkSettings(proto_settings.settings_to_test_locally(),
399 builder));
400 return flatbuffers::GetTemporaryPointer(*builder, settings);
401 }
402
ConvertFromProto(const proto::MinibenchmarkSettings & proto_settings,flatbuffers::FlatBufferBuilder * builder)403 const MinibenchmarkSettings* ConvertFromProto(
404 const proto::MinibenchmarkSettings& proto_settings,
405 flatbuffers::FlatBufferBuilder* builder) {
406 auto settings = ConvertMinibenchmarkSettings(proto_settings, builder);
407 return flatbuffers::GetTemporaryPointer(*builder, settings);
408 }
409
410 } // namespace tflite
411