From 2504c2fe4f3dc6975165d35a8ea1610d8bc4c477 Mon Sep 17 00:00:00 2001 From: Michael Butler Date: Wed, 11 Apr 2018 16:30:09 -0700 Subject: [PATCH] NNAPI: Add execution preference to prepareModel (HAL) A model can be prepared in different ways to optimize for different use-cases. This CL propagates the execution preference across the HAL so that the NN service can better fit the users needs. Bug: 77864669 Test: mma Test: NeuralNetworksTest_static Test: VtsHalNeuralnetworksV1_1TargetTest Change-Id: Ib928d510d462f36b6a87d5e81010513db7829fa8 --- current.txt | 4 +-- .../vts/functional/GeneratedTestHarness.cpp | 4 +-- neuralnetworks/1.1/IDevice.hal | 5 ++- neuralnetworks/1.1/types.hal | 21 +++++++++++ .../1.1/vts/functional/ValidateModel.cpp | 36 ++++++++++++++++--- .../1.1/vts/functional/ValidateRequest.cpp | 4 +-- 6 files changed, 62 insertions(+), 12 deletions(-) diff --git a/current.txt b/current.txt index e79e2d6f7e..7e4b102113 100644 --- a/current.txt +++ b/current.txt @@ -338,8 +338,8 @@ e15ebdf1e0a326ff5b8a59668d4d8cd3852bd88388eae91de13f5f7e1af50ed1 android.hardwar b8c7ed58aa8740361e63d0ce9e7c94227572a629f356958840b34809d2393a7c android.hardware.media.bufferpool@1.0::IClientManager 4a2c0dc82780e6c90731725a103feab8ab6ecf85a64e049b9cbd2b2c61620fe1 android.hardware.media.bufferpool@1.0::IConnection 6aef1218e5949f867b0104752ac536c1b707222a403341720de90141df129e3e android.hardware.media.bufferpool@1.0::types -3e4d8e0085ebe8549efb8ad4b8b400a141a3fa3f47ae23696b3e05a1612eb003 android.hardware.neuralnetworks@1.1::IDevice -50db076b03a6760557fc60ef433ba9dd2ff983cf3305eeb504b0fff3eaa604ff android.hardware.neuralnetworks@1.1::types +7698dc2382a2eeb43541840e3ee624f34108efdfb976b2bfa7c13ef15fb8c4c4 android.hardware.neuralnetworks@1.1::IDevice +5604001029a255648a9e955de0a822a48d9ba7cc259b106fb8be0cd43dc8eece android.hardware.neuralnetworks@1.1::types 8d3d86da0bfa4bf070970d8303c659f67f35d670c287d45a3f542e4fedadd578 android.hardware.nfc@1.1::INfc e85f566698d2a2c28100e264fcf2c691a066756ddf8dd341d009ff50cfe10614 android.hardware.nfc@1.1::INfcClientCallback 5e278fcaa3287d397d8eebe1c22aaa28150f5caae1cf9381cd6dc32cb37899c5 android.hardware.nfc@1.1::types diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp index 4f9d52837c..ed1fb944e6 100644 --- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp +++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp @@ -242,8 +242,8 @@ void Execute(const sp& device, std::function c // launch prepare model sp preparedModelCallback = new PreparedModelCallback(); ASSERT_NE(nullptr, preparedModelCallback.get()); - Return prepareLaunchStatus = - device->prepareModel_1_1(model, preparedModelCallback); + Return prepareLaunchStatus = device->prepareModel_1_1( + model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback); ASSERT_TRUE(prepareLaunchStatus.isOk()); ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus)); diff --git a/neuralnetworks/1.1/IDevice.hal b/neuralnetworks/1.1/IDevice.hal index d2c48433bb..1335bde193 100644 --- a/neuralnetworks/1.1/IDevice.hal +++ b/neuralnetworks/1.1/IDevice.hal @@ -102,6 +102,8 @@ interface IDevice extends @1.0::IDevice { * Multiple threads can call prepareModel on the same model concurrently. * * @param model The model to be prepared for execution. + * @param preference Indicates the intended execution behavior of a prepared + * model. * @param callback A callback object used to return the error status of * preparing the model for execution and the prepared model * if successful, nullptr otherwise. The callback object's @@ -115,6 +117,7 @@ interface IDevice extends @1.0::IDevice { * - INVALID_ARGUMENT if one of the input arguments is * invalid */ - prepareModel_1_1(Model model, IPreparedModelCallback callback) + prepareModel_1_1(Model model, ExecutionPreference preference, + IPreparedModelCallback callback) generates (ErrorStatus status); }; diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal index b4fccaee3c..8290fbbb06 100644 --- a/neuralnetworks/1.1/types.hal +++ b/neuralnetworks/1.1/types.hal @@ -382,3 +382,24 @@ struct Model { */ bool relaxComputationFloat32toFloat16; }; + +/** + * Execution preferences. + */ +enum ExecutionPreference : int32_t { + /** + * Prefer executing in a way that minimizes battery drain. + * This is desirable for compilations that will be executed often. + */ + LOW_POWER = 0, + /** + * Prefer returning a single answer as fast as possible, even if this causes + * more power consumption. + */ + FAST_SINGLE_ANSWER = 1, + /** + * Prefer maximizing the throughput of successive frames, for example when + * processing successive frames coming from the camera. + */ + SUSTAINED_SPEED = 2, +}; diff --git a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp index 7a20e26fe2..3aa55f8c7d 100644 --- a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp +++ b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp @@ -50,13 +50,13 @@ static void validateGetSupportedOperations(const sp& device, const std: } static void validatePrepareModel(const sp& device, const std::string& message, - const V1_1::Model& model) { + const V1_1::Model& model, ExecutionPreference preference) { SCOPED_TRACE(message + " [prepareModel_1_1]"); sp preparedModelCallback = new PreparedModelCallback(); ASSERT_NE(nullptr, preparedModelCallback.get()); Return prepareLaunchStatus = - device->prepareModel_1_1(model, preparedModelCallback); + device->prepareModel_1_1(model, preference, preparedModelCallback); ASSERT_TRUE(prepareLaunchStatus.isOk()); ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast(prepareLaunchStatus)); @@ -67,15 +67,24 @@ static void validatePrepareModel(const sp& device, const std::string& m ASSERT_EQ(nullptr, preparedModel.get()); } +static bool validExecutionPreference(ExecutionPreference preference) { + return preference == ExecutionPreference::LOW_POWER || + preference == ExecutionPreference::FAST_SINGLE_ANSWER || + preference == ExecutionPreference::SUSTAINED_SPEED; +} + // Primary validation function. This function will take a valid model, apply a // mutation to it to invalidate the model, then pass it to interface calls that // use the model. Note that the model here is passed by value, and any mutation // to the model does not leave this function. static void validate(const sp& device, const std::string& message, V1_1::Model model, - const std::function& mutation) { + const std::function& mutation, + ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER) { mutation(&model); - validateGetSupportedOperations(device, message, model); - validatePrepareModel(device, message, model); + if (validExecutionPreference(preference)) { + validateGetSupportedOperations(device, message, model); + } + validatePrepareModel(device, message, model, preference); } // Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation, @@ -486,6 +495,22 @@ static void addOperationOutputTest(const sp& device, const V1_1::Model& } } +///////////////////////// VALIDATE EXECUTION PREFERENCE ///////////////////////// + +static const int32_t invalidExecutionPreferences[] = { + static_cast(ExecutionPreference::LOW_POWER) - 1, // lower bound + static_cast(ExecutionPreference::SUSTAINED_SPEED) + 1, // upper bound +}; + +static void mutateExecutionPreferenceTest(const sp& device, const V1_1::Model& model) { + for (int32_t preference : invalidExecutionPreferences) { + const std::string message = + "mutateExecutionPreferenceTest: preference " + std::to_string(preference); + validate(device, message, model, [](Model*) {}, + static_cast(preference)); + } +} + ////////////////////////// ENTRY POINT ////////////////////////////// void ValidationTest::validateModel(const V1_1::Model& model) { @@ -503,6 +528,7 @@ void ValidationTest::validateModel(const V1_1::Model& model) { removeOperationOutputTest(device, model); addOperationInputTest(device, model); addOperationOutputTest(device, model); + mutateExecutionPreferenceTest(device, model); } } // namespace functional diff --git a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp index bd966144f6..b42f561c7f 100644 --- a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp +++ b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp @@ -60,8 +60,8 @@ static void createPreparedModel(const sp& device, const V1_1::Model& mo // launch prepare model sp preparedModelCallback = new PreparedModelCallback(); ASSERT_NE(nullptr, preparedModelCallback.get()); - Return prepareLaunchStatus = - device->prepareModel_1_1(model, preparedModelCallback); + Return prepareLaunchStatus = device->prepareModel_1_1( + model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback); ASSERT_TRUE(prepareLaunchStatus.isOk()); ASSERT_EQ(ErrorStatus::NONE, static_cast(prepareLaunchStatus));