Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,15 @@ enum NNAPIFlags {
// Please note for now, NNAPI perform worse using NCHW compare to using NHWC
NNAPI_FLAG_USE_NCHW = 0x002,

// Disable using NNAPI CPU implementation (nnapi-reference) for execution
// Please note, by enabling this option, it may cause the model cannot be executed using
// NNAPI execution provider.
// This option is only available after Android API level 29, and will be ignored for Android API level 28-
NNAPI_FLAG_CPU_DISABLED = 0x004,

// Keep NNAPI_FLAG_MAX at the end of the enum definition
// And assign the last NNAPIFlag to it
NNAPI_FLAG_LAST = NNAPI_FLAG_USE_NCHW,
NNAPI_FLAG_LAST = NNAPI_FLAG_CPU_DISABLED,
};

#ifdef __cplusplus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,23 @@ Status ModelBuilder::GetTargetDevices() {
for (uint32_t i = 0; i < num_devices; i++) {
ANeuralNetworksDevice* device = nullptr;
const char* device_name = nullptr;
int32_t device_type;
RETURN_STATUS_ON_ERROR_WITH_NOTE(
nnapi_->ANeuralNetworks_getDevice(i, &device), "Getting " + std::to_string(i) + "th device");

RETURN_STATUS_ON_ERROR_WITH_NOTE(nnapi_->ANeuralNetworksDevice_getName(device, &device_name),
"Getting " + std::to_string(i) + "th device's name");

RETURN_STATUS_ON_ERROR_WITH_NOTE(nnapi_->ANeuralNetworksDevice_getType(device, &device_type),
"Getting " + std::to_string(i) + "th device's type");

bool device_is_cpu = nnapi_cpu == device_name;
if ((target_device_option_ == TargetDeviceOption::CPU_DISABLED && !device_is_cpu) ||
(target_device_option_ == TargetDeviceOption::CPU_ONLY && device_is_cpu)) {
nnapi_target_devices_.push_back(device);
LOGS_DEFAULT(VERBOSE) << "Target device [" << device_name << "] added";
const auto device_detail = MakeString("[Name: [", device_name, "], Type [", device_type, "]], ");
nnapi_target_devices_detail_ += device_detail;
LOGS_DEFAULT(VERBOSE) << "Target device " << device_detail << " is added";
}
}

Expand Down Expand Up @@ -489,6 +495,7 @@ Status ModelBuilder::AddOperation(int op, const std::vector<uint32_t>& input_ind
output_indices.size(), &output_indices[0]),
"op = " + std::to_string(op));

num_nnapi_ops_++;
return Status::OK();
}

Expand All @@ -515,7 +522,34 @@ Status ModelBuilder::Compile(std::unique_ptr<Model>& model) {
nnapi_->ANeuralNetworksModel_finish(nnapi_model_->model_),
"on model finish");

// We have a list of target devices, try to see if the model can be run entirely
// using the list of target devices
bool use_create_for_devices = false;
if (!nnapi_target_devices_.empty()) {
bool supported_ops[num_nnapi_ops_];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think that the array needs to have a constant value as the dimension. interestingly, it seems only MSVC fails to compile something like this. https://godbolt.org/z/G96c3Y
maybe use std::unique_ptr<bool[]> instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know that, changed to use std::unique_ptr<bool[]>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool, would also suggest using onnxruntime::make_unique<bool[]>(num_nnapi_ops_)

RETURN_STATUS_ON_ERROR_WITH_NOTE(
nnapi_->ANeuralNetworksModel_getSupportedOperationsForDevices(
nnapi_model_->model_, nnapi_target_devices_.data(),
nnapi_target_devices_.size(), supported_ops),
"on getSupportedOperationsForDevices");

auto* it = std::find(supported_ops, supported_ops + num_nnapi_ops_, false);
if (it != supported_ops + num_nnapi_ops_) {
// There are some ops not supported by the list of the target devices
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: std::any_of may be slightly clearer

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change to std::all_of

// Fail the Compile
//
// TODO, add some logic to not fail for some cases
// Such as, if there are some acceptable fall back to cpu (nnapi-reference)
// and cpu is not in the target devices list
return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL,
"The model cannot run using current set of target devices, ",
nnapi_target_devices_detail_);
} else {
use_create_for_devices = true;
}
}

if (use_create_for_devices) {
RETURN_STATUS_ON_ERROR_WITH_NOTE(
nnapi_->ANeuralNetworksCompilation_createForDevices(
nnapi_model_->model_, nnapi_target_devices_.data(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ class ModelBuilder {

enum class TargetDeviceOption : int8_t {
ALL_DEVICES, // use all avaliable target devices
/* TODO support this option
SINGLE_DEVICE, // use a single target device, must be given

/* TODO support these options
PREFERRED_DEVICES, // Use one or more preferred devices (must be given)
EXCLUDED_DEVICES, // Exclude one or more devices (must be given)
*/

CPU_DISABLED, // use all avaliable target devices except CPU
CPU_ONLY, // use CPU only
};
Expand Down Expand Up @@ -74,6 +77,8 @@ class ModelBuilder {
// It is off by default
void SetUseFp16(bool use_fp16) { use_fp16_ = use_fp16; }

void SetTargetDeviceOption(TargetDeviceOption option) { target_device_option_ = option; }

// Set NNAPI execution preference
// Default preference is PREFER_SUSTAINED_SPEED
void ExecutePreference(
Expand Down Expand Up @@ -148,7 +153,10 @@ class ModelBuilder {

TargetDeviceOption target_device_option_{TargetDeviceOption::ALL_DEVICES};
std::vector<ANeuralNetworksDevice*> nnapi_target_devices_;
std::string nnapi_target_devices_detail_; // Debug info for target devices

// The number of nnapi operations in this model
size_t num_nnapi_ops_ = 0;
uint32_t next_index_ = 0;

// Convert the onnx model to ANeuralNetworksModel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,10 @@ common::Status NnapiExecutionProvider::Compile(const std::vector<FusedNodeAndGra
nnapi::ModelBuilder builder(graph_viewer);
builder.SetUseNCHW(nnapi_flags_ & NNAPI_FLAG_USE_NCHW);
builder.SetUseFp16(nnapi_flags_ & NNAPI_FLAG_USE_FP16);
if (nnapi_flags_ & NNAPI_FLAG_CPU_DISABLED) {
builder.SetTargetDeviceOption(nnapi::ModelBuilder::TargetDeviceOption::CPU_DISABLED);
}

std::unique_ptr<nnapi::Model> nnapi_model;
ORT_RETURN_IF_ERROR(builder.Compile(nnapi_model));

Expand Down