Skip to content

Commit

Permalink
The initial PR for NNAPI EP (microsoft#4287)
Browse files Browse the repository at this point in the history
* Move nnapi dnnlib to subfolder

* dnnlib compile settings

* add nnapi buildin build.py

* add onnxruntime_USE_NNAPI_BUILTIN

* compile using onnxruntime_USE_NNAPI_BUILTIN

* remove dnnlib from built in code

* Group onnxruntime_USE_NNAPI_BUILTIN sources

* add file stubs

* java 32bit compile error

* built in nnapi support 5-26

* init working version

* initializer support

* fix crash on free execution

* add dynamic input support

* bug fixes for dynamic input shape, add mul support, working on conv and batchnorm

* Add batchnormalization, add overflow check for int64 attributes

* add global average/max pool and reshape

* minor changes

* minor changes

* add skip relu and options to use different type of memory

* small bug fix for in operator relu

* bug fix for nnapi

* add transpose support, minor bug fix

* Add transpose support

* minor bug fixes, depthwise conv weight fix

* fixed the bug where the onnx model input has mismatch order than the nnapi model input

* add helper to add scalar operand

* add separated opbuilder to handle single operator

* add cast operator

* fixed reshape, moved some logs to verbose

* Add softmax and identity support, change shaper calling signature, and add support for int32 output

* changed the way to execute the NNAPI

* move NNMemory and InputOutputInfo into Model class

* add limited support for input dynamic shape

* add gemm support, fixed crash when allocating big array on stack

* add abs/exp/floor/log/sigmoid/neg/sin/sqrt/tanh support

* better dynamic input shape support;

* add more check for IsOpSupportedImpl, refactored some code

* some code style fix, switch to safeint

* Move opbuilders to a map with single instance, minor bug fixes

* add GetUniqueName for new temp tensors

* change from throw std to ort_throw

* build settings change and 3rd party notice update

* add readme for nnapi_lib, move to ort log, add comments to public functions, clean the code

* add android log sink and more logging changes, add new string for NnApiErrorDescription

* add nnapi execution options/fp16 relax

* fix a dnnlibrary build break

* addressed review comments

* address review comments, changed adding output for subgraph in NnapiExecutionProvider::GetCapability, minor issue fixes

* formatting in build.py

* more formatting fix in build.py, return fail status instead of throw in compute_func

* moved android_log_sink to platform folder, minor coding style changes

* addressed review comments
  • Loading branch information
guoyu-wang authored Jun 26, 2020
1 parent 37cbe85 commit 9e0f5fc
Showing 36 changed files with 5,727 additions and 20 deletions.
19 changes: 18 additions & 1 deletion ThirdPartyNotices.txt
Original file line number Diff line number Diff line change
@@ -3800,7 +3800,7 @@ SOFTWARE

nlohmann/json

MIT License
MIT License

Copyright (c) 2013-2019 Niels Lohmann

@@ -3953,3 +3953,20 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

-----

The Android Open Source Project

Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
12 changes: 11 additions & 1 deletion cgmanifests/cgmanifest.json
Original file line number Diff line number Diff line change
@@ -295,7 +295,17 @@
"DownloadUrl": "https://docs.nvidia.com/deeplearning/sdk/nccl-install-guide/index.html"
}
}
},
{
"component": {
"type": "git",
"git": {
"commitHash": "67afac65ce64fd4dce1494f43e565e8fe34bdffb",
"repositoryUrl": "https://android.googlesource.com/platform/frameworks/ml"
},
"comments": "used by onnxruntime"
}
}
],
"Version": 1
}
}
6 changes: 5 additions & 1 deletion cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -51,6 +51,7 @@ option(onnxruntime_USE_CUDA "Build with CUDA support" OFF)
option(onnxruntime_USE_OPENVINO "Build with OpenVINO support" OFF)
option(onnxruntime_USE_EIGEN_FOR_BLAS "Use eign for blas" ON)
option(onnxruntime_USE_NNAPI_DNNLIBRARY "Build with DNNLibrary for Android NNAPI support" OFF)
option(onnxruntime_USE_NNAPI_BUILTIN "Build with builtin NNAPI lib for Android NNAPI support" OFF)
option(onnxruntime_USE_RKNPU "Build with RKNPU support" OFF)
option(onnxruntime_USE_DNNL "Build with DNNL support" OFF)
option(onnxruntime_USE_MKLML "Build the default cpu provider with MKL-ML binary dependency" OFF)
@@ -181,6 +182,9 @@ if(onnxruntime_ENABLE_LTO)
endif()
endif()

if(onnxruntime_USE_NNAPI_BUILTIN AND onnxruntime_USE_NNAPI_DNNLIBRARY)
message(FATAL_ERROR "Please use only one of onnxruntime_USE_NNAPI_BUILTIN, onnxruntime_USE_NNAPI_DNNLIBRARY")
endif()

set(REPO_ROOT ${PROJECT_SOURCE_DIR}/..)
set(ONNXRUNTIME_ROOT ${PROJECT_SOURCE_DIR}/../onnxruntime)
@@ -845,7 +849,7 @@ if (onnxruntime_USE_CUDA)
else()
list(APPEND ONNXRUNTIME_CUDA_LIBRARIES cublas cudnn curand cufft)
endif()

if (WIN32)
link_directories(${onnxruntime_CUDNN_HOME}/lib/x64)

7 changes: 7 additions & 0 deletions cmake/onnxruntime_common.cmake
Original file line number Diff line number Diff line change
@@ -46,6 +46,13 @@ else()
"${ONNXRUNTIME_ROOT}/core/platform/posix/logging/*.cc"
)
endif()

if (CMAKE_SYSTEM_NAME STREQUAL "Android")
list(APPEND onnxruntime_common_src_patterns
"${ONNXRUNTIME_ROOT}/core/platform/android/logging/*.h"
"${ONNXRUNTIME_ROOT}/core/platform/android/logging/*.cc"
)
endif()
endif()

if(CMAKE_GENERATOR_PLATFORM)
2 changes: 1 addition & 1 deletion cmake/onnxruntime_java.cmake
Original file line number Diff line number Diff line change
@@ -76,7 +76,7 @@ endif()
if (onnxruntime_USE_TENSORRT)
target_compile_definitions(onnxruntime4j_jni PRIVATE USE_TENSORRT=1)
endif()
if (onnxruntime_USE_NNAPI_DNNLIBRARY)
if (onnxruntime_USE_NNAPI_DNNLIBRARY OR onnxruntime_USE_NNAPI_BUILTIN)
target_compile_definitions(onnxruntime4j_jni PRIVATE USE_NNAPI=1)
endif()
if (onnxruntime_USE_NUPHAR)
30 changes: 27 additions & 3 deletions cmake/onnxruntime_providers.cmake
Original file line number Diff line number Diff line change
@@ -59,7 +59,7 @@ if(onnxruntime_USE_TENSORRT)
set(PROVIDERS_TENSORRT onnxruntime_providers_tensorrt)
list(APPEND ONNXRUNTIME_PROVIDER_NAMES tensorrt)
endif()
if(onnxruntime_USE_NNAPI_DNNLIBRARY)
if(onnxruntime_USE_NNAPI_DNNLIBRARY OR onnxruntime_USE_NNAPI_BUILTIN)
set(PROVIDERS_NNAPI onnxruntime_providers_nnapi)
list(APPEND ONNXRUNTIME_PROVIDER_NAMES nnapi)
endif()
@@ -510,15 +510,17 @@ endif()

if (onnxruntime_USE_NNAPI_DNNLIBRARY)
add_definitions(-DUSE_NNAPI=1)
add_definitions(-DUSE_NNAPI_DNNLIBRARY=1)
option(DNN_READ_ONNX "" ON)
set(DNN_CUSTOM_PROTOC_EXECUTABLE ${ONNX_CUSTOM_PROTOC_EXECUTABLE})
option(DNN_CMAKE_INSTALL "" OFF)
option(DNN_BUILD_BIN "" OFF)
add_subdirectory(${REPO_ROOT}/cmake/external/DNNLibrary)
file(GLOB_RECURSE
file(GLOB
onnxruntime_providers_nnapi_cc_srcs CONFIGURE_DEPENDS
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/*.h"
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/*.cc"
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_dnnlibrary/*.h"
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_dnnlibrary/*.cc"
)
source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_nnapi_cc_srcs})
add_library(onnxruntime_providers_nnapi ${onnxruntime_providers_nnapi_cc_srcs})
@@ -533,6 +535,28 @@ if (onnxruntime_USE_NNAPI_DNNLIBRARY)
set_target_properties(onnxruntime_providers_nnapi PROPERTIES FOLDER "ONNXRuntime")
target_include_directories(onnxruntime_providers_nnapi PRIVATE ${ONNXRUNTIME_ROOT} ${nnapi_INCLUDE_DIRS})
set_target_properties(onnxruntime_providers_nnapi PROPERTIES LINKER_LANGUAGE CXX)
elseif (onnxruntime_USE_NNAPI_BUILTIN)
add_definitions(-DUSE_NNAPI=1)
add_definitions(-DUSE_NNAPI_BUILTIN=1)
file(GLOB
onnxruntime_providers_nnapi_cc_srcs_top CONFIGURE_DEPENDS
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/*.cc"
)
file(GLOB_RECURSE
onnxruntime_providers_nnapi_cc_srcs_nested CONFIGURE_DEPENDS
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/*.h"
"${ONNXRUNTIME_ROOT}/core/providers/nnapi/nnapi_builtin/*.cc"
)
set(onnxruntime_providers_nnapi_cc_srcs ${onnxruntime_providers_nnapi_cc_srcs_top} ${onnxruntime_providers_nnapi_cc_srcs_nested})
source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_nnapi_cc_srcs})
add_library(onnxruntime_providers_nnapi ${onnxruntime_providers_nnapi_cc_srcs})
onnxruntime_add_include_to_target(onnxruntime_providers_nnapi onnxruntime_common onnxruntime_framework onnx onnx_proto protobuf::libprotobuf-lite)
target_link_libraries(onnxruntime_providers_nnapi)
add_dependencies(onnxruntime_providers_nnapi onnx ${onnxruntime_EXTERNAL_DEPENDENCIES})
set_target_properties(onnxruntime_providers_nnapi PROPERTIES CXX_STANDARD_REQUIRED ON)
set_target_properties(onnxruntime_providers_nnapi PROPERTIES FOLDER "ONNXRuntime")
target_include_directories(onnxruntime_providers_nnapi PRIVATE ${ONNXRUNTIME_ROOT} ${nnapi_INCLUDE_DIRS})
set_target_properties(onnxruntime_providers_nnapi PROPERTIES LINKER_LANGUAGE CXX)
endif()

if (onnxruntime_USE_RKNPU)
12 changes: 6 additions & 6 deletions cmake/onnxruntime_unittests.cmake
Original file line number Diff line number Diff line change
@@ -206,7 +206,7 @@ if (onnxruntime_USE_NGRAPH)
list(APPEND onnxruntime_test_providers_src ${onnxruntime_test_providers_ngraph_src})
endif()

if (onnxruntime_USE_NNAPI_DNNLIBRARY)
if (onnxruntime_USE_NNAPI_DNNLIBRARY OR onnxruntime_USE_NNAPI_BUILTIN)
file(GLOB_RECURSE onnxruntime_test_providers_nnapi_src CONFIGURE_DEPENDS
"${TEST_SRC_DIR}/providers/nnapi/*"
)
@@ -302,7 +302,7 @@ if(onnxruntime_USE_OPENVINO)
list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_openvino)
endif()

if(onnxruntime_USE_NNAPI)
if(onnxruntime_USE_NNAPI_DNNLIBRARY OR onnxruntime_USE_NNAPI_BUILTIN)
list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_nnapi)
endif()

@@ -392,7 +392,7 @@ if(onnxruntime_USE_TENSORRT)
list(APPEND onnxruntime_test_providers_libs onnxruntime_providers_tensorrt)
endif()

if(onnxruntime_USE_NNAPI)
if(onnxruntime_USE_NNAPI_DNNLIBRARY OR onnxruntime_USE_NNAPI_BUILTIN)
list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/nnapi/*)
list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_nnapi)
list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_nnapi)
@@ -683,7 +683,7 @@ add_test(NAME onnx_test_pytorch_operator

if (CMAKE_SYSTEM_NAME STREQUAL "Android")
list(APPEND android_shared_libs log android)
if (onnxruntime_USE_NNAPI)
if (onnxruntime_USE_NNAPI_DNNLIBRARY)
list(APPEND android_shared_libs neuralnetworks)
endif()
endif()
@@ -857,7 +857,7 @@ if (onnxruntime_BUILD_JAVA)

# delegate to gradle's test runner
if(WIN32)
add_custom_command(TARGET custom_op_library POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:custom_op_library>
add_custom_command(TARGET custom_op_library POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:custom_op_library>
${JAVA_NATIVE_TEST_DIR}/$<TARGET_FILE_NAME:custom_op_library>)
# On windows ctest requires a test to be an .exe(.com) file
# So there are two options 1) Install Chocolatey and its gradle package
@@ -870,7 +870,7 @@ if (onnxruntime_BUILD_JAVA)
-DREPO_ROOT=${REPO_ROOT}
-P ${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime_java_unittests.cmake)
else()
add_custom_command(TARGET custom_op_library POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:custom_op_library>
add_custom_command(TARGET custom_op_library POST_BUILD COMMAND ${CMAKE_COMMAND} -E create_symlink $<TARGET_FILE:custom_op_library>
${JAVA_NATIVE_TEST_DIR}/$<TARGET_LINKER_FILE_NAME:custom_op_library>)
if (onnxruntime_USE_CUDA)
add_test(NAME onnxruntime4j_test COMMAND ${GRADLE_EXECUTABLE} cmakeCheck -DcmakeBuildDir=${CMAKE_CURRENT_BINARY_DIR} -DUSE_CUDA=1
44 changes: 44 additions & 0 deletions onnxruntime/core/platform/android/logging/android_log_sink.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#ifdef __ANDROID__
#include <android/log.h>

#include "core/common/logging/capture.h"
#include "core/common/logging/isink.h"
#include "core/platform/android/logging/android_log_sink.h"

namespace onnxruntime {
namespace logging {

void AndroidLogSink::SendImpl(const Timestamp& /* timestamp */, const std::string& logger_id, const Capture& message) {
std::ostringstream msg;

int severity = ANDROID_LOG_INFO;
switch (message.Severity()) {
case Severity::kVERBOSE:
severity = ANDROID_LOG_VERBOSE;
break;
case Severity::kINFO:
severity = ANDROID_LOG_INFO;
break;
case Severity::kWARNING:
severity = ANDROID_LOG_WARN;
break;
case Severity::kERROR:
severity = ANDROID_LOG_ERROR;
break;
case Severity::kFATAL:
severity = ANDROID_LOG_FATAL;
break;
}

msg << " [" << message.SeverityPrefix() << ":" << message.Category() << ":" << logger_id << ", "
<< message.Location().ToString() << "] " << message.Message() << std::endl;

__android_log_print(severity, message.Category(), "%s", msg.str().c_str());
}

} // namespace logging
} // namespace onnxruntime
#endif
20 changes: 20 additions & 0 deletions onnxruntime/core/platform/android/logging/android_log_sink.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once

#ifdef __ANDROID__
namespace onnxruntime {
namespace logging {
/// <summary>
/// A __android_log_print based ISink
/// </summary>
/// <seealso cref="ISink" />
class AndroidLogSink : public ISink {
public:
AndroidLogSink() = default;
void SendImpl(const Timestamp& timestamp, const std::string& logger_id, const Capture& message) override;
};
} // namespace logging
} // namespace onnxruntime
#endif
63 changes: 63 additions & 0 deletions onnxruntime/core/providers/nnapi/nnapi_builtin/builders/helper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//
// Created by daquexian on 5/21/18.
//
#pragma once

#include <core/common/common.h>
#include <string>

#include "core/providers/nnapi/nnapi_builtin/nnapi_lib/NeuralNetworksTypes.h"

#define THROW_ON_ERROR(val) \
{ \
const auto ret = (val); \
ORT_ENFORCE( \
ret == ANEURALNETWORKS_NO_ERROR, \
std::string("Error in ") + __FILE__ + std::string(":") + \
std::to_string(__LINE__) + std::string(", function name: ") + \
std::string(__func__) + "error, ret: " + GetErrorCause(ret)); \
}

#define THROW_ON_ERROR_WITH_NOTE(val, note) \
{ \
const auto ret = (val); \
ORT_ENFORCE( \
ret == ANEURALNETWORKS_NO_ERROR, \
std::string("Error in ") + __FILE__ + std::string(":") + \
std::to_string(__LINE__) + std::string(", function name: ") + \
std::string(__func__) + "error, ret: " + GetErrorCause(ret) + \
std::string(", ") + (note)); \
}

template <class Map, class Key>
inline bool Contains(const Map& map, const Key& key) {
return map.find(key) != map.end();
}

inline std::string GetErrorCause(int error_code) {
switch (error_code) {
case ANEURALNETWORKS_NO_ERROR:
return "ANEURALNETWORKS_NO_ERROR";
case ANEURALNETWORKS_OUT_OF_MEMORY:
return "ANEURALNETWORKS_OUT_OF_MEMORY";
case ANEURALNETWORKS_INCOMPLETE:
return "ANEURALNETWORKS_INCOMPLETE";
case ANEURALNETWORKS_UNEXPECTED_NULL:
return "ANEURALNETWORKS_UNEXPECTED_NULL";
case ANEURALNETWORKS_BAD_DATA:
return "ANEURALNETWORKS_BAD_DATA";
case ANEURALNETWORKS_OP_FAILED:
return "ANEURALNETWORKS_OP_FAILED";
case ANEURALNETWORKS_BAD_STATE:
return "ANEURALNETWORKS_BAD_STATE";
case ANEURALNETWORKS_UNMAPPABLE:
return "ANEURALNETWORKS_UNMAPPABLE";
case ANEURALNETWORKS_OUTPUT_INSUFFICIENT_SIZE:
return "ANEURALNETWORKS_OUTPUT_INSUFFICIENT_SIZE";
case ANEURALNETWORKS_UNAVAILABLE_DEVICE:
return "ANEURALNETWORKS_UNAVAILABLE_DEVICE";

default:
return "Unknown error code: " + std::to_string(error_code);
}
}
Loading

0 comments on commit 9e0f5fc

Please sign in to comment.