diff --git a/tensorflow/lite/experimental/acceleration/configuration/configuration.proto b/tensorflow/lite/experimental/acceleration/configuration/configuration.proto index e1c49f02856..44d462da073 100644 --- a/tensorflow/lite/experimental/acceleration/configuration/configuration.proto +++ b/tensorflow/lite/experimental/acceleration/configuration/configuration.proto @@ -69,6 +69,13 @@ enum NNAPIExecutionPreference { NNAPI_SUSTAINED_SPEED = 3; } +enum NNAPIExecutionPriority { + NNAPI_PRIORITY_UNDEFINED = 0; + NNAPI_PRIORITY_LOW = 1; + NNAPI_PRIORITY_MEDIUM = 2; + NNAPI_PRIORITY_HIGH = 3; +} + // One possible acceleration configuration. message ComputeSettings { // Which preference to use this accelerator for. @@ -110,6 +117,8 @@ message NNAPISettings { // performs less well than the TfLite built-in kernels; but allowing allows a // model to be partially accelerated which may be a win. optional bool allow_nnapi_cpu_on_android_10_plus = 7; + + optional NNAPIExecutionPriority execution_priority = 8; } // Which GPU backend to select. Default behaviour on Android is to try OpenCL diff --git a/tensorflow/lite/experimental/acceleration/configuration/nnapi_plugin.cc b/tensorflow/lite/experimental/acceleration/configuration/nnapi_plugin.cc index 7301983a815..cf99f530d6d 100644 --- a/tensorflow/lite/experimental/acceleration/configuration/nnapi_plugin.cc +++ b/tensorflow/lite/experimental/acceleration/configuration/nnapi_plugin.cc @@ -39,6 +39,20 @@ ConvertExecutionPrefence( } } +inline int ConvertExecutionPriority( + NNAPIExecutionPriority from_compatibility_priority) { + switch (from_compatibility_priority) { + case NNAPIExecutionPriority_NNAPI_PRIORITY_LOW: + return ANEURALNETWORKS_PRIORITY_LOW; + case NNAPIExecutionPriority_NNAPI_PRIORITY_MEDIUM: + return ANEURALNETWORKS_PRIORITY_MEDIUM; + case NNAPIExecutionPriority_NNAPI_PRIORITY_HIGH: + return ANEURALNETWORKS_PRIORITY_HIGH; + default: + return ANEURALNETWORKS_PRIORITY_DEFAULT; + } +} + class NnapiPlugin : public DelegatePluginInterface { public: TfLiteDelegatePtr Create() override { @@ -80,6 +94,8 @@ class NnapiPlugin : public DelegatePluginInterface { ConvertExecutionPrefence(nnapi_settings->execution_preference()); options_.disallow_nnapi_cpu = !nnapi_settings->allow_nnapi_cpu_on_android_10_plus(); + options_.execution_priority = + ConvertExecutionPriority(nnapi_settings->execution_priority()); } private: diff --git a/tensorflow/lite/experimental/acceleration/configuration/nnapi_plugin_test.cc b/tensorflow/lite/experimental/acceleration/configuration/nnapi_plugin_test.cc index 4f9f5dd08c1..c35e92e6fc1 100644 --- a/tensorflow/lite/experimental/acceleration/configuration/nnapi_plugin_test.cc +++ b/tensorflow/lite/experimental/acceleration/configuration/nnapi_plugin_test.cc @@ -18,6 +18,7 @@ limitations under the License. #include "flatbuffers/flatbuffers.h" // from @flatbuffers #include "tensorflow/lite/c/common.h" #include "tensorflow/lite/delegates/nnapi/nnapi_delegate.h" +#include "tensorflow/lite/delegates/nnapi/nnapi_delegate_kernel.h" #include "tensorflow/lite/delegates/nnapi/nnapi_delegate_mock_test.h" #include "tensorflow/lite/experimental/acceleration/configuration/configuration_generated.h" #include "tensorflow/lite/experimental/acceleration/configuration/delegate_registry.h" @@ -82,6 +83,25 @@ class NNAPIPluginTest : public ::testing::Test { kTfLiteOk) << " given input: " << input << " expected output: " << output; } + template + void CheckExecutionPriority() { + // Note - this uses a template since the NNAPI functions are C function + // pointers rather than lambdas so can't capture variables. + nnapi_->ANeuralNetworksCompilation_setPriority = + [](ANeuralNetworksCompilation* compilation, int32_t priority) { + return priority - output; + }; + CreateDelegate(CreateNNAPISettings(fbb_, 0, 0, 0, + NNAPIExecutionPreference_UNDEFINED, 0, 0, + /*allow CPU=*/true, input)); + // Since delegation succeeds, the model becomes immutable and hence can't + // reuse it. + SingleAddOpModel model; + model.Build(); + EXPECT_EQ(model.Interpreter()->ModifyGraphWithDelegate(delegate_.get()), + kTfLiteOk) + << " given input: " << input << " expected output: " << output; + } void CreateDelegate(flatbuffers::Offset settings) { settings_ = flatbuffers::GetTemporaryPointer( @@ -124,6 +144,19 @@ TEST_F(NNAPIPluginTest, PassesExecutionPreference) { StatefulNnApiDelegate::Options::kSustainedSpeed>(); } +TEST_F(NNAPIPluginTest, PassesExecutionPriority) { + nnapi_->android_sdk_version = + tflite::delegate::nnapi::kMinSdkVersionForNNAPI13; + CheckExecutionPriority(); + CheckExecutionPriority(); + CheckExecutionPriority(); + CheckExecutionPriority(); +} + TEST_F(NNAPIPluginTest, PassesCachingParameters) { nnapi_->ANeuralNetworksCompilation_setCaching = [](ANeuralNetworksCompilation* compilation, const char* cacheDir,