aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Eilers <jan.eilers@arm.com>2021-12-08 10:05:47 +0000
committerKeith Davis <keith.davis@arm.com>2022-06-29 10:04:20 +0100
commita96489a2fd459bd3d73297fa5fdaef5d13a57a4e (patch)
tree2299402be2854c1bd508f57a35edc5c9059961f6
parent764ac655bd301ffc8cde4c912e67499954f9ef8f (diff)
downloadarmnn-a96489a2fd459bd3d73297fa5fdaef5d13a57a4e.tar.gz
Add jni interface for the ArmNN Delegate
* adds a version script to hide away all symbols that are not required to use the interface * the main purpose of the jni interface is to enable the delegate to be used in android apps * Add static building to patch - see patch 7 for JNI patch only Signed-off-by: Jan Eilers <jan.eilers@arm.com> Signed-off-by: Keith Davis <keith.davis@arm.com> Change-Id: I9bb2d698b5fdb0d1b30cf79e6f19746310cd61b2
-rw-r--r--CMakeLists.txt32
-rw-r--r--cmake/GlobalConfig.cmake3
-rw-r--r--delegate/CMakeLists.txt8
-rw-r--r--delegate/armnnDelegateJNI/CMakeLists.txt62
-rw-r--r--delegate/armnnDelegateJNI/README.md15
-rw-r--r--delegate/armnnDelegateJNI/README.md.license4
-rw-r--r--delegate/armnnDelegateJNI/src/armnn_delegate_jni.cpp98
-rw-r--r--delegate/armnnDelegateJNI/version_script15
8 files changed, 224 insertions, 13 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1fcadb0475..c112accdf4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,13 +60,6 @@ add_subdirectory(src/armnnSerializer)
add_subdirectory(src/armnnDeserializer)
add_subdirectory(src/armnnTestUtils)
-
-if (BUILD_ARMNN_TFLITE_DELEGATE)
- set(ARMNN_SUB_PROJECT ON)
- add_subdirectory(delegate)
- add_definitions(-DARMNN_TF_LITE_DELEGATE)
-endif()
-
if (BUILD_TESTS)
add_subdirectory(tests)
endif()
@@ -443,20 +436,35 @@ foreach(lib ${armnnLibraries})
list(APPEND armnn_sources $<TARGET_OBJECTS:${lib}>)
endforeach()
+# The delegate needs to be placed after armnnLibraries has been fully populated. The armnn_delegate_jni library
+# requires a static armnn build.
+# Explanation:
+# Because backends are added as object libraries they won't be linked to armnn when building armnn statically.
+# A target that uses a static armnn library has to link to the object libraries in the variable armnnLibraries
+# manually to include all symbols from backends.
+if (BUILD_ARMNN_TFLITE_DELEGATE)
+ set(ARMNN_SUB_PROJECT ON)
+ set(ARMNN_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+ add_subdirectory(delegate)
+ add_definitions(-DARMNN_TF_LITE_DELEGATE)
+endif()
+
if(BUILD_BARE_METAL)
add_library_ex(armnn STATIC ${armnn_sources})
else()
- add_library_ex(armnn SHARED ${armnn_sources})
+ if (BUILD_SHARED_LIBS)
+ add_library_ex(armnn SHARED ${armnn_sources})
+ else()
+ add_library(armnn ${armnn_sources})
+ endif()
endif()
target_compile_definitions(armnn PRIVATE "ARMNN_COMPILING_DLL")
# Generate a map file for debug mode only
-if(CMAKE_BUILD_TYPE MATCHES debug)
- set_property(TARGET armnn APPEND_STRING PROPERTY
+set_property(TARGET armnn APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-Map=libarmnnMapFile.map")
- message(STATUS "Linker will generate mapfile " )
-endif()
+message(STATUS "Linker will generate mapfile ")
target_include_directories(armnn
PUBLIC
diff --git a/cmake/GlobalConfig.cmake b/cmake/GlobalConfig.cmake
index a5c17d5749..d5cdca2b56 100644
--- a/cmake/GlobalConfig.cmake
+++ b/cmake/GlobalConfig.cmake
@@ -35,6 +35,9 @@ option(BUILD_PIPE_ONLY "Build the PIPE libraries only" OFF)
option(BUILD_ARMNN_TFLITE_DELEGATE "Build the Arm NN TfLite delegate" OFF)
option(BUILD_MEMORY_STRATEGY_BENCHMARK "Build the MemoryBenchmark" OFF)
option(BUILD_BARE_METAL "Disable features requiring operating system support" OFF)
+option(BUILD_SHARED_LIBS "Determines if Armnn will be built statically or dynamically.
+ This is an experimental feature and not fully supported.
+ Only the ArmNN core and the Delegate can be built statically." ON)
include(SelectLibraryConfigurations)
diff --git a/delegate/CMakeLists.txt b/delegate/CMakeLists.txt
index 523214bb90..01dde4ebce 100644
--- a/delegate/CMakeLists.txt
+++ b/delegate/CMakeLists.txt
@@ -54,7 +54,7 @@ list(APPEND armnnDelegate_sources
src/Unpack.hpp
src/Transpose.hpp)
-add_library(armnnDelegate SHARED ${armnnDelegate_sources})
+add_library(armnnDelegate ${armnnDelegate_sources})
target_include_directories(armnnDelegate
PUBLIC
@@ -254,6 +254,12 @@ if(BUILD_UNIT_TESTS)
endif()
+option(BUILD_DELEGATE_JNI_INTERFACE "Builds a library to allow accessing the Arm NN delegate from Java code.
+ This is an experimental feature." Off)
+if(BUILD_DELEGATE_JNI_INTERFACE)
+ add_subdirectory(armnnDelegateJNI)
+endif()
+
####################################################
## Export targets
set(armnn_delegate_export_targets)
diff --git a/delegate/armnnDelegateJNI/CMakeLists.txt b/delegate/armnnDelegateJNI/CMakeLists.txt
new file mode 100644
index 0000000000..06eb3bf8e3
--- /dev/null
+++ b/delegate/armnnDelegateJNI/CMakeLists.txt
@@ -0,0 +1,62 @@
+#
+# Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+# SPDX-License-Identifier: MIT
+#
+
+cmake_minimum_required(VERSION 3.7.0)
+
+project("armnn_delegate_jni")
+
+# JNI is needed for jni calls
+find_package(JNI)
+
+list(APPEND jni_delegate_sources
+ src/armnn_delegate_jni.cpp)
+
+# the backends under src/backends extend the list of
+# object libs armnn to include in the build
+# If armnn is a static library (which it should be to make armnn_delegate_jni a stand alone library) then
+# the object libraries of the backends need to be linked manually
+include(${ARMNN_SOURCE_DIR}/src/backends/backends.cmake)
+foreach(lib ${armnnLibraries})
+ message(STATUS "Adding object library dependency to armnn_delegate_jni: ${lib}")
+ list(APPEND jni_delegate_sources $<TARGET_OBJECTS:${lib}>)
+endforeach()
+
+if (JNI_FOUND)
+ message (STATUS "JNI_INCLUDE_DIRS=${JNI_INCLUDE_DIRS}")
+ message (STATUS "JNI_LIBRARIES=${JNI_LIBRARIES}")
+else()
+ message (FATAL_ERROR "JNI library could not be found")
+endif()
+include_directories(${JNI_INCLUDE_DIRS})
+
+add_library(armnn_delegate_jni SHARED ${jni_delegate_sources})
+
+target_include_directories(
+ armnn_delegate_jni
+ PUBLIC
+ ${ARMNN_INCLUDE_DIR}
+ ${ARMNN_DELEGATE_INCLUDE_DIR}
+ ${ARMCOMPUTE_INCLUDE}
+ )
+
+target_link_libraries(
+ armnn_delegate_jni
+ PRIVATE
+ Armnn::Armnn
+ ArmnnDelegate::ArmnnDelegate
+ )
+
+# A version script is used to hide all symbols that are not required to use the jni interface
+# This is mostly required to avoid symbol conflicts between libc++_shared used to compile armnn
+# and an eventual other version used somewhere else: https://developer.android.com/ndk/guides/cpp-support
+# This also requires to tell the compiler to link to the static version of libc++_shared. This can be accomplished
+# by adding -DCMAKE_ANDROID_STL_TYPE=c++_static to the cmake command when building for android
+set(version_script "${CMAKE_CURRENT_SOURCE_DIR}/version_script")
+
+# Generate a map file for debug mode only
+set_property(TARGET armnn_delegate_jni APPEND_STRING PROPERTY
+ LINK_FLAGS " -Wl,--version-script=${version_script},-Map=mapfile.map")
+
+set_target_properties(armnn_delegate_jni PROPERTIES LINK_DEPENDS ${version_script})
diff --git a/delegate/armnnDelegateJNI/README.md b/delegate/armnnDelegateJNI/README.md
new file mode 100644
index 0000000000..98ddd54a34
--- /dev/null
+++ b/delegate/armnnDelegateJNI/README.md
@@ -0,0 +1,15 @@
+# The Arm NN TensorFlow Lite delegate JNI (Experimental)
+
+NOTE: This library is an experimental feature. We cannot guarentee full support for this.
+
+'armnnDelegateJNI' is a library for accelerating certain TensorFlow Lite operators on Arm hardware specifically through Android
+applications. Each release is packaged in an AAR which can be found on Maven Central.
+The pre-built library contains the ArmNN Core, ArmNN Utils, Neon backend, CL Backend, and the ArmNN Delegate.
+It is essential to only build these. The backends you choose are optional.
+
+It requires a static build which can be switched on through setting BUILD_SHARED_LIBS=OFF. You will also have to set
+CMAKE_ANDROID_STL_TYPE=c++_static when building ArmNN.
+
+BUILD_DELEGATE_JNI_INTERFACE will also have to be set to true.
+
+To download the prebuilt ArmNN Delegate JNI AAR from Maven Central, please go to [ArmNN Maven Central Release Page](https://search.maven.org/artifact/io.github.arm-software/armnn.delegate).
diff --git a/delegate/armnnDelegateJNI/README.md.license b/delegate/armnnDelegateJNI/README.md.license
new file mode 100644
index 0000000000..ac6973d209
--- /dev/null
+++ b/delegate/armnnDelegateJNI/README.md.license
@@ -0,0 +1,4 @@
+#
+# Copyright © 2022 ARM Ltd and Contributors. All rights reserved.
+# SPDX-License-Identifier: MIT
+# \ No newline at end of file
diff --git a/delegate/armnnDelegateJNI/src/armnn_delegate_jni.cpp b/delegate/armnnDelegateJNI/src/armnn_delegate_jni.cpp
new file mode 100644
index 0000000000..55cc066023
--- /dev/null
+++ b/delegate/armnnDelegateJNI/src/armnn_delegate_jni.cpp
@@ -0,0 +1,98 @@
+//
+// Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <armnn_delegate.hpp>
+#include <DelegateOptions.hpp>
+
+#if defined(ARMCOMPUTECL_ENABLED)
+#include <arm_compute/core/CL/OpenCL.h>
+#endif
+
+#include <jni.h>
+#include <string>
+
+extern "C" {
+
+/// Creates an Arm NN Delegate object.
+/// Options are passed in form of String arrays. For details about what options_keys and option_values
+/// are supported please see:
+// armnnDelegate::DelegateOptions::DelegateOptions(char const* const*, char const* const*,size_t,void (*)(const char*))
+JNIEXPORT jlong
+JNICALL Java_com_arm_armnn_delegate_ArmnnDelegate_createDelegate(JNIEnv* env,
+ jclass clazz,
+ jobjectArray optionKeys,
+ jobjectArray optionValues)
+{
+ int numOptions = env->GetArrayLength(optionKeys);
+ const char* nativeOptionKeys[numOptions];
+ const char* nativeOptionValues[numOptions];
+
+ jstring jKeyStrings[numOptions];
+ jstring jValueStrings[numOptions];
+
+ // Convert java array of string into char so we can make use of it in cpp code
+ for (int i = 0; i < numOptions; i++)
+ {
+ jKeyStrings[i] = static_cast<jstring>(env->GetObjectArrayElement(optionKeys, i));
+ jValueStrings[i] = static_cast<jstring>(env->GetObjectArrayElement(optionValues, i));
+
+ nativeOptionKeys[i] = env->GetStringUTFChars(jKeyStrings[i], 0);
+ nativeOptionValues[i] = env->GetStringUTFChars(jValueStrings[i], 0);
+ }
+
+ armnnDelegate::DelegateOptions delegateOptions(nativeOptionKeys,
+ nativeOptionValues,
+ numOptions,
+ nullptr);
+
+ // Release jni memory. After the delegate options are created there is no need to hold on to it anymore.
+ for (int i = 0; i < numOptions; i++)
+ {
+ env->ReleaseStringUTFChars(jKeyStrings[i], nativeOptionKeys[i]);
+ env->ReleaseStringUTFChars(jValueStrings[i], nativeOptionValues[i]);
+ }
+
+ return reinterpret_cast<jlong>(armnnDelegate::TfLiteArmnnDelegateCreate(delegateOptions));
+}
+
+/// Destroys a given Arm NN Delegate object
+JNIEXPORT void
+JNICALL Java_com_arm_armnn_delegate_ArmnnDelegate_deleteDelegate(JNIEnv* env, jclass clazz, jlong delegate)
+{
+ armnnDelegate::TfLiteArmnnDelegateDelete(reinterpret_cast<TfLiteDelegate*>(delegate));
+}
+
+/// Returns true if a Arm Mali GPU is detected.
+/// Can be used to ensure that GpuAcc is supported on a device.
+JNIEXPORT jboolean
+JNICALL Java_com_arm_armnn_delegate_ArmnnUtils_IsGpuAccSupported(JNIEnv* env, jclass clazz)
+{
+#if defined(ARMCOMPUTECL_ENABLED)
+ cl::Device device = cl::Device::getDefault();
+ char device_name[32];
+ cl_int err = clGetDeviceInfo(device.get(), CL_DEVICE_NAME, sizeof(device_name), &device_name, NULL);
+ if (err != CL_SUCCESS)
+ {
+ return false;
+ }
+ // search for "Mali" in the devices name
+ if (strstr(device_name, "Mali"))
+ {
+ return true;
+ }
+#endif
+ return false;
+}
+
+/// Returns true if the current device supports Neon instructions.
+/// Can be used to ensure the CpuAcc backend is supported.
+JNIEXPORT jboolean
+JNICALL Java_com_arm_armnn_delegate_ArmnnUtils_IsNeonDetected(JNIEnv* env, jclass clazz)
+{
+ return armnn::NeonDetected();
+}
+
+}
+
diff --git a/delegate/armnnDelegateJNI/version_script b/delegate/armnnDelegateJNI/version_script
new file mode 100644
index 0000000000..8dc044e494
--- /dev/null
+++ b/delegate/armnnDelegateJNI/version_script
@@ -0,0 +1,15 @@
+/*
+ Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
+ SPDX-License-Identifier: MIT
+*/
+
+LIBARMNN_DELEGATE_JNI {
+global:
+ Java_com_arm_armnn_delegate_ArmnnDelegate_createDelegate;
+ Java_com_arm_armnn_delegate_ArmnnDelegate_deleteDelegate;
+ Java_com_arm_armnn_delegate_ArmnnUtils_IsGpuAccSupported;
+ Java_com_arm_armnn_delegate_ArmnnUtils_IsNeonDetected;
+local:
+ *;
+
+}; \ No newline at end of file