Make the NDK execution object reusable.
This CL enables reusable execution object at NDK level.
- Add new API ANNExecution_setReusable
- Modify NDK specification related to execution usablility
- Change NNAPI ExecutionBuilder to allow reusable execution
- Add validation and generated tests
This CL only enables reusable execution object in the NNAPI runtime.
Optimizations will be applied in subsequent CLs.
Additionally, this CL changes a behavior of computations: Previously, we
wouldn't mark the builder as started until we get past the initial
validation, whereas now we mark the builder as started before the
validations and then mark it as completed if the validation fails.
Bug: 179692400
Test: NNT_static
Test: CtsNNAPITestCases
Change-Id: I0e2539f2adb7316af5b5364ac961f53e4ec09c59
Merged-In: I0e2539f2adb7316af5b5364ac961f53e4ec09c59
(cherry picked from commit 0b261d5651728eed74dd4c6033e25129b5e16368)
diff --git a/runtime/NeuralNetworks.cpp b/runtime/NeuralNetworks.cpp
index 3df11df..c16bf39 100644
--- a/runtime/NeuralNetworks.cpp
+++ b/runtime/NeuralNetworks.cpp
@@ -1381,8 +1381,7 @@
}
IEvent* e = reinterpret_cast<IEvent*>(event);
- e->wait();
- return convertErrorStatusToResultCode(e->getStatus());
+ return convertErrorStatusToResultCode(e->wait());
}
void ANeuralNetworksEvent_free(ANeuralNetworksEvent* event) {
@@ -1481,7 +1480,8 @@
*event = nullptr;
return ANEURALNETWORKS_BAD_DATA;
}
- std::unique_ptr<SyncFenceEvent> e = std::make_unique<SyncFenceEvent>(syncFenceFd, nullptr);
+ std::unique_ptr<SyncFenceEvent> e =
+ std::make_unique<SyncFenceEvent>(syncFenceFd, nullptr, nullptr);
*event = reinterpret_cast<ANeuralNetworksEvent*>(e.release());
return ANEURALNETWORKS_NO_ERROR;
}
@@ -1559,8 +1559,11 @@
int syncFenceToSignal = -1;
int n = r->computeFenced(waitForList, duration, &syncFenceToSignal);
- std::unique_ptr<SyncFenceEvent> e =
- std::make_unique<SyncFenceEvent>(syncFenceToSignal, r->getExecuteFencedInfoCallback());
+ std::unique_ptr<SyncFenceEvent> e = std::make_unique<SyncFenceEvent>(
+ syncFenceToSignal, r->getExecuteFencedInfoCallback(),
+ // TODO(miaowang): support dynamic output shape only with memory domain.
+ // For now just return empty output shapes.
+ [r](ErrorStatus status) { return r->finishComputation(status, {}); });
if (n != ANEURALNETWORKS_NO_ERROR) {
*event = nullptr;
} else {
@@ -1635,3 +1638,13 @@
const CompilationBuilder* c = reinterpret_cast<const CompilationBuilder*>(compilation);
return c->getPreferredMemoryPaddingForOutput(index, padding);
}
+
+int ANeuralNetworksExecution_setReusable(ANeuralNetworksExecution* execution, bool reusable) {
+ NNTRACE_RT(NNTRACE_PHASE_EXECUTION, "ANeuralNetworksExecution_setReusable");
+ if (!execution) {
+ LOG(ERROR) << "ANeuralNetworksExecution_setReusable passed a nullptr";
+ return ANEURALNETWORKS_UNEXPECTED_NULL;
+ }
+ ExecutionBuilder* r = reinterpret_cast<ExecutionBuilder*>(execution);
+ return r->setReusable(reusable);
+}