aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFrancis Murtagh <francis.murtagh@arm.com>2021-01-25 10:18:10 +0000
committerFrancis Murtagh <francis.murtagh@arm.com>2021-01-25 10:18:20 +0000
commit5dc64fe99227efece77eb7cd14abc47474a48fb8 (patch)
tree09de113127e07707ad8edb20075463696055f736 /src
parent2686849118217ba692439407adb53ec3849d48ac (diff)
downloadarmnn-5dc64fe99227efece77eb7cd14abc47474a48fb8.tar.gz
IVGCVSW-5525 Handle Neon optionality on 32 bit linux platforms
* Add neon detection for linux using HWCAPs * Add test to check for backend throwing BackendUnavailable exception Signed-off-by: Francis Murtagh <francis.murtagh@arm.com> Change-Id: Ib74aeb06abe5f88f21ecdd1edb2a1cd20ee2019d
Diffstat (limited to 'src')
-rw-r--r--src/armnn/Utils.cpp48
-rw-r--r--src/backends/backendsCommon/test/BackendRegistryTests.cpp44
-rw-r--r--src/backends/neon/NeonRegistryInitializer.cpp12
3 files changed, 103 insertions, 1 deletions
diff --git a/src/armnn/Utils.cpp b/src/armnn/Utils.cpp
index 13bf3025f2..62c8ae6262 100644
--- a/src/armnn/Utils.cpp
+++ b/src/armnn/Utils.cpp
@@ -5,6 +5,13 @@
#include "armnn/Logging.hpp"
#include "armnn/Utils.hpp"
+#if !defined(BARE_METAL) && (defined(__arm__) || defined(__aarch64__))
+
+#include <sys/auxv.h>
+#include <asm/hwcap.h>
+
+#endif
+
namespace armnn
{
void ConfigureLogging(bool printToStandardOutput, bool printToDebugOutput, LogSeverity severity)
@@ -25,4 +32,45 @@ struct DefaultLoggingConfiguration
static DefaultLoggingConfiguration g_DefaultLoggingConfiguration;
+// Detect the presence of Neon on Linux
+bool NeonDetected()
+{
+#if !defined(BARE_METAL) && (defined(__arm__) || defined(__aarch64__))
+ auto hwcaps= getauxval(AT_HWCAP);
+#endif
+
+#if !defined(BARE_METAL) && defined(__aarch64__)
+
+ if (hwcaps & HWCAP_ASIMD)
+ {
+ // On an arm64 device with Neon.
+ return true;
+ }
+ else
+ {
+ // On an arm64 device without Neon.
+ return false;
+ }
+
+#endif
+#if !defined(BARE_METAL) && defined(__arm__)
+
+ if (hwcaps & HWCAP_NEON)
+ {
+ // On an armhf device with Neon.
+ return true;
+ }
+ else
+ {
+ // On an armhf device without Neon.
+ return false;
+ }
+
+#endif
+
+ // This method of Neon detection is only supported on Linux so in order to prevent a false negative
+ // we will return true in cases where detection did not run.
+ return true;
+}
+
} // namespace armnn \ No newline at end of file
diff --git a/src/backends/backendsCommon/test/BackendRegistryTests.cpp b/src/backends/backendsCommon/test/BackendRegistryTests.cpp
index 213d114248..ce8acbbf2a 100644
--- a/src/backends/backendsCommon/test/BackendRegistryTests.cpp
+++ b/src/backends/backendsCommon/test/BackendRegistryTests.cpp
@@ -7,6 +7,7 @@
#include <armnn/BackendRegistry.hpp>
#include <armnn/backends/IBackendInternal.hpp>
+#include <reference/RefBackend.hpp>
#include <boost/test/unit_test.hpp>
@@ -103,4 +104,47 @@ BOOST_AUTO_TEST_CASE(TestDirectCallToRegistry)
BackendRegistryInstance().Deregister("HelloWorld");
}
+// Test that backends can throw exceptions during their factory function to prevent loading in an unsuitable
+// environment. For example Neon Backend loading on armhf device without neon support.
+// In reality the dynamic backend is loaded in during the LoadDynamicBackends(options.m_DynamicBackendsPath)
+// step of runtime constructor, then the factory function is called to check if supported, in case
+// of Neon not being detected the exception is raised and so the backend is not added to the supportedBackends
+// list
+
+BOOST_AUTO_TEST_CASE(ThrowBackendUnavailableException)
+{
+ using namespace armnn;
+
+ const BackendId mockBackendId("MockDynamicBackend");
+
+ const std::string exceptionMessage("Neon support not found on device, could not register CpuAcc Backend.\n");
+
+ // Register the mock backend with a factory function lambda equivalent to NeonRegisterInitializer
+ BackendRegistryInstance().Register(mockBackendId,
+ [exceptionMessage]()
+ {
+ if (false)
+ {
+ return IBackendInternalUniquePtr(new RefBackend);
+ }
+ ARMNN_LOG(info) << "Neon support not found on device, could not register CpuAcc Backend.";
+ throw armnn::BackendUnavailableException(exceptionMessage);
+ });
+
+ // Get the factory function of the mock backend
+ auto factoryFunc = BackendRegistryInstance().GetFactory(mockBackendId);
+
+ try
+ {
+ // Call the factory function as done during runtime backend registering
+ auto backend = factoryFunc();
+ }
+ catch (const BackendUnavailableException& e)
+ {
+ // Caught
+ BOOST_CHECK_EQUAL(e.what(), exceptionMessage);
+ BOOST_TEST_MESSAGE("ThrowBackendUnavailableExceptionImpl: BackendUnavailableException caught.");
+ }
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/backends/neon/NeonRegistryInitializer.cpp b/src/backends/neon/NeonRegistryInitializer.cpp
index fd2e84dd5f..fc981ab270 100644
--- a/src/backends/neon/NeonRegistryInitializer.cpp
+++ b/src/backends/neon/NeonRegistryInitializer.cpp
@@ -6,6 +6,7 @@
#include "NeonBackend.hpp"
#include <armnn/BackendRegistry.hpp>
+#include <armnn/Utils.hpp>
namespace
{
@@ -18,7 +19,16 @@ static BackendRegistry::StaticRegistryInitializer g_RegisterHelper
NeonBackend::GetIdStatic(),
[]()
{
- return IBackendInternalUniquePtr(new NeonBackend);
+ // Check if device supports Neon.
+ if (NeonDetected())
+ {
+ return IBackendInternalUniquePtr(new NeonBackend);
+ }
+
+ // If device does not support Neon throw exception so the Backend is not added to supportedBackends
+ ARMNN_LOG(info) << "Neon support not found on device, could not register CpuAcc Backend.";
+ throw armnn::BackendUnavailableException(
+ "Neon support not found on device, could not register CpuAcc Backend.\n");
}
};