diff options
author | Miao Wang <miaowang@google.com> | 2019-12-23 16:18:11 -0800 |
---|---|---|
committer | Xusong Wang <xusongw@google.com> | 2020-01-27 13:06:15 -0800 |
commit | 4e0d686495769c0fe1f9b41967a6c9f386c212fd (patch) | |
tree | 4a9a42bdc85e39068c42f3fbd0d020ee999a8286 | |
parent | 7b647483ebc7aeeac3208aa2db0a8e0fda305e6b (diff) | |
download | ml-4e0d686495769c0fe1f9b41967a6c9f386c212fd.tar.gz |
Add tests for sync fence related API.
The following tests are added:
- basic validation tests
- generated tests for
ANeuralNetworksExecution_startComputeWithDependencies.
Bug: 142778241
Test: mm
Change-Id: I5591db4583e8b752868d06e16874780800d4410e
Merged-In: I5591db4583e8b752868d06e16874780800d4410e
(cherry picked from commit 688992b3e241dd8936d63c6a21977bfc6b6f0773)
-rw-r--r-- | nn/runtime/include/NeuralNetworksWrapper.h | 3 | ||||
-rw-r--r-- | nn/runtime/test/TestGenerated.cpp | 6 | ||||
-rw-r--r-- | nn/runtime/test/TestMain.cpp | 2 | ||||
-rw-r--r-- | nn/runtime/test/TestNeuralNetworksWrapper.h | 16 | ||||
-rw-r--r-- | nn/runtime/test/TestTrivialModel.cpp | 43 | ||||
-rw-r--r-- | nn/runtime/test/TestValidation.cpp | 81 |
6 files changed, 148 insertions, 3 deletions
diff --git a/nn/runtime/include/NeuralNetworksWrapper.h b/nn/runtime/include/NeuralNetworksWrapper.h index 7428741fc..69edd1ddb 100644 --- a/nn/runtime/include/NeuralNetworksWrapper.h +++ b/nn/runtime/include/NeuralNetworksWrapper.h @@ -328,6 +328,9 @@ class Event { mEvent = newEvent; } + // Only for use by Execution + ANeuralNetworksEvent* getHandle() const { return mEvent; } + private: ANeuralNetworksEvent* mEvent = nullptr; }; diff --git a/nn/runtime/test/TestGenerated.cpp b/nn/runtime/test/TestGenerated.cpp index 93603a5eb..5842f0f36 100644 --- a/nn/runtime/test/TestGenerated.cpp +++ b/nn/runtime/test/TestGenerated.cpp @@ -488,6 +488,12 @@ TEST_P(GeneratedTests, Burst) { execute(testModel); Execution::setComputeMode(oldComputeMode); } + +TEST_P(GeneratedTests, Fenced) { + const auto oldComputeMode = Execution::setComputeMode(Execution::ComputeMode::FENCED); + execute(testModel); + Execution::setComputeMode(oldComputeMode); +} #else TEST_P(GeneratedTests, Test) { execute(testModel); diff --git a/nn/runtime/test/TestMain.cpp b/nn/runtime/test/TestMain.cpp index b75417b09..a4fefae70 100644 --- a/nn/runtime/test/TestMain.cpp +++ b/nn/runtime/test/TestMain.cpp @@ -78,6 +78,8 @@ static int test(bool useCpuOnly, Execution::ComputeMode computeMode, bool allowS return "ComputeMode::ASYNC"; case Execution::ComputeMode::BURST: return "ComputeMode::BURST"; + case Execution::ComputeMode::FENCED: + return "ComputeMode::FENCED"; } return "<unknown ComputeMode>"; }; diff --git a/nn/runtime/test/TestNeuralNetworksWrapper.h b/nn/runtime/test/TestNeuralNetworksWrapper.h index 05e68ace2..3111d148b 100644 --- a/nn/runtime/test/TestNeuralNetworksWrapper.h +++ b/nn/runtime/test/TestNeuralNetworksWrapper.h @@ -376,6 +376,18 @@ class Execution { ANeuralNetworksBurst_free(burst); return result; } + case ComputeMode::FENCED: { + ANeuralNetworksEvent* event = nullptr; + Result result = + static_cast<Result>(ANeuralNetworksExecution_startComputeWithDependencies( + mExecution, nullptr, 0, &event)); + if (result != Result::NO_ERROR) { + return result; + } + result = static_cast<Result>(ANeuralNetworksEvent_wait(event)); + ANeuralNetworksEvent_free(event); + return result; + } } return Result::BAD_DATA; } @@ -386,7 +398,7 @@ class Execution { // or // - use the burst API // Returns the previous ComputeMode. - enum class ComputeMode { SYNC, ASYNC, BURST }; + enum class ComputeMode { SYNC, ASYNC, BURST, FENCED }; static ComputeMode setComputeMode(ComputeMode mode) { ComputeMode oldComputeMode = mComputeMode; mComputeMode = mode; @@ -407,6 +419,8 @@ class Execution { return result; } + ANeuralNetworksExecution* getHandle() { return mExecution; }; + private: ANeuralNetworksCompilation* mCompilation = nullptr; ANeuralNetworksExecution* mExecution = nullptr; diff --git a/nn/runtime/test/TestTrivialModel.cpp b/nn/runtime/test/TestTrivialModel.cpp index 85da1d1f0..557b2aa62 100644 --- a/nn/runtime/test/TestTrivialModel.cpp +++ b/nn/runtime/test/TestTrivialModel.cpp @@ -150,6 +150,49 @@ TEST_F(TrivialTest, AddThree) { ASSERT_EQ(CompareMatrices(expected3b, actual), 0); } +TEST_F(TrivialTest, FencedAddThree) { + Model modelAdd3; + CreateAddThreeTensorModel(&modelAdd3, matrix3); + Compilation compilation(&modelAdd3); + compilation.finish(); + + Matrix3x4 output1, output2; + memset(&output1, 0, sizeof(output1)); + memset(&output2, 0, sizeof(output2)); + + // Start the first execution + Execution execution1(&compilation); + ASSERT_EQ(execution1.setInput(0, matrix1, sizeof(Matrix3x4)), Result::NO_ERROR); + ASSERT_EQ(execution1.setInput(1, matrix2, sizeof(Matrix3x4)), Result::NO_ERROR); + ASSERT_EQ(execution1.setOutput(0, output1, sizeof(Matrix3x4)), Result::NO_ERROR); + ANeuralNetworksEvent* event1; + ANeuralNetworksExecution* execution1_handle = execution1.getHandle(); + ASSERT_EQ(ANeuralNetworksExecution_startComputeWithDependencies(execution1_handle, nullptr, 0, + &event1), + ANEURALNETWORKS_NO_ERROR); + + // Start the second execution which will wait for the first one. + Execution execution2(&compilation); + ASSERT_EQ(execution2.setInput(0, matrix1, sizeof(Matrix3x4)), Result::NO_ERROR); + ASSERT_EQ(execution2.setInput(1, matrix1, sizeof(Matrix3x4)), Result::NO_ERROR); + ASSERT_EQ(execution2.setOutput(0, output2, sizeof(Matrix3x4)), Result::NO_ERROR); + ANeuralNetworksEvent* event2; + ANeuralNetworksExecution* execution2_handle = execution2.getHandle(); + ASSERT_EQ(ANeuralNetworksExecution_startComputeWithDependencies(execution2_handle, &event1, 1, + &event2), + ANEURALNETWORKS_NO_ERROR); + // Wait for the second event. + ASSERT_EQ(ANeuralNetworksEvent_wait(event2), ANEURALNETWORKS_NO_ERROR); + + // Check the results for both executions. + ASSERT_EQ(CompareMatrices(expected3, output1), 0); + ASSERT_EQ(CompareMatrices(expected3b, output2), 0); + + // Free the event objects + ANeuralNetworksEvent_free(event1); + ANeuralNetworksEvent_free(event2); +} + TEST_F(TrivialTest, BroadcastAddTwo) { Model modelBroadcastAdd2; OperandType scalarType(Type::INT32, {}); diff --git a/nn/runtime/test/TestValidation.cpp b/nn/runtime/test/TestValidation.cpp index 89d263c6d..a978589dd 100644 --- a/nn/runtime/test/TestValidation.cpp +++ b/nn/runtime/test/TestValidation.cpp @@ -1006,8 +1006,9 @@ TEST_F(ValidationTestCompilation, ExecutionTiming) { TEST_F(ValidationTestCompilation, ExecutionUsability) { ASSERT_EQ(ANeuralNetworksCompilation_finish(mCompilation), ANEURALNETWORKS_NO_ERROR); - enum class ExecutionType : uint32_t { ASYNC, SYNC, BURST }; - for (auto executionType : {ExecutionType::ASYNC, ExecutionType::SYNC, ExecutionType::BURST}) { + enum class ExecutionType : uint32_t { ASYNC, SYNC, BURST, FENCED }; + for (auto executionType : + {ExecutionType::ASYNC, ExecutionType::SYNC, ExecutionType::BURST, ExecutionType::FENCED}) { SCOPED_TRACE(static_cast<uint32_t>(executionType)); ANeuralNetworksExecution* execution; @@ -1068,6 +1069,14 @@ TEST_F(ValidationTestCompilation, ExecutionUsability) { ANEURALNETWORKS_BAD_STATE); ANeuralNetworksBurst_free(burst); } + + // Reuse for fenced execution. + { + ANeuralNetworksEvent* event; + ASSERT_EQ(ANeuralNetworksExecution_startComputeWithDependencies(execution, nullptr, + 0, &event), + ANEURALNETWORKS_BAD_STATE); + } }; // Compute. @@ -1097,6 +1106,17 @@ TEST_F(ValidationTestCompilation, ExecutionUsability) { ANeuralNetworksBurst_free(burst); break; } + case ExecutionType::FENCED: { + ANeuralNetworksEvent* event; + ASSERT_EQ(ANeuralNetworksExecution_startComputeWithDependencies(execution, nullptr, + 0, &event), + ANEURALNETWORKS_NO_ERROR); + testTooLate(); + ASSERT_EQ(ANeuralNetworksEvent_wait(event), ANEURALNETWORKS_NO_ERROR); + testTooLate(); + ANeuralNetworksEvent_free(event); + break; + } default: FAIL() << "Unreachable"; } @@ -1511,6 +1531,63 @@ TEST_F(ValidationTestExecution, EventWait) { EXPECT_EQ(ANeuralNetworksEvent_wait(nullptr), ANEURALNETWORKS_UNEXPECTED_NULL); } +TEST_F(ValidationTest, EventCreateFromSyncFenceFd) { + ANeuralNetworksEvent* event; + EXPECT_EQ(ANeuralNetworksEvent_createFromSyncFenceFd(-1, &event), ANEURALNETWORKS_BAD_DATA); + EXPECT_EQ(ANeuralNetworksEvent_createFromSyncFenceFd(1, nullptr), + ANEURALNETWORKS_UNEXPECTED_NULL); +} + +TEST_F(ValidationTest, EventGetSyncFenceFd) { + int sync_fd = -1; + EXPECT_EQ(ANeuralNetworksEvent_getSyncFenceFd(nullptr, &sync_fd), + ANEURALNETWORKS_UNEXPECTED_NULL); +} + +TEST_F(ValidationTestExecution, FencedExecution) { + // Create a valid execution and event first. + ANeuralNetworksExecution* execution1; + EXPECT_EQ(ANeuralNetworksExecution_create(mCompilation, &execution1), ANEURALNETWORKS_NO_ERROR); + float input0[] = {1.0f, 1.0f}, input1[] = {2.0f, 2.0f}, output0[2]; + int32_t input2[] = {0}; + EXPECT_EQ(ANeuralNetworksExecution_setInput(execution1, 0, nullptr, input0, sizeof(input0)), + ANEURALNETWORKS_NO_ERROR); + EXPECT_EQ(ANeuralNetworksExecution_setInput(execution1, 1, nullptr, input1, sizeof(input1)), + ANEURALNETWORKS_NO_ERROR); + EXPECT_EQ(ANeuralNetworksExecution_setInput(execution1, 2, nullptr, input2, sizeof(input2)), + ANEURALNETWORKS_NO_ERROR); + EXPECT_EQ(ANeuralNetworksExecution_setOutput(execution1, 0, nullptr, output0, sizeof(output0)), + ANEURALNETWORKS_NO_ERROR); + ANeuralNetworksEvent* event1 = nullptr; + EXPECT_EQ( + ANeuralNetworksExecution_startComputeWithDependencies(execution1, nullptr, 0, &event1), + ANEURALNETWORKS_NO_ERROR); + + EXPECT_EQ(ANeuralNetworksEvent_getSyncFenceFd(event1, nullptr), + ANEURALNETWORKS_UNEXPECTED_NULL); + + // The subsequent execution will wait for the first execution to finish. + ANeuralNetworksExecution* execution2; + ANeuralNetworksEvent* event2 = nullptr; + EXPECT_EQ(ANeuralNetworksExecution_create(mCompilation, &execution2), ANEURALNETWORKS_NO_ERROR); + EXPECT_EQ(ANeuralNetworksExecution_startComputeWithDependencies(nullptr, &event1, 1, &event2), + ANEURALNETWORKS_UNEXPECTED_NULL); + EXPECT_EQ( + ANeuralNetworksExecution_startComputeWithDependencies(execution2, nullptr, 1, &event2), + ANEURALNETWORKS_UNEXPECTED_NULL); + EXPECT_EQ( + ANeuralNetworksExecution_startComputeWithDependencies(execution2, &event1, 1, nullptr), + ANEURALNETWORKS_UNEXPECTED_NULL); + ANeuralNetworksEvent* wait_for_list[] = {event1, nullptr}; + EXPECT_EQ(ANeuralNetworksExecution_startComputeWithDependencies(execution2, wait_for_list, 2, + &event2), + ANEURALNETWORKS_UNEXPECTED_NULL); + + ANeuralNetworksEvent_free(event1); + ANeuralNetworksExecution_free(execution1); + ANeuralNetworksExecution_free(execution2); +} + TEST_F(ValidationTestExecution, GetOutputOperandRankAndDimensions) { ANeuralNetworksExecution* execution; EXPECT_EQ(ANeuralNetworksExecution_create(mCompilation, &execution), ANEURALNETWORKS_NO_ERROR); |