• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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