IVGCVSW-4212 Example of standalone dynamic reference backend
authorNarumol Prangnawarat <narumol.prangnawarat@arm.com>
Mon, 9 Dec 2019 17:24:41 +0000 (17:24 +0000)
committerNarumol Prangnawarat <narumol.prangnawarat@arm.com>
Tue, 10 Dec 2019 17:44:50 +0000 (17:44 +0000)
 * Add example to build dynamic reference backend
 * Add functions to clear dynamic backends
 * Fix the error when dynamic backend is not deregistered
 * Add DYARMNN_DYNAMIC_BACKEND_ENABLED to check disable empty
   dynamic backend when dynamic backend is enabled

Signed-off-by: Narumol Prangnawarat <narumol.prangnawarat@arm.com>
Change-Id: I1ef3a3f10ed6ca5ec18d0af04b007fc3bc71a3cb

13 files changed:
cmake/GlobalConfig.cmake
include/armnn/BackendRegistry.hpp
src/armnn/BackendRegistry.cpp
src/armnn/DeviceSpec.hpp
src/armnn/Runtime.cpp
src/backends/backendsCommon/DynamicBackendUtils.cpp
src/backends/backendsCommon/DynamicBackendUtils.hpp
src/backends/backendsCommon/test/DynamicBackendTests.cpp
src/backends/backendsCommon/test/DynamicBackendTests.hpp
src/backends/backendsCommon/test/OptimizationViewsTests.cpp
src/dynamic/reference/CMakeLists.txt [new file with mode: 0644]
src/dynamic/reference/RefDynamicBackend.cpp [new file with mode: 0644]
src/dynamic/reference/RefDynamicBackend.hpp [new file with mode: 0644]

index 191cd9d..51a7efd 100644 (file)
@@ -302,6 +302,11 @@ if(ARMNNREF)
     add_definitions(-DARMNNREF_ENABLED)
 endif()
 
+# ArmNN dynamic backend
+if(DYNAMIC_BACKEND_PATHS)
+    add_definitions(-DARMNN_DYNAMIC_BACKEND_ENABLED)
+endif()
+
 # Streamline annotate
 if(PROFILING_BACKEND_STREAMLINE)
     include_directories("${GATOR_ROOT}/annotate")
index 82e59d9..a0cfee9 100644 (file)
@@ -43,6 +43,8 @@ public:
         }
     };
 
+    void Deregister(const BackendId& id);
+
 protected:
     using FactoryStorage = std::unordered_map<BackendId, FactoryFunction>;
 
index 45f73b8..dc3e2bc 100644 (file)
@@ -27,6 +27,11 @@ void BackendRegistry::Register(const BackendId& id, BackendRegistry::FactoryFunc
     m_Factories[id] = factory;
 }
 
+void BackendRegistry::Deregister(const BackendId& id)
+{
+    m_Factories.erase(id);
+}
+
 bool BackendRegistry::IsBackendRegistered(const BackendId& id) const
 {
     return (m_Factories.find(id) != m_Factories.end());
index 3226470..703a4b1 100644 (file)
@@ -24,14 +24,33 @@ public:
         return m_SupportedBackends;
     }
 
-    void AddSupportedBackends(const BackendIdSet& backendIds)
+    void AddSupportedBackends(const BackendIdSet& backendIds, bool isDynamic = false)
     {
         m_SupportedBackends.insert(backendIds.begin(), backendIds.end());
+        if (isDynamic)
+        {
+            m_DynamicBackends.insert(backendIds.begin(), backendIds.end());
+        }
+    }
+
+    void ClearDynamicBackends()
+    {
+        for (const auto& id : m_DynamicBackends)
+        {
+            m_SupportedBackends.erase(id);
+        }
+        m_DynamicBackends.clear();
+    }
+
+    const BackendIdSet& GetDynamicBackends() const
+    {
+        return m_DynamicBackends;
     }
 
 private:
     DeviceSpec() = delete;
     BackendIdSet m_SupportedBackends;
+    BackendIdSet m_DynamicBackends;
 };
 
 } // namespace armnn
index 9b0ce1a..4ad6fa5 100644 (file)
@@ -214,6 +214,10 @@ Runtime::~Runtime()
                       << std::endl;
         }
     }
+
+    // Clear all dynamic backends.
+    DynamicBackendUtils::DeregisterDynamicBackends(m_DeviceSpec.GetDynamicBackends());
+    m_DeviceSpec.ClearDynamicBackends();
 }
 
 LoadedNetwork* Runtime::GetLoadedNetworkPtr(NetworkId networkId) const
@@ -273,7 +277,7 @@ void Runtime::LoadDynamicBackends(const std::string& overrideBackendPath)
     BackendIdSet registeredBackendIds = DynamicBackendUtils::RegisterDynamicBackends(m_DynamicBackends);
 
     // Add the registered dynamic backend ids to the list of supported backends
-    m_DeviceSpec.AddSupportedBackends(registeredBackendIds);
+    m_DeviceSpec.AddSupportedBackends(registeredBackendIds, true);
 }
 
 } // namespace armnn
index ab0006d..f893458 100644 (file)
@@ -310,6 +310,18 @@ std::vector<DynamicBackendPtr> DynamicBackendUtils::CreateDynamicBackends(const
     return dynamicBackends;
 }
 
+void DynamicBackendUtils::DeregisterDynamicBackends(const BackendIdSet& dynamicBackends)
+{
+    // Get a reference of the backend registry
+    BackendRegistry& backendRegistry = BackendRegistryInstance();
+
+    for (const auto& id : dynamicBackends)
+    {
+        backendRegistry.Deregister(id);
+    }
+
+}
+
 BackendIdSet DynamicBackendUtils::RegisterDynamicBackends(const std::vector<DynamicBackendPtr>& dynamicBackends)
 {
     // Get a reference of the backend registry
index 2763b9d..f4cdd4d 100644 (file)
@@ -42,6 +42,7 @@ public:
 
     static std::vector<DynamicBackendPtr> CreateDynamicBackends(const std::vector<std::string>& sharedObjects);
     static BackendIdSet RegisterDynamicBackends(const std::vector<DynamicBackendPtr>& dynamicBackends);
+    static void DeregisterDynamicBackends(const BackendIdSet& dynamicBackends);
 
 protected:
     /// Protected methods for testing purposes
index c6606be..40e063d 100644 (file)
@@ -55,7 +55,9 @@ ARMNN_SIMPLE_TEST_CASE(RegisterMultipleDynamicBackends, RegisterMultipleDynamicB
 ARMNN_SIMPLE_TEST_CASE(RegisterMultipleInvalidDynamicBackends, RegisterMultipleInvalidDynamicBackendsTestImpl);
 ARMNN_SIMPLE_TEST_CASE(RegisterMixedDynamicBackends, RegisterMixedDynamicBackendsTestImpl);
 
+#if !defined(ARMNN_DYNAMIC_BACKEND_ENABLED)
 ARMNN_SIMPLE_TEST_CASE(RuntimeEmpty, RuntimeEmptyTestImpl);
+#endif
 ARMNN_SIMPLE_TEST_CASE(RuntimeDynamicBackends, RuntimeDynamicBackendsTestImpl);
 ARMNN_SIMPLE_TEST_CASE(RuntimeDuplicateDynamicBackends, RuntimeDuplicateDynamicBackendsTestImpl);
 ARMNN_SIMPLE_TEST_CASE(RuntimeInvalidDynamicBackends, RuntimeInvalidDynamicBackendsTestImpl);
index 561578e..4238ef6 100644 (file)
@@ -1198,6 +1198,8 @@ void RegisterMixedDynamicBackendsTestImpl()
     }
 }
 
+#if !defined(ARMNN_DYNAMIC_BACKEND_ENABLED)
+
 void RuntimeEmptyTestImpl()
 {
     using namespace armnn;
@@ -1218,6 +1220,8 @@ void RuntimeEmptyTestImpl()
     BOOST_TEST(backendRegistry.Size() == 0);
 }
 
+#endif
+
 void RuntimeDynamicBackendsTestImpl()
 {
     using namespace armnn;
index 5474f5d..639e1fd 100644 (file)
@@ -25,14 +25,8 @@ void CheckLayers(Graph& graph)
         {
             case LayerType::Input:
                 ++m_inputLayerCount;
-                if (layer->GetGuid() == profiling::ProfilingGuid(0))
-                {
-                    BOOST_TEST(layer->GetName() == "inLayer0");
-                }
-                else if (layer->GetGuid() == profiling::ProfilingGuid(1))
-                {
-                    BOOST_TEST(layer->GetName() == "inLayer1");
-                }
+                BOOST_TEST((layer->GetName() == std::string("inLayer0") ||
+                            layer->GetName() == std::string("inLayer1")));
                 break;
             // The Addition layer should become a PreCompiled Layer after Optimisation
             case LayerType::PreCompiled:
diff --git a/src/dynamic/reference/CMakeLists.txt b/src/dynamic/reference/CMakeLists.txt
new file mode 100644 (file)
index 0000000..79bf7ec
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# Copyright © 2019 Arm Ltd. All rights reserved.
+# SPDX-License-Identifier: MIT
+#
+
+cmake_minimum_required (VERSION 3.0.2)
+
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+# File needed to wrap the existing backend into a dynamic one
+list(APPEND armnnRefDynamicBackend_sources
+    RefDynamicBackend.cpp
+    RefDynamicBackend.hpp
+)
+
+# Set the backend source path
+set(RefBackendPath ${PROJECT_SOURCE_DIR}/../../../src/backends/reference)
+
+# Source files of the backend, taken directly from the source tree
+file(GLOB RefBackendBaseFiles ${RefBackendPath}/*.cpp)
+file(GLOB RefBackendWorloadFiles ${RefBackendPath}/workloads/*.cpp)
+set(RefBackendFiles ${RefBackendBaseFiles} ${RefBackendWorloadFiles})
+
+# Remove the file that contains the static backend registration
+list(REMOVE_ITEM RefBackendFiles ${RefBackendPath}/RefRegistryInitializer.cpp)
+
+# Create the shared object
+add_library(Arm_CpuRef_backend MODULE ${armnnRefDynamicBackend_sources} ${RefBackendFiles})
+
+target_include_directories(Arm_CpuRef_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../include)
+target_include_directories(Arm_CpuRef_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../third-party) # for half
+target_include_directories(Arm_CpuRef_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../src/armnn)
+target_include_directories(Arm_CpuRef_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../src/armnnUtils)
+target_include_directories(Arm_CpuRef_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../src/backends)
+target_include_directories(Arm_CpuRef_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../src/profiling)
\ No newline at end of file
diff --git a/src/dynamic/reference/RefDynamicBackend.cpp b/src/dynamic/reference/RefDynamicBackend.cpp
new file mode 100644 (file)
index 0000000..f2ed0f6
--- /dev/null
@@ -0,0 +1,33 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "RefDynamicBackend.hpp"
+
+#include <reference/RefBackend.hpp>
+
+using namespace armnn;
+
+const char* GetBackendId()
+{
+    return RefBackend::GetIdStatic().Get().c_str();
+}
+
+void GetVersion(uint32_t* outMajor, uint32_t* outMinor)
+{
+    if (!outMajor || !outMinor)
+    {
+        return;
+    }
+
+    BackendVersion apiVersion = IBackendInternal::GetApiVersion();
+
+    *outMajor = apiVersion.m_Major;
+    *outMinor = apiVersion.m_Minor;
+}
+
+void* BackendFactory()
+{
+    return new RefBackend();
+}
diff --git a/src/dynamic/reference/RefDynamicBackend.hpp b/src/dynamic/reference/RefDynamicBackend.hpp
new file mode 100644 (file)
index 0000000..bc680a1
--- /dev/null
@@ -0,0 +1,15 @@
+//
+// Copyright © 2019 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <cstdint>
+
+extern "C"
+{
+const char* GetBackendId();
+void GetVersion(uint32_t* outMajor, uint32_t* outMinor);
+void* BackendFactory();
+}