From 9c6a53d7465f6fc8145e80b724d232598f355753 Mon Sep 17 00:00:00 2001 From: "A. Unique TensorFlower" Date: Mon, 30 Nov 2020 02:24:34 -0800 Subject: [PATCH] Make `ComputeSettings` proto to flatbuffer conversion tool portable. PiperOrigin-RevId: 344773745 Change-Id: Id5e87824abb2cb880ce87804a6a24fd3e8391f25 --- .../acceleration/configuration/BUILD | 2 - .../configuration/proto_to_flatbuffer.cc | 235 +++++++++++++++--- .../configuration/proto_to_flatbuffer.h | 9 +- 3 files changed, 207 insertions(+), 39 deletions(-) diff --git a/tensorflow/lite/experimental/acceleration/configuration/BUILD b/tensorflow/lite/experimental/acceleration/configuration/BUILD index 1bfd2494fe1..023db7b1c74 100644 --- a/tensorflow/lite/experimental/acceleration/configuration/BUILD +++ b/tensorflow/lite/experimental/acceleration/configuration/BUILD @@ -78,14 +78,12 @@ flatbuffer_java_library( cc_library( name = "proto_to_flatbuffer", srcs = [ - "configuration_fbs_contents-inl.h", "proto_to_flatbuffer.cc", ], hdrs = ["proto_to_flatbuffer.h"], deps = [ ":configuration_cc_proto", ":configuration_fbs", - "//tensorflow/core/platform:protobuf", "//tensorflow/lite:minimal_logging", "@flatbuffers", ], diff --git a/tensorflow/lite/experimental/acceleration/configuration/proto_to_flatbuffer.cc b/tensorflow/lite/experimental/acceleration/configuration/proto_to_flatbuffer.cc index 709bb70ca70..7478722880e 100644 --- a/tensorflow/lite/experimental/acceleration/configuration/proto_to_flatbuffer.cc +++ b/tensorflow/lite/experimental/acceleration/configuration/proto_to_flatbuffer.cc @@ -14,45 +14,216 @@ limitations under the License. ==============================================================================*/ #include "tensorflow/lite/experimental/acceleration/configuration/proto_to_flatbuffer.h" -#include - -#include "flatbuffers/idl.h" // from @flatbuffers -#include "flatbuffers/util.h" // from @flatbuffers -#include "tensorflow/core/platform/protobuf.h" +#include "flatbuffers/flatbuffers.h" // from @flatbuffers +#include "tensorflow/lite/experimental/acceleration/configuration/configuration.pb.h" +#include "tensorflow/lite/experimental/acceleration/configuration/configuration_generated.h" #include "tensorflow/lite/minimal_logging.h" namespace tflite { -namespace { -#include "tensorflow/lite/experimental/acceleration/configuration/configuration_fbs_contents-inl.h" +using ::flatbuffers::FlatBufferBuilder; +using ::flatbuffers::Offset; + +ExecutionPreference ConvertExecutionPreference( + proto::ExecutionPreference preference) { + switch (preference) { + case proto::ExecutionPreference::ANY: + return ExecutionPreference_ANY; + case proto::ExecutionPreference::LOW_LATENCY: + return ExecutionPreference_LOW_LATENCY; + case proto::ExecutionPreference::LOW_POWER: + return ExecutionPreference_LOW_POWER; + case proto::ExecutionPreference::FORCE_CPU: + return ExecutionPreference_FORCE_CPU; + } + TFLITE_LOG_PROD(TFLITE_LOG_ERROR, + "Unexpected value for ExecutionPreference: %d", preference); + return ExecutionPreference_ANY; +} + +Delegate ConvertDelegate(proto::Delegate delegate) { + switch (delegate) { + case proto::Delegate::NONE: + return Delegate_NONE; + case proto::Delegate::NNAPI: + return Delegate_NNAPI; + case proto::Delegate::GPU: + return Delegate_GPU; + case proto::Delegate::HEXAGON: + return Delegate_HEXAGON; + case proto::Delegate::XNNPACK: + return Delegate_XNNPACK; + case proto::Delegate::EDGETPU: + return Delegate_EDGETPU; + } + TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Unexpected value for Delegate: %d", + delegate); + return Delegate_NONE; +} + +NNAPIExecutionPreference ConvertNNAPIExecutionPreference( + proto::NNAPIExecutionPreference preference) { + switch (preference) { + case proto::NNAPIExecutionPreference::UNDEFINED: + return NNAPIExecutionPreference_UNDEFINED; + case proto::NNAPIExecutionPreference::NNAPI_LOW_POWER: + return NNAPIExecutionPreference_NNAPI_LOW_POWER; + case proto::NNAPIExecutionPreference::NNAPI_FAST_SINGLE_ANSWER: + return NNAPIExecutionPreference_NNAPI_FAST_SINGLE_ANSWER; + case proto::NNAPIExecutionPreference::NNAPI_SUSTAINED_SPEED: + return NNAPIExecutionPreference_NNAPI_SUSTAINED_SPEED; + } + TFLITE_LOG_PROD(TFLITE_LOG_ERROR, + "Unexpected value for NNAPIExecutionPreference: %d", + preference); + return NNAPIExecutionPreference_UNDEFINED; +} + +NNAPIExecutionPriority ConvertNNAPIExecutionPriority( + proto::NNAPIExecutionPriority priority) { + switch (priority) { + case proto::NNAPIExecutionPriority::NNAPI_PRIORITY_UNDEFINED: + return NNAPIExecutionPriority_NNAPI_PRIORITY_UNDEFINED; + case proto::NNAPIExecutionPriority::NNAPI_PRIORITY_LOW: + return NNAPIExecutionPriority_NNAPI_PRIORITY_LOW; + case proto::NNAPIExecutionPriority::NNAPI_PRIORITY_MEDIUM: + return NNAPIExecutionPriority_NNAPI_PRIORITY_MEDIUM; + case proto::NNAPIExecutionPriority::NNAPI_PRIORITY_HIGH: + return NNAPIExecutionPriority_NNAPI_PRIORITY_HIGH; + } + TFLITE_LOG_PROD(TFLITE_LOG_ERROR, + "Unexpected value for NNAPIExecutionPriority: %d", priority); + return NNAPIExecutionPriority_NNAPI_PRIORITY_UNDEFINED; +} + +GPUBackend ConvertGPUBackend(proto::GPUBackend backend) { + switch (backend) { + case proto::GPUBackend::UNSET: + return GPUBackend_UNSET; + case proto::GPUBackend::OPENCL: + return GPUBackend_OPENCL; + case proto::GPUBackend::OPENGL: + return GPUBackend_OPENGL; + } + TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Unexpected value for GPUBackend: %d", + backend); + return GPUBackend_UNSET; +} + +EdgeTpuSettings_::PowerState ConvertEdgeTpuPowerState( + proto::EdgeTpuSettings::PowerState state) { + switch (state) { + case proto::EdgeTpuSettings::UNDEFINED: + return EdgeTpuSettings_::PowerState_UNDEFINED; + case proto::EdgeTpuSettings::TPU_CORE_OFF: + return EdgeTpuSettings_::PowerState_TPU_CORE_OFF; + case proto::EdgeTpuSettings::READY: + return EdgeTpuSettings_::PowerState_READY; + case proto::EdgeTpuSettings::READY_WITH_RETENTION: + return EdgeTpuSettings_::PowerState_READY_WITH_RETENTION; + case proto::EdgeTpuSettings::ACTIVE_MIN_POWER: + return EdgeTpuSettings_::PowerState_ACTIVE_MIN_POWER; + case proto::EdgeTpuSettings::ACTIVE_LOW_POWER: + return EdgeTpuSettings_::PowerState_ACTIVE_LOW_POWER; + case proto::EdgeTpuSettings::ACTIVE: + return EdgeTpuSettings_::PowerState_ACTIVE; + case proto::EdgeTpuSettings::OVER_DRIVE: + return EdgeTpuSettings_::PowerState_OVER_DRIVE; + } + TFLITE_LOG_PROD(TFLITE_LOG_ERROR, + "Unexpected value for EdgeTpuSettings::PowerState: %d", + state); + return EdgeTpuSettings_::PowerState_UNDEFINED; +} + +Offset ConvertFallbackSettings( + const proto::FallbackSettings& settings, FlatBufferBuilder* builder) { + return CreateFallbackSettings( + *builder, /*allow_automatic_fallback_on_compilation_error=*/ + settings.allow_automatic_fallback_on_compilation_error(), + /*allow_automatic_fallback_on_execution_error=*/ + settings.allow_automatic_fallback_on_execution_error()); +} + +Offset ConvertNNAPISettings(const proto::NNAPISettings& settings, + FlatBufferBuilder* builder) { + return CreateNNAPISettings( + *builder, + /*accelerator_name=*/builder->CreateString(settings.accelerator_name()), + /*cache_directory=*/builder->CreateString(settings.cache_directory()), + /*model_token=*/builder->CreateString(settings.model_token()), + ConvertNNAPIExecutionPreference(settings.execution_preference()), + /*no_of_nnapi_instances_to_cache=*/ + settings.no_of_nnapi_instances_to_cache(), + ConvertFallbackSettings(settings.fallback_settings(), builder), + /*allow_nnapi_cpu_on_android_10_plus=*/ + settings.allow_nnapi_cpu_on_android_10_plus(), + ConvertNNAPIExecutionPriority(settings.execution_priority()), + /*allow_dynamic_dimensions=*/ + settings.allow_dynamic_dimensions(), + /*allow_fp16_precision_for_fp32=*/ + settings.allow_fp16_precision_for_fp32()); +} + +Offset ConvertGPUSettings(const proto::GPUSettings& settings, + FlatBufferBuilder* builder) { + return CreateGPUSettings( + *builder, + /*is_precision_loss_allowed=*/settings.is_precision_loss_allowed(), + /*enable_quantized_inference=*/settings.enable_quantized_inference(), + ConvertGPUBackend(settings.force_backend())); +} + +Offset ConvertHexagonSettings( + const proto::HexagonSettings& settings, FlatBufferBuilder* builder) { + return CreateHexagonSettings( + *builder, + /*debug_level=*/settings.debug_level(), + /*powersave_level=*/settings.powersave_level(), + /*print_graph_profile=*/settings.print_graph_profile(), + /*print_graph_debug=*/settings.print_graph_debug()); +} + +Offset ConvertXNNPackSettings( + const proto::XNNPackSettings& settings, FlatBufferBuilder* builder) { + return CreateXNNPackSettings(*builder, + /*num_threads=*/settings.num_threads()); +} + +Offset ConvertCPUSettings(const proto::CPUSettings& settings, + FlatBufferBuilder* builder) { + return CreateCPUSettings(*builder, + /*num_threads=*/settings.num_threads()); +} + +Offset ConvertEdgeTpuSettings( + const proto::EdgeTpuSettings& settings, FlatBufferBuilder* builder) { + return CreateEdgeTpuSettings( + *builder, ConvertEdgeTpuPowerState(settings.inference_power_state())); +} + +Offset ConvertTfliteSettings( + const proto::TFLiteSettings& settings, FlatBufferBuilder* builder) { + return CreateTFLiteSettings( + *builder, ConvertDelegate(settings.delegate()), + ConvertNNAPISettings(settings.nnapi_settings(), builder), + ConvertGPUSettings(settings.gpu_settings(), builder), + ConvertHexagonSettings(settings.hexagon_settings(), builder), + ConvertXNNPackSettings(settings.xnnpack_settings(), builder), + ConvertCPUSettings(settings.cpu_settings(), builder), + /*max_delegated_partitions=*/settings.max_delegated_partitions(), + ConvertEdgeTpuSettings(settings.edgetpu_settings(), builder), + ConvertFallbackSettings(settings.fallback_settings(), builder)); } const ComputeSettings* ConvertFromProto( - flatbuffers::Parser* parser, const proto::ComputeSettings& proto_settings) { - std::string json; - tensorflow::protobuf::util::JsonPrintOptions options; - options.preserve_proto_field_names = true; - options.always_print_primitive_fields = true; // For catching problems. - auto status = tensorflow::protobuf::util::MessageToJsonString(proto_settings, - &json, options); - if (!status.ok()) { - TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Failed to convert to Json: %s", - status.ToString().c_str()); - return nullptr; - } - if (!parser->Parse(configuration_fbs_contents)) { - TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Failed to parse schema: %s", - parser->error_.c_str()); - return nullptr; - } - parser->SetRootType("tflite.ComputeSettings"); - if (!parser->Parse(json.c_str())) { - TFLITE_LOG_PROD(TFLITE_LOG_ERROR, "Failed to parse json: %s", - parser->error_.c_str()); - return nullptr; - } - return flatbuffers::GetRoot( - parser->builder_.GetBufferPointer()); + const proto::ComputeSettings& proto_settings, FlatBufferBuilder* builder) { + auto settings = CreateComputeSettings( + *builder, ConvertExecutionPreference(proto_settings.preference()), + ConvertTfliteSettings(proto_settings.tflite_settings(), builder), + builder->CreateString(proto_settings.model_namespace_for_statistics()), + builder->CreateString(proto_settings.model_identifier_for_statistics())); + return flatbuffers::GetTemporaryPointer(*builder, settings); } } // namespace tflite diff --git a/tensorflow/lite/experimental/acceleration/configuration/proto_to_flatbuffer.h b/tensorflow/lite/experimental/acceleration/configuration/proto_to_flatbuffer.h index 3b69e8465a5..18e147f847f 100644 --- a/tensorflow/lite/experimental/acceleration/configuration/proto_to_flatbuffer.h +++ b/tensorflow/lite/experimental/acceleration/configuration/proto_to_flatbuffer.h @@ -15,17 +15,16 @@ limitations under the License. #ifndef TENSORFLOW_LITE_EXPERIMENTAL_ACCELERATION_CONFIGURATION_PROTO_TO_FLATBUFFER_H_ #define TENSORFLOW_LITE_EXPERIMENTAL_ACCELERATION_CONFIGURATION_PROTO_TO_FLATBUFFER_H_ -#include "flatbuffers/idl.h" // from @flatbuffers +#include "flatbuffers/flatbuffers.h" // from @flatbuffers #include "tensorflow/lite/experimental/acceleration/configuration/configuration.pb.h" #include "tensorflow/lite/experimental/acceleration/configuration/configuration_generated.h" namespace tflite { -// Converts the protobuf version ComputeSettings to the flatbuffer version, via -// json. The parser is used for state - the returned pointer is valid only as -// long as the parser is kept alive and unmutated. +// Converts the provided ComputeSettings from proto to flatbuffer format. const ComputeSettings* ConvertFromProto( - flatbuffers::Parser* parser, const proto::ComputeSettings& proto_settings); + const proto::ComputeSettings& proto_settings, + flatbuffers::FlatBufferBuilder* builder); } // namespace tflite