IVGCVSW-3543 Implement the backend versioning algorithm
authorMatteo Martincigh <matteo.martincigh@arm.com>
Thu, 25 Jul 2019 14:25:44 +0000 (15:25 +0100)
committerMatteo Martincigh <matteo.martincigh@arm.com>
Thu, 25 Jul 2019 15:35:08 +0000 (16:35 +0100)
 * Added version structure for backends, with comparisons operators
 * Added version to IBackendInternal
 * Added version utility function to DynamicBackendUtils class

Signed-off-by: Matteo Martincigh <matteo.martincigh@arm.com>
Change-Id: I3697469675c27f79f7cfb296cfa69ec7e06375e5

src/backends/backendsCommon/DynamicBackendUtils.cpp
src/backends/backendsCommon/DynamicBackendUtils.hpp
src/backends/backendsCommon/IBackendInternal.hpp
src/backends/backendsCommon/test/CMakeLists.txt
src/backends/backendsCommon/test/DynamicBackendTests.cpp [new file with mode: 0644]
src/backends/backendsCommon/test/DynamicBackendTests.hpp [new file with mode: 0644]

index 9a47654..0ab02d7 100644 (file)
@@ -34,6 +34,20 @@ void DynamicBackendUtils::CloseHandle(const void* sharedObjectHandle)
     dlclose(const_cast<void*>(sharedObjectHandle));
 }
 
+bool DynamicBackendUtils::IsBackendCompatible(const BackendVersion &backendVersion)
+{
+    BackendVersion backendApiVersion = IBackendInternal::GetApiVersion();
+
+    return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
+}
+
+bool DynamicBackendUtils::IsBackendCompatibleImpl(const BackendVersion &backendApiVersion,
+                                                  const BackendVersion &backendVersion)
+{
+    return backendVersion.m_Major == backendApiVersion.m_Major &&
+           backendVersion.m_Minor <= backendApiVersion.m_Minor;
+}
+
 std::string DynamicBackendUtils::GetDlError()
 {
     const char* errorMessage = dlerror();
index 011a823..0a2d428 100644 (file)
@@ -5,6 +5,8 @@
 
 #pragma once
 
+#include "IBackendInternal.hpp"
+
 #include <armnn/Exceptions.hpp>
 
 #include <string>
@@ -24,6 +26,12 @@ public:
     template<typename EntryPointType>
     static EntryPointType GetEntryPoint(const void* sharedObjectHandle, const char* symbolName);
 
+    static bool IsBackendCompatible(const BackendVersion& backendVersion);
+
+protected:
+    /// Protected for testing purposes
+    static bool IsBackendCompatibleImpl(const BackendVersion& backendApiVersion, const BackendVersion& backendVersion);
+
 private:
     static std::string GetDlError();
 
index a0d6569..c548683 100644 (file)
@@ -25,6 +25,42 @@ class IWorkloadFactory;
 class IMemoryManager;
 class ILayerSupport;
 
+struct BackendVersion
+{
+    uint32_t m_Major;
+    uint32_t m_Minor;
+
+    BackendVersion()
+        : m_Major(0)
+        , m_Minor(0)
+    {}
+    BackendVersion(uint32_t major, uint32_t minor)
+        : m_Major(major)
+        , m_Minor(minor)
+    {}
+
+    bool operator==(const BackendVersion& other) const
+    {
+        return this == &other ||
+               (this->m_Major == other.m_Major &&
+                this->m_Minor == other.m_Minor);
+    }
+
+    bool operator<=(const BackendVersion& other) const
+    {
+        return this->m_Major < other.m_Major ||
+               (this->m_Major == other.m_Major &&
+                this->m_Minor <= other.m_Minor);
+    }
+};
+
+inline std::ostream& operator<<(std::ostream& os, const BackendVersion& backendVersion)
+{
+    os << "[" << backendVersion.m_Major << "." << backendVersion.m_Minor << "]";
+
+    return os;
+}
+
 class IBackendInternal : public IBackend
 {
 protected:
@@ -79,7 +115,7 @@ public:
     virtual IMemoryManagerUniquePtr CreateMemoryManager() const
     {
         return IMemoryManagerUniquePtr();
-    };
+    }
 
     virtual IWorkloadFactoryPtr CreateWorkloadFactory(
         const IMemoryManagerSharedPtr& memoryManager = nullptr) const = 0;
@@ -142,6 +178,9 @@ public:
     /// Either this method or CreateMemoryManager() and
     /// IWorkloadFactory::CreateTensor()/IWorkloadFactory::CreateSubtensor() methods must be implemented.
     virtual void RegisterTensorHandleFactories(class TensorHandleFactoryRegistry& registry) {}
+
+    /// Returns the version of the Backend API
+    static BackendVersion GetApiVersion() { return { 1, 0 }; }
 };
 
 using IBackendInternalUniquePtr = std::unique_ptr<IBackendInternal>;
index 7c2d0eb..3ddaaaf 100644 (file)
@@ -19,6 +19,8 @@ list(APPEND armnnBackendsCommonUnitTests_sources
     DequantizeEndToEndTestImpl.hpp
     DetectionPostProcessLayerTestImpl.hpp
     DetectionPostProcessTestImpl.hpp
+    DynamicBackendTests.cpp
+    DynamicBackendTests.hpp
     EndToEndTestImpl.hpp
     FullyConnectedTestImpl.hpp
     GatherTestImpl.hpp
diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.cpp b/src/backends/backendsCommon/test/DynamicBackendTests.cpp
new file mode 100644 (file)
index 0000000..5104d06
--- /dev/null
@@ -0,0 +1,12 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "DynamicBackendTests.hpp"
+
+BOOST_AUTO_TEST_SUITE(DynamicBackendTests)
+
+ARMNN_SIMPLE_TEST_CASE(BackendVersioning, BackendVersioningTestImpl);
+
+BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.hpp b/src/backends/backendsCommon/test/DynamicBackendTests.hpp
new file mode 100644 (file)
index 0000000..3b0c95b
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <backendsCommon/DynamicBackendUtils.hpp>
+
+#include <test/UnitTests.hpp>
+
+#include <boost/test/unit_test.hpp>
+
+void BackendVersioningTestImpl()
+{
+    class TestDynamicBackendUtils : public armnn::DynamicBackendUtils
+    {
+    public:
+        static bool IsBackendCompatibleTest(const armnn::BackendVersion& backendApiVersion,
+                                            const armnn::BackendVersion& backendVersion)
+        {
+            return IsBackendCompatibleImpl(backendApiVersion, backendVersion);
+        }
+    };
+
+    // The backend API version used for the tests
+    armnn::BackendVersion backendApiVersion{ 2, 4 };
+
+    // Same backend and backend API versions are compatible with the backend API
+    armnn::BackendVersion sameBackendVersion{ 2, 4 };
+    BOOST_TEST(sameBackendVersion == backendApiVersion);
+    BOOST_TEST(sameBackendVersion <= backendApiVersion);
+    BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, sameBackendVersion) == true);
+
+    // Backend versions that differ from the backend API version by major revision are not compatible
+    // with the backend API
+    armnn::BackendVersion laterMajorBackendVersion{ 3, 4 };
+    BOOST_TEST(!(laterMajorBackendVersion == backendApiVersion));
+    BOOST_TEST(!(laterMajorBackendVersion <= backendApiVersion));
+    BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMajorBackendVersion) == false);
+
+    armnn::BackendVersion earlierMajorBackendVersion{ 1, 4 };
+    BOOST_TEST(!(earlierMajorBackendVersion == backendApiVersion));
+    BOOST_TEST(earlierMajorBackendVersion <= backendApiVersion);
+    BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion,
+                                                                earlierMajorBackendVersion) == false);
+
+    // Backend versions with the same major revision but later minor revision than
+    // the backend API version are not compatible with the backend API
+    armnn::BackendVersion laterMinorBackendVersion{ 2, 5 };
+    BOOST_TEST(!(laterMinorBackendVersion == backendApiVersion));
+    BOOST_TEST(!(laterMinorBackendVersion <= backendApiVersion));
+    BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, laterMinorBackendVersion) == false);
+
+    // Backend versions with the same major revision but earlier minor revision than
+    // the backend API version are compatible with the backend API
+    armnn::BackendVersion earlierMinorBackendVersion{ 2, 3 };
+    BOOST_TEST(!(earlierMinorBackendVersion == backendApiVersion));
+    BOOST_TEST(earlierMinorBackendVersion <= backendApiVersion);
+    BOOST_TEST(TestDynamicBackendUtils::IsBackendCompatibleTest(backendApiVersion, earlierMinorBackendVersion) == true);
+}