aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatteo Martincigh <matteo.martincigh@arm.com>2019-08-05 12:16:47 +0100
committerMatteo Martincigh <matteo.martincigh@arm.com>2019-08-05 16:32:05 +0000
commite7d449893b85a00a063836bd01dce4f925a24dd2 (patch)
treebff2b2770caa91c3bbf7270db8a21a3f4eb9964f
parent4fc3c48c2d230d8c55aa01aa98e32b6df7cafc0c (diff)
downloadarmnn-e7d449893b85a00a063836bd01dce4f925a24dd2.tar.gz
IVGCVSW-3541 Get the paths where to load the dynamic backends from
* Adds GetBackendPaths and IsPathValid to DynamicBackendUtils * Adds related unit tests Change-Id: I94e377d92a88a4b5d48026f6ad5b4d5387d20c21 Signed-off-by: Jan Eilers <jan.eilers@arm.com> Signed-off-by: Matteo Martincigh <matteo.martincigh@arm.com>
-rw-r--r--CMakeLists.txt8
-rw-r--r--cmake/GlobalConfig.cmake1
-rw-r--r--include/armnn/IRuntime.hpp5
-rw-r--r--src/backends/backendsCommon/DynamicBackendUtils.cpp92
-rw-r--r--src/backends/backendsCommon/DynamicBackendUtils.hpp11
-rw-r--r--src/backends/backendsCommon/test/DynamicBackendTests.cpp3
-rw-r--r--src/backends/backendsCommon/test/DynamicBackendTests.hpp115
7 files changed, 233 insertions, 2 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index eaaf2d6813..08c693d30d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,6 +15,11 @@ foreach(cmake_file ${additional_cmake_files})
include(${cmake_file})
endforeach()
+if (DYNAMIC_BACKEND_PATHS)
+ # It's expected to have the format: DYNAMIC_BACKEND_PATHS="PATH_1:PATH_2...:PATH_N"
+ add_definitions('-DDYNAMIC_BACKEND_PATHS="${DYNAMIC_BACKEND_PATHS}"')
+endif()
+
include(GNUInstallDirs)
add_subdirectory(samples)
@@ -451,7 +456,8 @@ endif()
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-target_link_libraries(armnn ${Boost_LOG_LIBRARY} ${Boost_THREAD_LIBRARY} ${Boost_SYSTEM_LIBRARY})
+target_link_libraries(armnn ${Boost_LOG_LIBRARY} ${Boost_THREAD_LIBRARY}
+ ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY})
if(ARMCOMPUTENEON OR ARMCOMPUTECL)
target_link_libraries(armnn ${ARMCOMPUTE_LIBRARIES})
diff --git a/cmake/GlobalConfig.cmake b/cmake/GlobalConfig.cmake
index 26b3ff4d8c..8dad57a297 100644
--- a/cmake/GlobalConfig.cmake
+++ b/cmake/GlobalConfig.cmake
@@ -19,6 +19,7 @@ option(BUILD_ACCURACY_TOOL "Build Accuracy Tool" OFF)
option(FLATC_DIR "Path to Flatbuffers compiler" OFF)
option(TF_LITE_GENERATED_PATH "Tensorflow lite generated C++ schema location" OFF)
option(FLATBUFFERS_ROOT "Location where the flatbuffers 'include' and 'lib' folders to be found" Off)
+option(DYNAMIC_BACKEND_PATHS "Colon seperated list of paths where to load the dynamic backends from" "")
include(SelectLibraryConfigurations)
diff --git a/include/armnn/IRuntime.hpp b/include/armnn/IRuntime.hpp
index 0366663841..3f3c998f3a 100644
--- a/include/armnn/IRuntime.hpp
+++ b/include/armnn/IRuntime.hpp
@@ -31,6 +31,7 @@ public:
CreationOptions()
: m_GpuAccTunedParameters(nullptr)
, m_EnableGpuProfiling(false)
+ , m_DynamicBackendsPath("")
{}
/// If set, uses the GpuAcc tuned parameters from the given object when executing GPU workloads.
@@ -39,6 +40,10 @@ public:
// Setting this flag will allow the user to obtain GPU profiling information from the runtime.
bool m_EnableGpuProfiling;
+
+ // Setting this value will override the paths set by the DYNAMIC_BACKEND_PATHS compiler directive
+ // Only a single path is allowed for the override
+ std::string m_DynamicBackendsPath;
};
static IRuntime* CreateRaw(const CreationOptions& options);
diff --git a/src/backends/backendsCommon/DynamicBackendUtils.cpp b/src/backends/backendsCommon/DynamicBackendUtils.cpp
index 0ab02d7c98..ae36a24b30 100644
--- a/src/backends/backendsCommon/DynamicBackendUtils.cpp
+++ b/src/backends/backendsCommon/DynamicBackendUtils.cpp
@@ -5,6 +5,10 @@
#include "DynamicBackendUtils.hpp"
+#include <boost/filesystem/operations.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/log/trivial.hpp>
+
namespace armnn
{
@@ -59,4 +63,92 @@ std::string DynamicBackendUtils::GetDlError()
return std::string(errorMessage);
}
+std::vector<std::string> DynamicBackendUtils::GetBackendPaths(const std::string& overrideBackendPath)
+{
+ // Check if a path where to dynamically load the backends from is given
+ if (!overrideBackendPath.empty())
+ {
+ if (!IsPathValid(overrideBackendPath))
+ {
+ BOOST_LOG_TRIVIAL(warning) << "WARNING: The given override path for dynamic backends \""
+ << overrideBackendPath << "\" is not valid";
+
+ return {};
+ }
+
+ return std::vector<std::string>{ overrideBackendPath };
+ }
+
+ // Expects a colon-separated list: DYNAMIC_BACKEND_PATHS="PATH_1:PATH_2:...:PATH_N"
+ const std::string backendPaths = DYNAMIC_BACKEND_PATHS;
+
+ return GetBackendPathsImpl(backendPaths);
+}
+
+std::vector<std::string> DynamicBackendUtils::GetBackendPathsImpl(const std::string& backendPaths)
+{
+ std::unordered_set<std::string> uniqueBackendPaths;
+ std::vector<std::string> tempBackendPaths;
+ std::vector<std::string> validBackendPaths;
+
+ // Split the given list of paths
+ boost::split(tempBackendPaths, backendPaths, boost::is_any_of(":"));
+
+ for (const std::string& path : tempBackendPaths)
+ {
+ // Check whether the path is valid
+ if (!IsPathValid(path))
+ {
+ continue;
+ }
+
+ // Check whether the path is a duplicate
+ auto it = uniqueBackendPaths.find(path);
+ if (it != uniqueBackendPaths.end())
+ {
+ // The path is a duplicate
+ continue;
+ }
+
+ // Add the path to the set of unique paths
+ uniqueBackendPaths.insert(path);
+
+ // Add the path to the list of valid paths
+ validBackendPaths.push_back(path);
+ }
+
+ return validBackendPaths;
+}
+
+bool DynamicBackendUtils::IsPathValid(const std::string& path)
+{
+ if (path.empty())
+ {
+ BOOST_LOG_TRIVIAL(warning) << "WARNING: The given backend path is empty";
+ return false;
+ }
+
+ boost::filesystem::path boostPath(path);
+
+ if (!boost::filesystem::exists(boostPath))
+ {
+ BOOST_LOG_TRIVIAL(warning) << "WARNING: The given backend path \"" << path << "\" does not exist";
+ return false;
+ }
+
+ if (!boost::filesystem::is_directory(boostPath))
+ {
+ BOOST_LOG_TRIVIAL(warning) << "WARNING: The given backend path \"" << path << "\" is not a directory";
+ return false;
+ }
+
+ if (!boostPath.is_absolute())
+ {
+ BOOST_LOG_TRIVIAL(warning) << "WARNING: The given backend path \"" << path << "\" is not absolute";
+ return false;
+ }
+
+ return true;
+}
+
} // namespace armnn
diff --git a/src/backends/backendsCommon/DynamicBackendUtils.hpp b/src/backends/backendsCommon/DynamicBackendUtils.hpp
index 0a2d428fd3..f0bfd3b220 100644
--- a/src/backends/backendsCommon/DynamicBackendUtils.hpp
+++ b/src/backends/backendsCommon/DynamicBackendUtils.hpp
@@ -11,9 +11,14 @@
#include <string>
#include <dlfcn.h>
+#include <vector>
#include <boost/format.hpp>
+#if !defined(DYNAMIC_BACKEND_PATHS)
+#define DYNAMIC_BACKEND_PATHS ""
+#endif
+
namespace armnn
{
@@ -28,9 +33,13 @@ public:
static bool IsBackendCompatible(const BackendVersion& backendVersion);
+ static std::vector<std::string> GetBackendPaths(const std::string& overrideBackendPath = "");
+ static bool IsPathValid(const std::string& path);
+
protected:
- /// Protected for testing purposes
+ /// Protected methods for testing purposes
static bool IsBackendCompatibleImpl(const BackendVersion& backendApiVersion, const BackendVersion& backendVersion);
+ static std::vector<std::string> GetBackendPathsImpl(const std::string& backendPaths);
private:
static std::string GetDlError();
diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.cpp b/src/backends/backendsCommon/test/DynamicBackendTests.cpp
index 10a650af7e..16d07c1a47 100644
--- a/src/backends/backendsCommon/test/DynamicBackendTests.cpp
+++ b/src/backends/backendsCommon/test/DynamicBackendTests.cpp
@@ -40,4 +40,7 @@ ARMNN_SIMPLE_TEST_CASE(CreateDynamicBackendObjectInvalidInterface6,
ARMNN_SIMPLE_TEST_CASE(CreateDynamicBackendObjectInvalidInterface7,
CreateDynamicBackendObjectInvalidInterface7TestImpl);
+ARMNN_SIMPLE_TEST_CASE(GetBackendPaths, GetBackendPathsTestImpl)
+ARMNN_SIMPLE_TEST_CASE(GetBackendPathsOverride, GetBackendPathsOverrideTestImpl)
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.hpp b/src/backends/backendsCommon/test/DynamicBackendTests.hpp
index 55f90d48eb..32778118c3 100644
--- a/src/backends/backendsCommon/test/DynamicBackendTests.hpp
+++ b/src/backends/backendsCommon/test/DynamicBackendTests.hpp
@@ -34,6 +34,11 @@ static std::string g_TestInvalidTestDynamicBackend5FileName = "libInvalidTestDyn
static std::string g_TestInvalidTestDynamicBackend6FileName = "libInvalidTestDynamicBackend6.so";
static std::string g_TestInvalidTestDynamicBackend7FileName = "libInvalidTestDynamicBackend7.so";
+static std::string g_TestDynamicBackendsFileParsingSubDir1 = "backendsTestPath1/";
+static std::string g_TestDynamicBackendsFileParsingSubDir2 = "backendsTestPath2/";
+static std::string g_TestDynamicBackendsFileParsingSubDir3 = "backendsTestPath3/";
+static std::string g_TestDynamicBackendsFileParsingSubDir4 = "backendsTestPath4/";
+
std::string GetTestDirectoryBasePath()
{
using namespace boost::filesystem;
@@ -455,3 +460,113 @@ void CreateDynamicBackendObjectInvalidInterface7TestImpl()
BOOST_CHECK_THROW(dynamicBackend.reset(new DynamicBackend(sharedObjectHandle)), RuntimeException);
BOOST_TEST((dynamicBackend == nullptr));
}
+
+void GetBackendPathsTestImpl()
+{
+ using namespace armnn;
+ using namespace boost::filesystem;
+
+ // The test covers four directories:
+ // <unit test path>/src/backends/backendsCommon/test/
+ // ├─ backendsTestPath1/ -> existing, contains files
+ // ├─ backendsTestPath2/ -> existing, contains files
+ // ├─ backendsTestPath3/ -> existing, but empty
+ // └─ backendsTestPath4/ -> not existing
+
+ std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1);
+ std::string subDir2 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir2);
+ std::string subDir3 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir3);
+ std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4);
+
+ BOOST_CHECK(exists(subDir1));
+ BOOST_CHECK(exists(subDir2));
+ BOOST_CHECK(exists(subDir3));
+ BOOST_CHECK(!exists(subDir4));
+
+ class TestDynamicBackendUtils : public DynamicBackendUtils
+ {
+ public:
+ static std::vector<std::string> GetBackendPathsImplTest(const std::string& path)
+ {
+ return GetBackendPathsImpl(path);
+ }
+ };
+
+ // No path
+ BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest("").empty());
+
+ // Malformed path
+ std::string malformedDir(subDir1 + "/" + subDir1);
+ BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(malformedDir).size()==0);
+
+ // Single valid path
+ std::vector<std::string> DynamicBackendPaths2 = TestDynamicBackendUtils::GetBackendPathsImplTest(subDir1);
+ BOOST_TEST(DynamicBackendPaths2.size() == 1);
+ BOOST_TEST(DynamicBackendPaths2[0] == subDir1);
+
+ // Multiple equal and valid paths
+ std::string multipleEqualDirs(subDir1 + ":" + subDir1);
+ std::vector<std::string> DynamicBackendPaths3 = TestDynamicBackendUtils::GetBackendPathsImplTest(multipleEqualDirs);
+ BOOST_TEST(DynamicBackendPaths3.size() == 1);
+ BOOST_TEST(DynamicBackendPaths3[0] == subDir1);
+
+ // Multiple empty paths
+ BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(":::").empty());
+
+ // Multiple valid paths
+ std::string multipleValidPaths(subDir1 + ":" + subDir2 + ":" + subDir3);
+ std::vector<std::string> DynamicBackendPaths5 =
+ TestDynamicBackendUtils::GetBackendPathsImplTest(multipleValidPaths);
+ BOOST_TEST(DynamicBackendPaths5.size() == 3);
+ BOOST_TEST(DynamicBackendPaths5[0] == subDir1);
+ BOOST_TEST(DynamicBackendPaths5[1] == subDir2);
+ BOOST_TEST(DynamicBackendPaths5[2] == subDir3);
+
+ // Valid among empty paths
+ std::string validAmongEmptyDirs("::" + subDir1 + ":");
+ std::vector<std::string> DynamicBackendPaths6 =
+ TestDynamicBackendUtils::GetBackendPathsImplTest(validAmongEmptyDirs);
+ BOOST_TEST(DynamicBackendPaths6.size() == 1);
+ BOOST_TEST(DynamicBackendPaths6[0] == subDir1);
+
+ // Invalid among empty paths
+ std::string invalidAmongEmptyDirs(":" + subDir4 + "::");
+ BOOST_TEST(TestDynamicBackendUtils::GetBackendPathsImplTest(invalidAmongEmptyDirs).empty());
+
+ // Valid, invalid and empty paths
+ std::string validInvalidEmptyDirs(subDir1 + ":" + subDir4 + ":");
+ std::vector<std::string> DynamicBackendPaths8 =
+ TestDynamicBackendUtils::GetBackendPathsImplTest(validInvalidEmptyDirs);
+ BOOST_TEST(DynamicBackendPaths8.size() == 1);
+ BOOST_TEST(DynamicBackendPaths8[0] == subDir1);
+
+ // Mix of duplicates of valid, invalid and empty paths
+ std::string duplicateValidInvalidEmptyDirs(validInvalidEmptyDirs + ":" + validInvalidEmptyDirs + ":" +
+ subDir2 + ":" + subDir2);
+ std::vector<std::string> DynamicBackendPaths9 =
+ TestDynamicBackendUtils::GetBackendPathsImplTest(duplicateValidInvalidEmptyDirs);
+ BOOST_TEST(DynamicBackendPaths9.size() == 2);
+ BOOST_TEST(DynamicBackendPaths9[0] == subDir1);
+ BOOST_TEST(DynamicBackendPaths9[1] == subDir2);
+}
+
+void GetBackendPathsOverrideTestImpl()
+{
+ using namespace armnn;
+ using namespace boost::filesystem;
+
+ std::string subDir1 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir1);
+ std::string subDir4 = GetTestSubDirectory(g_TestDynamicBackendsFileParsingSubDir4);
+
+ BOOST_CHECK(exists(subDir1));
+ BOOST_CHECK(!exists(subDir4));
+
+ // Override with valid path
+ std::vector<std::string> validResult = DynamicBackendUtils::GetBackendPaths(subDir1);
+ BOOST_TEST(validResult.size() == 1);
+ BOOST_TEST(validResult[0] == subDir1);
+
+ // Override with invalid path
+ std::vector<std::string> invalidResult = DynamicBackendUtils::GetBackendPaths(subDir4);
+ BOOST_TEST(invalidResult.empty());
+}