mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-07-30 20:18:08 +00:00
Add stub implementation of the NNAPI interface (#11288)
* Add stub implementation of the NNAPI interface so that model builder code can be unit tested on all platforms. Needed to fix a lot of type mismatch warnings. As these don't occur on Android builds used static_cast for simplicity.
This commit is contained in:
parent
a937920e24
commit
63d4f45186
15 changed files with 281 additions and 140 deletions
|
|
@ -956,13 +956,14 @@ if (onnxruntime_USE_NNAPI_BUILTIN)
|
|||
else()
|
||||
file(GLOB
|
||||
onnxruntime_providers_nnapi_cc_srcs_nested CONFIGURE_DEPENDS
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/model.*"
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.h"
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.cc"
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/builders/helper.h"
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/builders/helper.cc"
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/builders/op_support_checker.h"
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/builders/op_support_checker.cc"
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/builders/*.h"
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/builders/*.cc"
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/nnapi_lib/NeuralNetworksTypes.h"
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/nnapi_lib/NeuralNetworksWrapper.*"
|
||||
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/nnapi_lib/nnapi_implementation.*"
|
||||
)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ ModelBuilder::ModelBuilder(const GraphViewer& graph_viewer)
|
|||
: nnapi_(NnApiImplementation()), graph_viewer_(graph_viewer) {}
|
||||
|
||||
int32_t ModelBuilder::GetNNAPIFeatureLevel() const {
|
||||
return nnapi_ ? nnapi_->nnapi_runtime_feature_level : 0;
|
||||
return nnapi_ ? static_cast<int32_t>(nnapi_->nnapi_runtime_feature_level) : 0;
|
||||
}
|
||||
|
||||
// Scalar operand is copied into the model, no need to persist
|
||||
|
|
@ -530,8 +530,8 @@ Status ModelBuilder::AddOperation(int op, const std::vector<uint32_t>& input_ind
|
|||
|
||||
RETURN_STATUS_ON_ERROR_WITH_NOTE(
|
||||
nnapi_->ANeuralNetworksModel_addOperation(
|
||||
nnapi_model_->model_, op, input_indices.size(), &input_indices[0],
|
||||
output_indices.size(), &output_indices[0]),
|
||||
nnapi_model_->model_, op, static_cast<uint32_t>(input_indices.size()), &input_indices[0],
|
||||
static_cast<uint32_t>(output_indices.size()), &output_indices[0]),
|
||||
"op = " + std::to_string(op));
|
||||
|
||||
num_nnapi_ops_++;
|
||||
|
|
@ -574,7 +574,7 @@ Status ModelBuilder::Compile(std::unique_ptr<Model>& model) {
|
|||
RETURN_STATUS_ON_ERROR_WITH_NOTE(
|
||||
nnapi_->ANeuralNetworksModel_getSupportedOperationsForDevices(
|
||||
nnapi_model_->model_, nnapi_target_devices_.data(),
|
||||
nnapi_target_devices_.size(), supported_ops),
|
||||
static_cast<uint32_t>(nnapi_target_devices_.size()), supported_ops),
|
||||
"on getSupportedOperationsForDevices");
|
||||
|
||||
bool all_ops_supported = std::all_of(supported_ops, supported_ops + num_nnapi_ops_,
|
||||
|
|
@ -598,7 +598,7 @@ Status ModelBuilder::Compile(std::unique_ptr<Model>& model) {
|
|||
RETURN_STATUS_ON_ERROR_WITH_NOTE(
|
||||
nnapi_->ANeuralNetworksCompilation_createForDevices(
|
||||
nnapi_model_->model_, nnapi_target_devices_.data(),
|
||||
nnapi_target_devices_.size(), &nnapi_model_->compilation_),
|
||||
static_cast<uint32_t>(nnapi_target_devices_.size()), &nnapi_model_->compilation_),
|
||||
"on createForDevices");
|
||||
} else {
|
||||
RETURN_STATUS_ON_ERROR_WITH_NOTE(
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ static Status AddSqueezeOp(ModelBuilder& model_builder,
|
|||
if (axes.empty()) { // Squeeze all
|
||||
for (size_t i = 0; i < input_dims; i++) {
|
||||
if (input_shape[i] == 1)
|
||||
axes.push_back(i);
|
||||
axes.push_back(static_cast<int32_t>(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -725,12 +725,12 @@ Status TransposeOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, co
|
|||
const auto& output = node_unit.Outputs()[0].node_arg.Name();
|
||||
NodeAttrHelper helper(node_unit);
|
||||
std::vector<int32_t> perm = helper.Get("perm", std::vector<int32_t>());
|
||||
auto input_dims = shaper[input].size();
|
||||
auto input_dims = static_cast<int32_t>(shaper[input].size());
|
||||
if (perm.empty()) {
|
||||
for (int32_t i = input_dims - 1; i >= 0; i--)
|
||||
perm.push_back(i);
|
||||
} else {
|
||||
ORT_RETURN_IF_NOT(perm.size() == input_dims, "Perm and input should have same dimension");
|
||||
ORT_RETURN_IF_NOT(static_cast<int32_t>(perm.size()) == input_dims, "Perm and input should have same dimension");
|
||||
}
|
||||
|
||||
// Check if the quantization scale and ZP are correct
|
||||
|
|
@ -1980,7 +1980,7 @@ Status ConcatOpBuilder::AddToModelBuilderImpl(ModelBuilder& model_builder, const
|
|||
y_scale, y_zero_point));
|
||||
}
|
||||
|
||||
int rank = shaper[input0].size();
|
||||
int32_t rank = static_cast<int32_t>(shaper[input0].size());
|
||||
int32_t axis = static_cast<int32_t>(HandleNegativeAxis(helper.Get("axis", 1), rank));
|
||||
|
||||
ADD_SCALAR_OPERAND(model_builder, input_indices, axis);
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ Status Shaper::ReshapeImpl(const std::string& input_name,
|
|||
ORT_RETURN_IF_NOT(dim_i != 0, "NNAPI does not support 0 reshape dimension");
|
||||
if (dim_i == -1) {
|
||||
ORT_RETURN_IF_NOT(unk_dim_idx == -1, "Only one input dimension of Attr(shape) can be unknown!");
|
||||
unk_dim_idx = i;
|
||||
unk_dim_idx = static_cast<int>(i);
|
||||
} else {
|
||||
capacity *= dim_i;
|
||||
output_dimen[i] = static_cast<uint32_t>(dim_i);
|
||||
|
|
@ -260,7 +260,7 @@ Status Shaper::ReshapeImpl(const std::string& input_name,
|
|||
if (input_size == 0)
|
||||
output_dimen[unk_dim_idx] = 0;
|
||||
else
|
||||
output_dimen[unk_dim_idx] = input_size / capacity;
|
||||
output_dimen[unk_dim_idx] = static_cast<uint32_t>(input_size / capacity);
|
||||
|
||||
capacity *= output_dimen[unk_dim_idx];
|
||||
}
|
||||
|
|
@ -372,7 +372,7 @@ Status Shaper::SqueezeImpl(const std::string& input_name,
|
|||
const std::vector<int32_t>& axes,
|
||||
const std::string& output_name) {
|
||||
const Shape& input_dimen = shape_map_.at(input_name);
|
||||
int32_t input_size = input_dimen.size();
|
||||
int32_t input_size = static_cast<int32_t>(input_dimen.size());
|
||||
std::unordered_set<int32_t> axes_to_be_squeezed;
|
||||
|
||||
// If the Op is squeezing all by not specifying axes, the axes is pre-populate
|
||||
|
|
@ -403,11 +403,11 @@ Status Shaper::ResizeUsingScalesImpl(const std::string& input_name,
|
|||
const std::string& output_name) {
|
||||
Shape output_dimen = shape_map_.at(input_name);
|
||||
if (nchw) {
|
||||
output_dimen[2] *= scale_h;
|
||||
output_dimen[3] *= scale_w;
|
||||
output_dimen[2] = static_cast<uint32_t>(output_dimen[2] * scale_h);
|
||||
output_dimen[3] = static_cast<uint32_t>(output_dimen[3] * scale_w);
|
||||
} else { // nhwc
|
||||
output_dimen[1] *= scale_h;
|
||||
output_dimen[2] *= scale_w;
|
||||
output_dimen[1] = static_cast<uint32_t>(output_dimen[1] * scale_h);
|
||||
output_dimen[2] = static_cast<uint32_t>(output_dimen[2] * scale_w);
|
||||
}
|
||||
shape_map_[output_name] = output_dimen;
|
||||
return Status::OK();
|
||||
|
|
@ -458,4 +458,4 @@ void Shaper::Clear() {
|
|||
}
|
||||
|
||||
} // namespace nnapi
|
||||
} // namespace onnxruntime
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
|
@ -121,4 +122,4 @@ class Shaper {
|
|||
};
|
||||
|
||||
} // namespace nnapi
|
||||
} // namespace onnxruntime
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ Status Model::PrepareForExecution(std::unique_ptr<Execution>& execution) {
|
|||
}
|
||||
|
||||
int32_t Model::GetNNAPIFeatureLevel() const {
|
||||
return nnapi_ ? nnapi_->nnapi_runtime_feature_level : 0;
|
||||
return nnapi_ ? static_cast<int32_t>(nnapi_->nnapi_runtime_feature_level) : 0;
|
||||
}
|
||||
|
||||
#pragma region Model::NNMemory
|
||||
|
|
@ -159,7 +159,7 @@ Execution::~Execution() {
|
|||
Status Execution::SetInputBuffers(const std::vector<InputBuffer>& inputs) {
|
||||
for (size_t i = 0; i < inputs.size(); i++) {
|
||||
const auto& input(inputs[i]);
|
||||
ORT_RETURN_IF_ERROR(SetInputBuffer(i, input));
|
||||
ORT_RETURN_IF_ERROR(SetInputBuffer(static_cast<int32_t>(i), input));
|
||||
ORT_RETURN_IF_ERROR(shaper_.UpdateShape(input.name, input.type.dimensions));
|
||||
}
|
||||
|
||||
|
|
@ -169,7 +169,7 @@ Status Execution::SetInputBuffers(const std::vector<InputBuffer>& inputs) {
|
|||
|
||||
Status Execution::SetOutputBuffers(const std::vector<OutputBuffer>& outputs) {
|
||||
for (size_t i = 0; i < outputs.size(); i++) {
|
||||
ORT_RETURN_IF_ERROR(SetOutputBuffer(i, outputs[i]));
|
||||
ORT_RETURN_IF_ERROR(SetOutputBuffer(static_cast<int32_t>(i), outputs[i]));
|
||||
}
|
||||
|
||||
return Status::OK();
|
||||
|
|
@ -216,4 +216,4 @@ Status Execution::Predict(const std::vector<int32_t>& dynamic_outputs, std::vect
|
|||
#pragma endregion
|
||||
|
||||
} // namespace nnapi
|
||||
} // namespace onnxruntime
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -14,7 +14,9 @@ struct NnApi;
|
|||
namespace onnxruntime {
|
||||
namespace nnapi {
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#define USENNAPISHAREDMEM 1
|
||||
#endif
|
||||
|
||||
class Execution;
|
||||
|
||||
|
|
@ -189,4 +191,4 @@ class Execution {
|
|||
};
|
||||
|
||||
} // namespace nnapi
|
||||
} // namespace onnxruntime
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -10,17 +10,14 @@
|
|||
#include "core/platform/env.h"
|
||||
#include "core/providers/common.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/builders/helper.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/builders/model_builder.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/builders/op_support_checker.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/model.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/nnapi_lib/nnapi_implementation.h"
|
||||
#include "core/providers/partitioning_utils.h"
|
||||
#include "core/providers/shared/node_unit/node_unit.h"
|
||||
#include "core/session/onnxruntime_cxx_api.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "core/providers/nnapi/nnapi_builtin/builders/model_builder.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/model.h"
|
||||
#endif
|
||||
|
||||
namespace onnxruntime {
|
||||
|
||||
namespace {
|
||||
|
|
@ -239,6 +236,7 @@ static Status GetOutputBuffer(Ort::CustomOpApi& ort,
|
|||
|
||||
return Status::OK();
|
||||
}
|
||||
#endif // __ANDROID__
|
||||
|
||||
common::Status NnapiExecutionProvider::Compile(const std::vector<FusedNodeAndGraph>& fused_nodes_and_graphs,
|
||||
std::vector<NodeComputeInfo>& node_compute_funcs) {
|
||||
|
|
@ -355,6 +353,7 @@ common::Status NnapiExecutionProvider::Compile(const std::vector<FusedNodeAndGra
|
|||
ort.ReleaseTensorTypeAndShapeInfo(tensor_info);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
// From this point we will need to take the exclusive lock on the model until the Predict is
|
||||
// performed, to block other threads to perform Predict on the same model
|
||||
// TODO, investigate concurrent runs for different executions from the same model
|
||||
|
|
@ -439,29 +438,17 @@ common::Status NnapiExecutionProvider::Compile(const std::vector<FusedNodeAndGra
|
|||
memcpy(onnx_output_buffer, model_output_buffer, output_buffer_byte_size);
|
||||
}
|
||||
}
|
||||
|
||||
return Status::OK();
|
||||
#else
|
||||
// we have a stubbed out NNAPI implementation, so at this point there's nothing else we can do.
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED, "Model execution is not supported in this build.");
|
||||
#endif
|
||||
};
|
||||
|
||||
node_compute_funcs.push_back(compute_info);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
#else
|
||||
common::Status NnapiExecutionProvider::Compile(const std::vector<FusedNodeAndGraph>& fused_nodes_and_graphs,
|
||||
std::vector<NodeComputeInfo>& node_compute_funcs) {
|
||||
for (const auto& fused_node_and_graph : fused_nodes_and_graphs) {
|
||||
ORT_UNUSED_PARAMETER(fused_node_and_graph);
|
||||
NodeComputeInfo compute_info;
|
||||
compute_info.create_state_func = [](ComputeContext* /*context*/, FunctionState* /*state*/) { return 0; };
|
||||
compute_info.release_state_func = [](FunctionState /*state*/) {};
|
||||
compute_info.compute_func = [](FunctionState /* state */, const OrtCustomOpApi* /* api */,
|
||||
OrtKernelContext* /* context */) {
|
||||
return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED, "Compute is not supported in this build.");
|
||||
};
|
||||
node_compute_funcs.push_back(compute_info);
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
#endif // __ANDROID__
|
||||
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -42,8 +42,6 @@ class NnapiExecutionProvider : public IExecutionProvider {
|
|||
|
||||
const std::unordered_set<std::string> partitioning_stop_ops_;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
std::unordered_map<std::string, std::unique_ptr<onnxruntime::nnapi::Model>> nnapi_models_;
|
||||
#endif
|
||||
};
|
||||
} // namespace onnxruntime
|
||||
|
|
|
|||
|
|
@ -25,22 +25,22 @@ namespace wrapper {
|
|||
OperandType::OperandType(Type type, const std::vector<uint32_t>& d, float scale, int32_t zeroPoint)
|
||||
: type(type), dimensions(d) {
|
||||
operandType = {
|
||||
.type = static_cast<int32_t>(type),
|
||||
.dimensionCount = static_cast<uint32_t>(dimensions.size()),
|
||||
.dimensions = dimensions.size() > 0 ? dimensions.data() : nullptr,
|
||||
.scale = scale,
|
||||
.zeroPoint = zeroPoint,
|
||||
/*.type = */ static_cast<int32_t>(type),
|
||||
/*.dimensionCount = */ static_cast<uint32_t>(dimensions.size()),
|
||||
/*.dimensions = */ dimensions.size() > 0 ? dimensions.data() : nullptr,
|
||||
/*.scale = */ scale,
|
||||
/*.zeroPoint = */ zeroPoint,
|
||||
};
|
||||
}
|
||||
|
||||
OperandType::OperandType(Type type, const std::vector<uint32_t>& d, SymmPerChannelQuantParams&& channelQuant)
|
||||
: type(type), dimensions(d), channelQuant(std::move(channelQuant)) {
|
||||
operandType = {
|
||||
.type = static_cast<int32_t>(type),
|
||||
.dimensionCount = static_cast<uint32_t>(dimensions.size()),
|
||||
.dimensions = dimensions.size() > 0 ? dimensions.data() : nullptr,
|
||||
.scale = 0.0f,
|
||||
.zeroPoint = 0,
|
||||
/*.type = */ static_cast<int32_t>(type),
|
||||
/*.dimensionCount = */ static_cast<uint32_t>(dimensions.size()),
|
||||
/*.dimensions = */ dimensions.size() > 0 ? dimensions.data() : nullptr,
|
||||
/*.scale = */ 0.0f,
|
||||
/*.zeroPoint = */ 0,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -99,16 +99,16 @@ size_t OperandType::GetElementByteSize() const {
|
|||
|
||||
size_t OperandType::GetOperandBlobByteSize() const {
|
||||
// use uin64_t even dimension is uint32_t to prevent overflow
|
||||
uint64_t num_elements = std::accumulate(dimensions.begin(), dimensions.end(), 1, std::multiplies<uint64_t>());
|
||||
uint64_t num_elements = std::accumulate(dimensions.begin(), dimensions.end(), uint64_t(1), std::multiplies<uint64_t>());
|
||||
return SafeInt<size_t>(num_elements) * GetElementByteSize();
|
||||
}
|
||||
|
||||
void OperandType::SetDimensions(const std::vector<uint32_t>& d) {
|
||||
dimensions = d;
|
||||
operandType.dimensionCount = dimensions.size();
|
||||
operandType.dimensionCount = static_cast<uint32_t>(dimensions.size());
|
||||
operandType.dimensions = dimensions.size() > 0 ? dimensions.data() : nullptr;
|
||||
}
|
||||
|
||||
} // namespace wrapper
|
||||
} // namespace nn
|
||||
} // namespace android
|
||||
} // namespace android
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ enum class ExecutePreference {
|
|||
PREFER_SUSTAINED_SPEED = ANEURALNETWORKS_PREFER_SUSTAINED_SPEED
|
||||
};
|
||||
|
||||
// handle clash with existing #define on Windows
|
||||
#ifdef _MSC_VER
|
||||
#undef NO_ERROR
|
||||
#endif
|
||||
|
||||
enum class Result {
|
||||
NO_ERROR = ANEURALNETWORKS_NO_ERROR,
|
||||
OUT_OF_MEMORY = ANEURALNETWORKS_OUT_OF_MEMORY,
|
||||
|
|
@ -103,9 +108,9 @@ struct SymmPerChannelQuantParams {
|
|||
SymmPerChannelQuantParams(std::vector<float> scalesVec, uint32_t channelDim)
|
||||
: scales(std::move(scalesVec)) {
|
||||
params = {
|
||||
.channelDim = channelDim,
|
||||
.scaleCount = static_cast<uint32_t>(scales.size()),
|
||||
.scales = scales.size() > 0 ? scales.data() : nullptr,
|
||||
/*.channelDim = */ channelDim,
|
||||
/*.scaleCount =*/static_cast<uint32_t>(scales.size()),
|
||||
/*.scales = */ scales.size() > 0 ? scales.data() : nullptr,
|
||||
};
|
||||
}
|
||||
SymmPerChannelQuantParams(const SymmPerChannelQuantParams& other)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ limitations under the License.
|
|||
==============================================================================*/
|
||||
#include "nnapi_implementation.h"
|
||||
|
||||
// use real implementation on Android.
|
||||
// use stub on other platforms to allow unit testing model building.
|
||||
#if defined(__ANDROID__)
|
||||
#include <dlfcn.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/mman.h>
|
||||
|
|
@ -198,14 +201,10 @@ const NnApi LoadNnApi() {
|
|||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_finish);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperand);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_setOperandValue);
|
||||
LOAD_FUNCTION_OPTIONAL(
|
||||
libneuralnetworks,
|
||||
ANeuralNetworksModel_setOperandSymmPerChannelQuantParams);
|
||||
LOAD_FUNCTION(libneuralnetworks,
|
||||
ANeuralNetworksModel_setOperandValueFromMemory);
|
||||
LOAD_FUNCTION_OPTIONAL(libneuralnetworks, ANeuralNetworksModel_setOperandSymmPerChannelQuantParams);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_setOperandValueFromMemory);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_addOperation);
|
||||
LOAD_FUNCTION(libneuralnetworks,
|
||||
ANeuralNetworksModel_identifyInputsAndOutputs);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksModel_identifyInputsAndOutputs);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_create);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_free);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksCompilation_setPreference);
|
||||
|
|
@ -215,8 +214,7 @@ const NnApi LoadNnApi() {
|
|||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInput);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setInputFromMemory);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setOutput);
|
||||
LOAD_FUNCTION(libneuralnetworks,
|
||||
ANeuralNetworksExecution_setOutputFromMemory);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_setOutputFromMemory);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksExecution_startCompute);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_wait);
|
||||
LOAD_FUNCTION(libneuralnetworks, ANeuralNetworksEvent_free);
|
||||
|
|
@ -331,6 +329,173 @@ const NnApi LoadNnApi() {
|
|||
|
||||
} // namespace
|
||||
|
||||
#else
|
||||
//
|
||||
// Stub out the API with default implementations that do nothing.
|
||||
//
|
||||
#include "core/providers/nnapi/nnapi_builtin/builders/helper.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/nnapi_lib/NeuralNetworksTypes.h"
|
||||
|
||||
const NnApi LoadNnApi() {
|
||||
NnApi nnapi = {};
|
||||
nnapi.android_sdk_version = ORT_NNAPI_MAX_SUPPORTED_API_LEVEL;
|
||||
nnapi.nnapi_runtime_feature_level = ANEURALNETWORKS_FEATURE_LEVEL_5;
|
||||
|
||||
nnapi.ANeuralNetworksMemory_createFromFd =
|
||||
[](size_t, int, int, size_t, ANeuralNetworksMemory**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksMemory_free = [](ANeuralNetworksMemory*) {};
|
||||
nnapi.ANeuralNetworksModel_create = [](ANeuralNetworksModel**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksModel_free = [](ANeuralNetworksModel*) {};
|
||||
nnapi.ANeuralNetworksModel_finish = [](ANeuralNetworksModel*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksModel_addOperand = [](ANeuralNetworksModel*, const ANeuralNetworksOperandType*) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksModel_setOperandValue = [](ANeuralNetworksModel*, int32_t, const void*, size_t) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksModel_setOperandSymmPerChannelQuantParams =
|
||||
[](ANeuralNetworksModel*, int32_t, const ANeuralNetworksSymmPerChannelQuantParams*) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksModel_setOperandValueFromMemory =
|
||||
[](ANeuralNetworksModel*, int32_t, const ANeuralNetworksMemory*, size_t, size_t) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksModel_addOperation =
|
||||
[](ANeuralNetworksModel*, ANeuralNetworksOperationType, uint32_t, const uint32_t*, uint32_t, const uint32_t*) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksModel_identifyInputsAndOutputs =
|
||||
[](ANeuralNetworksModel*, uint32_t, const uint32_t*, uint32_t, const uint32_t*) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksModel_relaxComputationFloat32toFloat16 =
|
||||
[](ANeuralNetworksModel*, bool) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksCompilation_create =
|
||||
[](ANeuralNetworksModel*, ANeuralNetworksCompilation**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksCompilation_free = [](ANeuralNetworksCompilation*) {};
|
||||
nnapi.ANeuralNetworksCompilation_setPreference =
|
||||
[](ANeuralNetworksCompilation*, int32_t) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksCompilation_finish =
|
||||
[](ANeuralNetworksCompilation*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksExecution_create =
|
||||
[](ANeuralNetworksCompilation*, ANeuralNetworksExecution**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksExecution_free = [](ANeuralNetworksExecution*) {};
|
||||
nnapi.ANeuralNetworksExecution_setInput =
|
||||
[](ANeuralNetworksExecution*, int32_t, const ANeuralNetworksOperandType*, const void*, size_t) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksExecution_setInputFromMemory =
|
||||
[](ANeuralNetworksExecution*, int32_t, const ANeuralNetworksOperandType*, const ANeuralNetworksMemory*, size_t, size_t) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksExecution_setOutput =
|
||||
[](ANeuralNetworksExecution*, int32_t, const ANeuralNetworksOperandType*, void*, size_t) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksExecution_setOutputFromMemory =
|
||||
[](ANeuralNetworksExecution*, int32_t, const ANeuralNetworksOperandType*, const ANeuralNetworksMemory*, size_t, size_t) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksExecution_startCompute =
|
||||
[](ANeuralNetworksExecution*, ANeuralNetworksEvent**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksEvent_wait = [](ANeuralNetworksEvent*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksEvent_free = [](ANeuralNetworksEvent*) {};
|
||||
nnapi.ASharedMemory_create = [](const char*, size_t) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworks_getDeviceCount = [](uint32_t*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworks_getDevice = [](uint32_t, ANeuralNetworksDevice**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksDevice_getName =
|
||||
[](const ANeuralNetworksDevice*, const char**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksDevice_getVersion =
|
||||
[](const ANeuralNetworksDevice*, const char**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksDevice_getFeatureLevel =
|
||||
[](const ANeuralNetworksDevice*, int64_t* feature_level) {
|
||||
*feature_level = ANEURALNETWORKS_FEATURE_LEVEL_5;
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksDevice_getType =
|
||||
[](const ANeuralNetworksDevice*, int32_t*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksModel_getSupportedOperationsForDevices =
|
||||
[](const ANeuralNetworksModel*, const ANeuralNetworksDevice* const*, uint32_t, bool*) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksCompilation_createForDevices =
|
||||
[](ANeuralNetworksModel*, const ANeuralNetworksDevice* const*, uint32_t, ANeuralNetworksCompilation**) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksCompilation_setCaching =
|
||||
[](ANeuralNetworksCompilation*, const char*, const uint8_t*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksCompilation_setTimeout =
|
||||
[](ANeuralNetworksCompilation*, uint64_t) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksCompilation_setPriority =
|
||||
[](ANeuralNetworksCompilation*, int) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksExecution_compute =
|
||||
[](ANeuralNetworksExecution*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksExecution_setTimeout =
|
||||
[](ANeuralNetworksExecution*, uint64_t) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksExecution_setLoopTimeout =
|
||||
[](ANeuralNetworksExecution*, uint64_t) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksExecution_getOutputOperandRank =
|
||||
[](ANeuralNetworksExecution*, int32_t, uint32_t*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksExecution_getOutputOperandDimensions =
|
||||
[](ANeuralNetworksExecution*, int32_t, uint32_t*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksBurst_create =
|
||||
[](ANeuralNetworksCompilation*, ANeuralNetworksBurst**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksBurst_free = [](ANeuralNetworksBurst*) {};
|
||||
nnapi.ANeuralNetworksExecution_burstCompute =
|
||||
[](ANeuralNetworksExecution*, ANeuralNetworksBurst*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksMemory_createFromAHardwareBuffer =
|
||||
[](const AHardwareBuffer*, ANeuralNetworksMemory**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksExecution_setMeasureTiming =
|
||||
[](ANeuralNetworksExecution*, bool) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksExecution_getDuration =
|
||||
[](const ANeuralNetworksExecution*, int32_t, uint64_t*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksDevice_getExtensionSupport =
|
||||
[](const ANeuralNetworksDevice*, const char*, bool*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksModel_getExtensionOperandType =
|
||||
[](ANeuralNetworksModel*, const char*, uint16_t, int32_t*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksModel_getExtensionOperationType =
|
||||
[](ANeuralNetworksModel*, const char*, uint16_t, ANeuralNetworksOperationType*) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksModel_setOperandExtensionData =
|
||||
[](ANeuralNetworksModel*, int32_t, const void*, size_t) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksMemoryDesc_create = [](ANeuralNetworksMemoryDesc**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksMemoryDesc_free = [](ANeuralNetworksMemoryDesc*) {};
|
||||
nnapi.ANeuralNetworksMemoryDesc_addInputRole =
|
||||
[](ANeuralNetworksMemoryDesc*, const ANeuralNetworksCompilation*, uint32_t, float) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksMemoryDesc_addOutputRole =
|
||||
[](ANeuralNetworksMemoryDesc*, const ANeuralNetworksCompilation*, uint32_t, float) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksMemoryDesc_setDimensions =
|
||||
[](ANeuralNetworksMemoryDesc*, uint32_t, const uint32_t*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksMemoryDesc_finish =
|
||||
[](ANeuralNetworksMemoryDesc*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksMemory_createFromDesc =
|
||||
[](const ANeuralNetworksMemoryDesc*, ANeuralNetworksMemory**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksMemory_copy =
|
||||
[](const ANeuralNetworksMemory*, const ANeuralNetworksMemory*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksEvent_createFromSyncFenceFd =
|
||||
[](int, ANeuralNetworksEvent**) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksEvent_getSyncFenceFd =
|
||||
[](const ANeuralNetworksEvent*, int*) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksExecution_startComputeWithDependencies =
|
||||
[](ANeuralNetworksExecution*, const ANeuralNetworksEvent* const*, uint32_t, uint64_t, ANeuralNetworksEvent**) {
|
||||
return int(ANEURALNETWORKS_NO_ERROR);
|
||||
};
|
||||
nnapi.ANeuralNetworksExecution_enableInputAndOutputPadding =
|
||||
[](ANeuralNetworksExecution*, bool) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworksExecution_setReusable =
|
||||
[](ANeuralNetworksExecution*, bool) { return int(ANEURALNETWORKS_NO_ERROR); };
|
||||
nnapi.ANeuralNetworks_getRuntimeFeatureLevel = []() { return int64_t(ANEURALNETWORKS_FEATURE_LEVEL_5); };
|
||||
|
||||
return nnapi;
|
||||
}
|
||||
#endif // defined(__ANDROID__)
|
||||
|
||||
const NnApi* NnApiImplementation() {
|
||||
static const NnApi nnapi = LoadNnApi();
|
||||
return &nnapi;
|
||||
|
|
|
|||
|
|
@ -8,16 +8,17 @@ These files do not need to be updated frequently, unless new functionalities are
|
|||
introduced in new Android OS versions, and we will integrate the new functionalities.
|
||||
|
||||
The modifications to these files,
|
||||
NeuralNetworksTypes.h
|
||||
* The enum ANEURALNETWORKS_MAX_SIZE_OF_IMMEDIATELY_COPIED_VALUES was added.
|
||||
* The operation ANEURALNETWORKS_GROUPED_CONV_2D was added.
|
||||
nnapi_implementation.h/cc
|
||||
* CreateNnApiFromSupportLibrary was removed
|
||||
[TODO, add support of CreateNnApiFromSupportLibrary for Android 12]
|
||||
NeuralNetworksTypes.h
|
||||
* The enum ANEURALNETWORKS_MAX_SIZE_OF_IMMEDIATELY_COPIED_VALUES was added.
|
||||
* The operation ANEURALNETWORKS_GROUPED_CONV_2D was added.
|
||||
nnapi_implementation.h/cc
|
||||
* CreateNnApiFromSupportLibrary was removed
|
||||
* A stub implementation was added to enable unit testing on non-Android platforms
|
||||
* [TODO, add support of CreateNnApiFromSupportLibrary for Android 12]
|
||||
|
||||
2. Files: NeuralNetworksWrapper.h
|
||||
NeuralNetworksWrapper.cc
|
||||
This NeuralNetworksWrapper.h is copied from The Android Open Source Project
|
||||
https://android.googlesource.com/platform/frameworks/ml/+/refs/heads/master/nn/runtime/include/
|
||||
This file is heavily modified, and an extra NeuralNetworksWrapper.cc was added.
|
||||
Please do not update these files.
|
||||
This NeuralNetworksWrapper.h is copied from The Android Open Source Project
|
||||
* https://android.googlesource.com/platform/frameworks/ml/+/refs/heads/master/nn/runtime/include/
|
||||
This file is heavily modified, and an extra NeuralNetworksWrapper.cc was added.
|
||||
Please do not update these files.
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD)
|
||||
#include "core/common/logging/logging.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/builders/op_builder.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/builders/op_support_checker.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/nnapi_execution_provider.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/nnapi_lib/NeuralNetworksTypes.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/nnapi_lib/nnapi_implementation.h"
|
||||
|
|
@ -16,23 +18,15 @@
|
|||
#include "test/util/include/test/test_environment.h"
|
||||
#include "test/util/include/test_utils.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include "core/providers/nnapi/nnapi_builtin/builders/op_builder.h"
|
||||
#include "core/providers/nnapi/nnapi_builtin/builders/op_support_checker.h"
|
||||
#endif
|
||||
|
||||
#if !defined(ORT_MINIMAL_BUILD)
|
||||
// if this is a full build we need the provider test utils
|
||||
#include "test/providers/provider_test_utils.h"
|
||||
#include "test/optimizer/qdq_test_utils.h"
|
||||
#endif
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
#if !defined(ORT_MINIMAL_BUILD)
|
||||
#include "test/optimizer/qdq_test_utils.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
using namespace ONNX_NAMESPACE;
|
||||
using namespace ::onnxruntime::logging;
|
||||
|
|
@ -42,6 +36,17 @@ namespace test {
|
|||
|
||||
#if !defined(ORT_MINIMAL_BUILD)
|
||||
|
||||
namespace {
|
||||
void TestModelLoad(const ORTCHAR_T* model_file_name, const std::function<void(const Graph&)>& check_graph) {
|
||||
SessionOptions so;
|
||||
InferenceSessionWrapper session_object{so, GetEnvironment()};
|
||||
ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(std::make_unique<NnapiExecutionProvider>(0)));
|
||||
ASSERT_STATUS_OK(session_object.Load(model_file_name));
|
||||
ASSERT_STATUS_OK(session_object.Initialize());
|
||||
check_graph(session_object.GetGraph());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Since NNAPI EP handles Reshape and Flatten differently,
|
||||
// Please see ReshapeOpBuilder::CanSkipReshape in
|
||||
// <repo_root>/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/op_builder.cc
|
||||
|
|
@ -69,13 +74,9 @@ TEST(NnapiExecutionProviderTest, ReshapeFlattenTest) {
|
|||
feeds);
|
||||
#else
|
||||
// test load only
|
||||
SessionOptions so;
|
||||
InferenceSessionWrapper session_object{so, GetEnvironment()};
|
||||
ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(std::make_unique<NnapiExecutionProvider>(0)));
|
||||
ASSERT_STATUS_OK(session_object.Load(model_file_name));
|
||||
ASSERT_STATUS_OK(session_object.Initialize());
|
||||
ASSERT_GT(CountAssignedNodes(session_object.GetGraph(), kNnapiExecutionProvider), 0)
|
||||
<< "Some nodes should have been taken by the NNAPI EP";
|
||||
TestModelLoad(model_file_name,
|
||||
[](const Graph& graph) { ASSERT_GT(CountAssignedNodes(graph, kNnapiExecutionProvider), 0)
|
||||
<< "Some nodes should have been taken by the NNAPI EP"; });
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -100,14 +101,9 @@ TEST(NnapiExecutionProviderTest, DynamicGraphInputTest) {
|
|||
std::make_unique<NnapiExecutionProvider>(0),
|
||||
feeds);
|
||||
#else
|
||||
// test load only
|
||||
SessionOptions so;
|
||||
InferenceSessionWrapper session_object{so, GetEnvironment()};
|
||||
ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(std::make_unique<NnapiExecutionProvider>(0)));
|
||||
ASSERT_STATUS_OK(session_object.Load(model_file_name));
|
||||
ASSERT_STATUS_OK(session_object.Initialize());
|
||||
ASSERT_EQ(CountAssignedNodes(session_object.GetGraph(), kNnapiExecutionProvider), 1)
|
||||
<< "Exactly one node (Add) should have been taken by the NNAPI EP";
|
||||
TestModelLoad(model_file_name,
|
||||
[](const Graph& graph) { ASSERT_EQ(CountAssignedNodes(graph, kNnapiExecutionProvider), 1)
|
||||
<< "Exactly one node (Add) should have been taken by the NNAPI EP"; });
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -133,14 +129,9 @@ TEST(NnapiExecutionProviderTest, InternalUint8SupportTest) {
|
|||
std::make_unique<NnapiExecutionProvider>(0),
|
||||
feeds);
|
||||
#else
|
||||
// test load only
|
||||
SessionOptions so;
|
||||
InferenceSessionWrapper session_object{so, GetEnvironment()};
|
||||
ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(std::make_unique<NnapiExecutionProvider>(0)));
|
||||
ASSERT_STATUS_OK(session_object.Load(model_file_name));
|
||||
ASSERT_STATUS_OK(session_object.Initialize());
|
||||
ASSERT_GT(CountAssignedNodes(session_object.GetGraph(), kNnapiExecutionProvider), 0)
|
||||
<< "Some nodes should have been taken by the NNAPI EP";
|
||||
TestModelLoad(model_file_name,
|
||||
[](const Graph& graph) { ASSERT_GT(CountAssignedNodes(graph, kNnapiExecutionProvider), 0)
|
||||
<< "Some nodes should have been taken by the NNAPI EP"; });
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -217,14 +208,9 @@ TEST(NnapiExecutionProviderTest, FunctionTest) {
|
|||
std::make_unique<NnapiExecutionProvider>(0),
|
||||
feeds);
|
||||
#else
|
||||
// test load only
|
||||
SessionOptions so;
|
||||
InferenceSessionWrapper session_object{so, GetEnvironment()};
|
||||
ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(std::make_unique<NnapiExecutionProvider>(0)));
|
||||
ASSERT_STATUS_OK(session_object.Load(model_file_name));
|
||||
ASSERT_STATUS_OK(session_object.Initialize());
|
||||
ASSERT_GT(CountAssignedNodes(session_object.GetGraph(), kNnapiExecutionProvider), 0)
|
||||
<< "Some nodes should have been taken by the NNAPI EP";
|
||||
TestModelLoad(model_file_name,
|
||||
[](const Graph& graph) { ASSERT_GT(CountAssignedNodes(graph, kNnapiExecutionProvider), 0)
|
||||
<< "Some nodes should have been taken by the NNAPI EP"; });
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -267,11 +253,9 @@ TEST(NnapiExecutionProviderTest, TestNoShapeInputModel) {
|
|||
// verify the entire graph will not be assigned to NNAPI EP
|
||||
SessionOptions so;
|
||||
InferenceSessionWrapper session_object{so, GetEnvironment()};
|
||||
ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(std::make_unique<NnapiExecutionProvider>(0)));
|
||||
ASSERT_STATUS_OK(session_object.Load(model_file_name));
|
||||
ASSERT_STATUS_OK(session_object.Initialize());
|
||||
ASSERT_EQ(CountAssignedNodes(session_object.GetGraph(), kNnapiExecutionProvider), 0)
|
||||
<< "No node should be taken by the NNAPI EP";
|
||||
TestModelLoad(model_file_name,
|
||||
[](const Graph& graph) { ASSERT_EQ(CountAssignedNodes(graph, kNnapiExecutionProvider), 0)
|
||||
<< "No nodes should have been taken by the NNAPI EP"; });
|
||||
}
|
||||
|
||||
static void RunQDQModelTest(
|
||||
|
|
@ -520,13 +504,10 @@ TEST(NnapiExecutionProviderTest, TestOrtFormatModel) {
|
|||
feeds);
|
||||
#else
|
||||
// test load only
|
||||
SessionOptions so;
|
||||
InferenceSessionWrapper session_object{so, GetEnvironment()};
|
||||
ASSERT_STATUS_OK(session_object.RegisterExecutionProvider(std::make_unique<NnapiExecutionProvider>(0)));
|
||||
ASSERT_STATUS_OK(session_object.Load(model_file_name));
|
||||
ASSERT_STATUS_OK(session_object.Initialize());
|
||||
ASSERT_GT(CountAssignedNodes(session_object.GetGraph(), kNnapiExecutionProvider), 0)
|
||||
<< "Some nodes should have been taken by the NNAPI EP";
|
||||
TestModelLoad(model_file_name,
|
||||
[](const Graph& graph) { ASSERT_GT(CountAssignedNodes(graph, kNnapiExecutionProvider), 0)
|
||||
<< "Some nodes should have been taken by the NNAPI EP"; });
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -133,8 +133,8 @@ std::unique_ptr<IExecutionProvider> DefaultNupharExecutionProvider(bool allow_un
|
|||
// }
|
||||
|
||||
std::unique_ptr<IExecutionProvider> DefaultNnapiExecutionProvider() {
|
||||
// For any non - Android system, NNAPI will only be used for ort model converter
|
||||
// Make it unavailable here, you can still manually append NNAPI EP to session for model conversion
|
||||
// The NNAPI EP uses a stub implementation on non-Android platforms so cannot be used to execute a model.
|
||||
// Manually append an NNAPI EP instance to the session to unit test the GetCapability and Compile implementation.
|
||||
#if defined(USE_NNAPI) && defined(__ANDROID__)
|
||||
return CreateExecutionProviderFactory_Nnapi(0, {})->CreateProvider();
|
||||
#else
|
||||
|
|
|
|||
Loading…
Reference in a new issue