Neuralnetworks HAL cleanup -- frameworks/ml/nn
Does three primary cleanups:
1) Removes unused OperandTypes, creates OEM types
2) Creates explicit ErrorStatus; functions return status
3) IDevice::initialize renamed to getCapabilities,
IDevice::getSupportedSubgraph renamed to getSupportedOperations
It makes the corresponding changes to the runtime.
Bug: 63905942
Test: mm, frameworks/ml/nn/runtime/test
Change-Id: I1545373dfa30780aaf9b61b3938be536cf122e74
diff --git a/runtime/Event.cpp b/runtime/Event.cpp
index 67de4f5..efaacb3 100644
--- a/runtime/Event.cpp
+++ b/runtime/Event.cpp
@@ -21,10 +21,10 @@
// thread::join failed: Resource deadlock would occur
}
-Return<void> Event::notify(ReturnedStatus status) {
+Return<void> Event::notify(ErrorStatus status) {
{
std::lock_guard<std::mutex> lock(mMutex);
- mStatus = status == ReturnedStatus::SUCCESS ? Status::SUCCESS : Status::ERROR;
+ mStatus = status == ErrorStatus::NONE ? Status::SUCCESS : Status::ERROR;
if (mStatus == Status::SUCCESS && mCallback != nullptr) {
bool success = mCallback();
if (!success) {
diff --git a/runtime/Event.h b/runtime/Event.h
index 4f7f2f6..5682bc7 100644
--- a/runtime/Event.h
+++ b/runtime/Event.h
@@ -24,8 +24,6 @@
using ::android::hardware::Void;
using ::android::sp;
-using ReturnedStatus = ::android::hardware::neuralnetworks::V1_0::Status;
-
/**
* The Event class is used internally by the Neuralnetworks runtime to
* synchronize between different threads. An asynchronous task is launched
@@ -79,7 +77,7 @@
*
* @param neuralnetworks::V1_0::Status SUCCESS or ERROR
*/
- Return<void> notify(ReturnedStatus status) override;
+ Return<void> notify(ErrorStatus status) override;
/**
* Event::poll returns the current status of the event.
diff --git a/runtime/Manager.cpp b/runtime/Manager.cpp
index 270e0cf..f6caf6d 100644
--- a/runtime/Manager.cpp
+++ b/runtime/Manager.cpp
@@ -27,8 +27,12 @@
namespace android {
namespace nn {
+// TODO: handle errors from initialize correctly
void Device::initialize() {
- mInterface->initialize([&]([[maybe_unused]] const Capabilities& capabilities) {
+ mInterface->getCapabilities([&](ErrorStatus status, const Capabilities& capabilities) {
+ if (status != ErrorStatus::NONE) {
+ LOG(ERROR) << "IDevice::getCapabilities returned the error " << toString(status);
+ }
LOG(DEBUG) << "Capab " << capabilities.float16Performance.execTime;
LOG(DEBUG) << "Capab " << capabilities.float32Performance.execTime;
/*
diff --git a/runtime/NeuralNetworks.cpp b/runtime/NeuralNetworks.cpp
index 2e59820..8c7c288 100644
--- a/runtime/NeuralNetworks.cpp
+++ b/runtime/NeuralNetworks.cpp
@@ -33,20 +33,16 @@
// Make sure the constants defined in the header file have not changed values.
// IMPORTANT: When adding new values, update kNumberOfDataTypes in Utils.h.
-static_assert(ANEURALNETWORKS_FLOAT16 == 0, "ANEURALNETWORKS_FLOAT16 may have changed");
+static_assert(ANEURALNETWORKS_OEM == 0, "ANEURALNETWORKS_OEM may have changed");
static_assert(ANEURALNETWORKS_FLOAT32 == 1, "ANEURALNETWORKS_FLOAT32 may have changed");
-static_assert(ANEURALNETWORKS_INT8 == 2, "ANEURALNETWORKS_INT8 may have changed");
-static_assert(ANEURALNETWORKS_UINT8 == 3, "ANEURALNETWORKS_UINT8 may have changed");
-static_assert(ANEURALNETWORKS_INT16 == 4, "ANEURALNETWORKS_INT16 may have changed");
-static_assert(ANEURALNETWORKS_UINT16 == 5, "ANEURALNETWORKS_UINT16 may have changed");
-static_assert(ANEURALNETWORKS_INT32 == 6, "ANEURALNETWORKS_INT32 may have changed");
-static_assert(ANEURALNETWORKS_UINT32 == 7, "ANEURALNETWORKS_UINT32 may have changed");
-static_assert(ANEURALNETWORKS_TENSOR_FLOAT16 == 8,
- "ANEURALNETWORKS_TENSOR_FLOAT16 may have changed");
-static_assert(ANEURALNETWORKS_TENSOR_FLOAT32 == 9,
+static_assert(ANEURALNETWORKS_INT32 == 2, "ANEURALNETWORKS_INT32 may have changed");
+static_assert(ANEURALNETWORKS_UINT32 == 3, "ANEURALNETWORKS_UINT32 may have changed");
+static_assert(ANEURALNETWORKS_TENSOR_OEM_BYTE == 4,
+ "ANEURALNETWORKS_TENSOR_OEM_BYTE may have changed");
+static_assert(ANEURALNETWORKS_TENSOR_FLOAT32 == 5,
"ANEURALNETWORKS_TENSOR_FLOAT32 may have changed");
-static_assert(ANEURALNETWORKS_TENSOR_INT32 == 10, "ANEURALNETWORKS_TENSOR_INT32 may have changed");
-static_assert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM == 11,
+static_assert(ANEURALNETWORKS_TENSOR_INT32 == 6, "ANEURALNETWORKS_TENSOR_INT32 may have changed");
+static_assert(ANEURALNETWORKS_TENSOR_QUANT8_ASYMM == 7,
"ANEURALNETWORKS_TENSOR_QUANT8_ASYMM may have changed");
// IMPORTANT: When adding new values, update kNumberOfOperationTypes in Utils.h.
@@ -116,24 +112,16 @@
// Make sure that the constants are compatible with the values defined in
// hardware/interfaces/neuralnetworks/1.0/types.hal.
-static_assert(static_cast<uint32_t>(OperandType::FLOAT16) == ANEURALNETWORKS_FLOAT16,
- "FLOAT16 != ANEURALNETWORKS_FLOAT16");
+static_assert(static_cast<uint32_t>(OperandType::OEM) == ANEURALNETWORKS_OEM,
+ "OEM != ANEURALNETWORKS_OEM");
static_assert(static_cast<uint32_t>(OperandType::FLOAT32) == ANEURALNETWORKS_FLOAT32,
"FLOAT32 != ANEURALNETWORKS_FLOAT32");
-static_assert(static_cast<uint32_t>(OperandType::INT8) == ANEURALNETWORKS_INT8,
- "INT8 != ANEURALNETWORKS_INT8");
-static_assert(static_cast<uint32_t>(OperandType::UINT8) == ANEURALNETWORKS_UINT8,
- "UINT8 != ANEURALNETWORKS_UINT8");
-static_assert(static_cast<uint32_t>(OperandType::INT16) == ANEURALNETWORKS_INT16,
- "INT16 != ANEURALNETWORKS_INT16");
-static_assert(static_cast<uint32_t>(OperandType::UINT16) == ANEURALNETWORKS_UINT16,
- "UINT16 != ANEURALNETWORKS_UINT16");
static_assert(static_cast<uint32_t>(OperandType::INT32) == ANEURALNETWORKS_INT32,
"INT32 != ANEURALNETWORKS_INT32");
static_assert(static_cast<uint32_t>(OperandType::UINT32) == ANEURALNETWORKS_UINT32,
"UINT32 != ANEURALNETWORKS_UINT32");
-static_assert(static_cast<uint32_t>(OperandType::TENSOR_FLOAT16) == ANEURALNETWORKS_TENSOR_FLOAT16,
- "TENSOR_FLOAT16 != ANEURALNETWORKS_TENSOR_FLOAT16");
+static_assert(static_cast<uint32_t>(OperandType::TENSOR_OEM_BYTE) == ANEURALNETWORKS_TENSOR_OEM_BYTE,
+ "TENSOR_OEM_BYTE != ANEURALNETWORKS_TENSOR_OEM_BYTE");
static_assert(static_cast<uint32_t>(OperandType::TENSOR_FLOAT32) == ANEURALNETWORKS_TENSOR_FLOAT32,
"TENSOR_FLOAT32 != ANEURALNETWORKS_TENSOR_FLOAT32");
static_assert(static_cast<uint32_t>(OperandType::TENSOR_QUANT8_ASYMM) ==
@@ -244,8 +232,7 @@
type.scale); return ANEURALNETWORKS_BAD_DATA;
}
if (type.scale != 0.f &&
- (type.type == ANEURALNETWORKS_FLOAT16 ||
- type.type != ANEURALNETWORKS_FLOAT32)) {
+ (type.type != ANEURALNETWORKS_FLOAT32)) {
LOG(ERROR) << ("%s OperandType scale %f with float type %u", tag, type.scale,
type.type); return ANEURALNETWORKS_BAD_DATA;
}
diff --git a/runtime/RequestBuilder.cpp b/runtime/RequestBuilder.cpp
index 8b68924..3738783 100644
--- a/runtime/RequestBuilder.cpp
+++ b/runtime/RequestBuilder.cpp
@@ -218,14 +218,24 @@
}
int RequestBuilder::startComputeOnDevice(sp<IDevice> driver, const Model& model) {
- LOG(DEBUG) << "RequestBuilder::startComputeOnDevice1";
+ LOG(DEBUG) << "RequestBuilder::startComputeOnDevice";
// TODO Dangerous! In async, the model will outlive it here. Safe for now
sp<Event> preparationEvent = new Event();
- sp<IPreparedModel> preparedModel = driver->prepareModel(model, preparationEvent);
+ ErrorStatus prepareStatus = ErrorStatus::GENERAL_FAILURE;
+ sp<IPreparedModel> preparedModel;
+
+ driver->prepareModel(model, preparationEvent,
+ [&](ErrorStatus status, const sp<IPreparedModel>& prepared) {
+ prepareStatus = status;
+ preparedModel = prepared;
+ });
+
// Immediately synchronize with event for now
// TODO: change to asynchronous later
- preparationEvent->wait();
- if (preparedModel == nullptr) {
+ Event::Status eventStatus = preparationEvent->wait();
+
+ if (prepareStatus != ErrorStatus::NONE || preparedModel == nullptr ||
+ eventStatus != Event::Status::SUCCESS) {
return ANEURALNETWORKS_OP_FAILED;
}
@@ -281,7 +291,7 @@
// maybe the HIDL infrastructure handles this magically? At worst,
// it seems like this is a small memory leak, if the Event stays
// alive forever.
- if (!preparedModel->execute(request, eventSp)) {
+ if (preparedModel->execute(request, eventSp) != ErrorStatus::NONE) {
LOG(DEBUG) << "**Execute failed**";
return ANEURALNETWORKS_OP_FAILED;
}
@@ -320,8 +330,9 @@
const sp<IEvent>& event) {
CpuExecutor executor;
int err = executor.run(model, request, runTimePoolInfos);
- Status executionStatus = err == ANEURALNETWORKS_NO_ERROR ? Status::SUCCESS : Status::ERROR;
- event->notify(executionStatus);
+ ErrorStatus status = err == ANEURALNETWORKS_NO_ERROR ?
+ ErrorStatus::NONE : ErrorStatus::GENERAL_FAILURE;
+ event->notify(status);
}
int RequestBuilder::startComputeOnCpu(const Model& model) {
diff --git a/runtime/include/NeuralNetworks.h b/runtime/include/NeuralNetworks.h
index 3785048..9f540ae 100644
--- a/runtime/include/NeuralNetworks.h
+++ b/runtime/include/NeuralNetworks.h
@@ -63,42 +63,34 @@
typedef enum {
/** The following entries are used to declare scalars. */
- /** A 16 bit floating point scalar value. */
- ANEURALNETWORKS_FLOAT16 = 0,
+ /** OEM specific scalar value. */
+ ANEURALNETWORKS_OEM = 0,
/** A 32 bit floating point scalar value. */
ANEURALNETWORKS_FLOAT32 = 1,
- /** A signed 8 bit integer scalar value. */
- ANEURALNETWORKS_INT8 = 2,
- /** An unsigned 8 bit integer scalar value. */
- ANEURALNETWORKS_UINT8 = 3,
- /** A signed 16 bit integer scalar value. */
- ANEURALNETWORKS_INT16 = 4,
- /** An unsigned 16 bit integer scalar value. */
- ANEURALNETWORKS_UINT16 = 5,
/** A signed 32 bit integer scalar value. */
- ANEURALNETWORKS_INT32 = 6,
+ ANEURALNETWORKS_INT32 = 2,
/** An unsigned 32 bit integer scalar value. */
- ANEURALNETWORKS_UINT32 = 7,
+ ANEURALNETWORKS_UINT32 = 3,
/** The following entries are used to declare tensors. */
- /** A tensor of 16 bit floating point values. */
- ANEURALNETWORKS_TENSOR_FLOAT16 = 8,
+ /** A tensor of OEM specific values. */
+ ANEURALNETWORKS_TENSOR_OEM_BYTE = 4,
/** A tensor of 32 bit floating point values. */
- ANEURALNETWORKS_TENSOR_FLOAT32 = 9,
+ ANEURALNETWORKS_TENSOR_FLOAT32 = 5,
/** A tensor of 32 bit integer values. */
- ANEURALNETWORKS_TENSOR_INT32 = 10,
+ ANEURALNETWORKS_TENSOR_INT32 = 6,
/** A tensor of 8 bit integers that represent real numbers.
*
* Attached to this tensor are two numbers that can be used to convert
- * the 8 bit integer to the real value and vice versa. These two numbers are:
+ * the 8 bit integer to the real value and vice versa. These two numbers are:
* - scale: a 32 bit floating point value
* - zero_value: an 32 bit integer
*
* The formula is:
* real_value = (integer_value - zero_value) * scale.
*/
- ANEURALNETWORKS_TENSOR_QUANT8_ASYMM = 11,
+ ANEURALNETWORKS_TENSOR_QUANT8_ASYMM = 7,
} OperandCode;
/**
diff --git a/runtime/include/NeuralNetworksWrapper.h b/runtime/include/NeuralNetworksWrapper.h
index 366cf8b..3e359f1 100644
--- a/runtime/include/NeuralNetworksWrapper.h
+++ b/runtime/include/NeuralNetworksWrapper.h
@@ -29,15 +29,11 @@
namespace wrapper {
enum class Type {
- FLOAT16 = ANEURALNETWORKS_FLOAT16,
+ OEM = ANEURALNETWORKS_OEM,
FLOAT32 = ANEURALNETWORKS_FLOAT32,
- INT8 = ANEURALNETWORKS_INT8,
- UINT8 = ANEURALNETWORKS_UINT8,
- INT16 = ANEURALNETWORKS_INT16,
- UINT16 = ANEURALNETWORKS_UINT16,
INT32 = ANEURALNETWORKS_INT32,
UINT32 = ANEURALNETWORKS_UINT32,
- TENSOR_FLOAT16 = ANEURALNETWORKS_TENSOR_FLOAT16,
+ TENSOR_OEM_BYTE = ANEURALNETWORKS_TENSOR_OEM_BYTE,
TENSOR_FLOAT32 = ANEURALNETWORKS_TENSOR_FLOAT32,
TENSOR_INT32 = ANEURALNETWORKS_TENSOR_INT32,
TENSOR_QUANT8_ASYMM = ANEURALNETWORKS_TENSOR_QUANT8_ASYMM,