aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Eilers <jan.eilers@arm.com>2021-07-14 13:50:15 +0100
committerJan Eilers <jan.eilers@arm.com>2021-07-22 11:58:01 +0100
commit15fcc7ed3163c9d4b1856955271854198c3c2696 (patch)
treea4c2991ec2150c23c593f683df749f12b425cc84
parent801e2d55de7a02b98f3d77dc9775b10b2bd9f16b (diff)
downloadarmnn-15fcc7ed3163c9d4b1856955271854198c3c2696.tar.gz
IVGCVSW-6073 Add protected mode to ArmNN CreationOptions
* Adds logic to the Runtime to activate protected mode * Adds ProtectedContentAllocation backend capability to ClBackend It's not fully activated yet because the CustomAllocator is missing. Will print an error message and won't register the backend but won't fail. * Extends IBackendInternal with an UseCustomAllocator function. * Adds related unit tests Signed-off-by: Jan Eilers <jan.eilers@arm.com> Change-Id: I64f465c5800eb104aa90db1bbf772a4148b5072f
-rw-r--r--include/armnn/IRuntime.hpp7
-rw-r--r--include/armnn/backends/IBackendInternal.hpp27
-rw-r--r--src/armnn/Runtime.cpp27
-rw-r--r--src/armnn/test/OptimizerTests.cpp346
-rw-r--r--src/backends/backendsCommon/test/DynamicBackendTests.hpp2
-rw-r--r--src/backends/cl/ClBackend.hpp17
6 files changed, 351 insertions, 75 deletions
diff --git a/include/armnn/IRuntime.hpp b/include/armnn/IRuntime.hpp
index bee61d21a9..fcb8c05e30 100644
--- a/include/armnn/IRuntime.hpp
+++ b/include/armnn/IRuntime.hpp
@@ -90,6 +90,7 @@ public:
, m_EnableGpuProfiling(false)
, m_DynamicBackendsPath("")
, m_CustomAllocator(nullptr)
+ , m_ProtectedMode(false)
{}
/// If set, uses the GpuAcc tuned parameters from the given object when executing GPU workloads.
@@ -108,6 +109,12 @@ public:
/// Only supported for GpuAcc
ICustomAllocator* m_CustomAllocator;
+ /// Setting this flag will allow the user to create the Runtime in protected mode.
+ /// It will run all the inferences on protected memory and will make sure that
+ /// INetworkProperties::m_ImportEnabled set to true with MemorySource::DmaBufProtected option
+ /// This will use Protected Memory Allocator associated with the backend
+ bool m_ProtectedMode;
+
struct ExternalProfilingOptions
{
ExternalProfilingOptions()
diff --git a/include/armnn/backends/IBackendInternal.hpp b/include/armnn/backends/IBackendInternal.hpp
index b8edfe1f71..3b4ef95703 100644
--- a/include/armnn/backends/IBackendInternal.hpp
+++ b/include/armnn/backends/IBackendInternal.hpp
@@ -56,6 +56,13 @@ struct BackendVersion
(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)
@@ -176,7 +183,7 @@ public:
MemorySourceFlags outputFlags);
/// Returns the version of the Backend API
- static constexpr BackendVersion GetApiVersion() { return BackendVersion(1, 0); }
+ static constexpr BackendVersion GetApiVersion() { return BackendVersion(1, 1); }
/// Returns a BackendCapability if the backend lists the capability
/// The BackendCapability must then be inspected to check whether or not that BackendCapability is supported
@@ -189,6 +196,24 @@ public:
/// Returns true if backend support the capability false otherwise
ARMNN_DEPRECATED_MSG("This function has been deprecated in favour of GetCapability")
virtual bool HasCapability(BackendCapability /*capabilityClass*/) const { return false; }
+
+ /// Signals the backend to use a custom memory allocator provided by the user
+ ///
+ /// \param errMsg - Optional string variable to return error messages
+ /// \return - Returns true if switching to custom allocator was successful
+ virtual bool UseCustomMemoryAllocator(armnn::Optional<std::string&> errMsg)
+ {
+ if (errMsg)
+ {
+ std::stringstream message;
+ message << "The backend " << GetId() << " doesn't support using a custom allocator. This error might"
+ " be related with the protected mode if the backend doesn't"
+ " fully support it.";
+
+ errMsg.value() = message.str();
+ }
+ return false;
+ }
};
using IBackendInternalUniquePtr = std::unique_ptr<IBackendInternal>;
diff --git a/src/armnn/Runtime.cpp b/src/armnn/Runtime.cpp
index f16d186191..c2b748653d 100644
--- a/src/armnn/Runtime.cpp
+++ b/src/armnn/Runtime.cpp
@@ -6,6 +6,7 @@
#include <armnn/Version.hpp>
#include <armnn/BackendRegistry.hpp>
+#include <armnn/BackendHelper.hpp>
#include <armnn/Logging.hpp>
#include <armnn/utility/Timer.hpp>
@@ -282,6 +283,32 @@ RuntimeImpl::RuntimeImpl(const IRuntime::CreationOptions& options)
auto backend = factoryFun();
ARMNN_ASSERT(backend.get() != nullptr);
+ // If the runtime is created in protected mode only add backends that support this mode
+ if (options.m_ProtectedMode)
+ {
+ // check if backend supports ProtectedMode
+ using BackendCapability = BackendOptions::BackendOption;
+ BackendCapability protectedContentCapability {"ProtectedContentAllocation", true};
+ if (!HasCapability(protectedContentCapability, id))
+ {
+ // Protected Content Allocation is not supported by the backend
+ // backend should not be registered
+ ARMNN_LOG(warning) << "Backend "
+ << id
+ << " is not registered as does not support protected content allocation \n";
+ continue;
+ }
+ std::string err;
+ if (!backend->UseCustomMemoryAllocator(err))
+ {
+ ARMNN_LOG(error) << "The backend "
+ << id
+ << " reported an error when entering protected mode. Backend won't be used."
+ << " ErrorMsg: " << err;
+ continue;
+ }
+ }
+
auto context = backend->CreateBackendContext(options);
// backends are allowed to return nullptrs if they
diff --git a/src/armnn/test/OptimizerTests.cpp b/src/armnn/test/OptimizerTests.cpp
index d4e2d499d5..19bd58193a 100644
--- a/src/armnn/test/OptimizerTests.cpp
+++ b/src/armnn/test/OptimizerTests.cpp
@@ -139,6 +139,153 @@ void CreateLSTMLayerHelper(Graph &graph, bool CifgEnabled)
Connect(layer, output, lstmTensorInfo3, 3, 0);
}
+
+class MockLayerSupport : public LayerSupportBase
+{
+public:
+ bool IsInputSupported(const TensorInfo& /*input*/,
+ Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
+ {
+ return true;
+ }
+
+ bool IsOutputSupported(const TensorInfo& /*input*/,
+ Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
+ {
+ return true;
+ }
+
+ bool IsActivationSupported(const TensorInfo& /*input0*/,
+ const TensorInfo& /*output*/,
+ const ActivationDescriptor& /*descriptor*/,
+ Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
+ {
+ return true;
+ }
+};
+
+template <typename NamePolicy>
+class MockBackend : public IBackendInternal
+{
+public:
+ MockBackend() :
+ m_BackendCapabilities(NamePolicy::GetIdStatic(), {{"NullCapability", false}}),
+ m_CustomAllocator(false) {};
+ MockBackend(const BackendCapabilities& capabilities) :
+ m_BackendCapabilities(capabilities),
+ m_CustomAllocator(false) {};
+ ~MockBackend() = default;
+
+ static const BackendId& GetIdStatic()
+ {
+ return NamePolicy::GetIdStatic();
+ }
+ const BackendId& GetId() const override
+ {
+ return GetIdStatic();
+ }
+
+ IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager() const override
+ {
+ return nullptr;
+ };
+
+ IBackendInternal::IWorkloadFactoryPtr
+ CreateWorkloadFactory(const IBackendInternal::IMemoryManagerSharedPtr&) const override
+ {
+ return nullptr;
+ }
+
+ IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const override
+ {
+ return nullptr;
+ }
+
+ IBackendInternal::Optimizations GetOptimizations() const override
+ {
+ return {};
+ }
+ IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override
+ {
+ return std::make_shared<MockLayerSupport>();
+ }
+
+ OptimizationViews OptimizeSubgraphView(const SubgraphView&) const override
+ {
+ return {};
+ };
+
+ BackendCapabilities GetCapabilities() const override
+ {
+ return m_BackendCapabilities;
+ };
+
+ virtual bool UseCustomMemoryAllocator(armnn::Optional<std::string&> errMsg) override
+ {
+ IgnoreUnused(errMsg);
+ m_CustomAllocator = true;
+ return m_CustomAllocator;
+ }
+
+ BackendCapabilities m_BackendCapabilities;
+ bool m_CustomAllocator;
+};
+
+template <typename NamePolicy>
+class NoProtectedModeMockBackend : public IBackendInternal
+{
+public:
+ NoProtectedModeMockBackend() : m_BackendCapabilities(NamePolicy::GetIdStatic(), {{"NullCapability", false}}) {};
+ NoProtectedModeMockBackend(const BackendCapabilities& capabilities) : m_BackendCapabilities(capabilities) {};
+ ~NoProtectedModeMockBackend() = default;
+
+ static const BackendId& GetIdStatic()
+ {
+ return NamePolicy::GetIdStatic();
+ }
+ const BackendId& GetId() const override
+ {
+ return GetIdStatic();
+ }
+
+ IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager() const override
+ {
+ return nullptr;
+ };
+
+ IBackendInternal::IWorkloadFactoryPtr
+ CreateWorkloadFactory(const IBackendInternal::IMemoryManagerSharedPtr&) const override
+ {
+ return nullptr;
+ }
+
+ IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const override
+ {
+ return nullptr;
+ }
+
+ IBackendInternal::Optimizations GetOptimizations() const override
+ {
+ return {};
+ }
+ IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override
+ {
+ return std::make_shared<MockLayerSupport>();
+ }
+
+ OptimizationViews OptimizeSubgraphView(const SubgraphView&) const override
+ {
+ return {};
+ };
+
+ BackendCapabilities GetCapabilities() const override
+ {
+ return m_BackendCapabilities;
+ };
+
+ BackendCapabilities m_BackendCapabilities;
+};
+
} // namespace
TEST_SUITE("Optimizer")
@@ -543,77 +690,6 @@ TEST_CASE("DetectionPostProcessValidateTensorShapes")
CHECK_NOTHROW(graph.InferTensorInfos());
}
-class MockLayerSupport : public LayerSupportBase
-{
-public:
- bool IsInputSupported(const TensorInfo& /*input*/,
- Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
- {
- return true;
- }
-
- bool IsOutputSupported(const TensorInfo& /*input*/,
- Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
- {
- return true;
- }
-
- bool IsActivationSupported(const TensorInfo& /*input0*/,
- const TensorInfo& /*output*/,
- const ActivationDescriptor& /*descriptor*/,
- Optional<std::string&> /*reasonIfUnsupported = EmptyOptional()*/) const override
- {
- return true;
- }
-};
-
-template <typename NamePolicy>
-class MockBackend : public IBackendInternal
-{
-public:
- MockBackend() = default;
- ~MockBackend() = default;
-
- static const BackendId& GetIdStatic()
- {
- return NamePolicy::GetIdStatic();
- }
- const BackendId& GetId() const override
- {
- return GetIdStatic();
- }
-
- IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager() const override
- {
- return nullptr;
- };
-
- IBackendInternal::IWorkloadFactoryPtr
- CreateWorkloadFactory(const IBackendInternal::IMemoryManagerSharedPtr&) const override
- {
- return nullptr;
- }
-
- IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const override
- {
- return nullptr;
- }
-
- IBackendInternal::Optimizations GetOptimizations() const override
- {
- return {};
- }
- IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override
- {
- return std::make_shared<MockLayerSupport>();
- }
-
- OptimizationViews OptimizeSubgraphView(const SubgraphView&) const override
- {
- return {};
- };
-};
-
TEST_CASE("BackendCapabilityTest")
{
BackendId backendId = "MockBackend";
@@ -848,4 +924,132 @@ TEST_CASE("OptimizeForExclusiveConnectionsWithoutFuseTest")
&IsLayerOfType<armnn::OutputLayer>,
&IsLayerOfType<armnn::OutputLayer>));
}
+} // Optimizer TestSuite
+
+TEST_SUITE("Runtime")
+{
+// This test really belongs into RuntimeTests.cpp but it requires all sort of MockBackends which are
+// already defined here
+TEST_CASE("RuntimeProtectedModeOption")
+{
+ using namespace armnn;
+
+ struct MockPolicy
+ {
+ static const BackendId& GetIdStatic()
+ {
+ static BackendId id = "MockBackend";
+ return id;
+ }
+ };
+
+ struct ProtectedPolicy
+ {
+ static const BackendId& GetIdStatic()
+ {
+ static BackendId id = "MockBackendProtectedContent";
+ return id;
+ }
+ };
+
+ struct SillyPolicy
+ {
+ static const BackendId& GetIdStatic()
+ {
+ static BackendId id = "SillyMockBackend";
+ return id;
+ }
+ };
+
+ BackendCapabilities mockBackendCapabilities("MockBackend",
+ {
+ {"ProtectedContentAllocation", false}
+ });
+ BackendCapabilities mockProtectedBackendCapabilities("MockBackendProtectedContent",
+ {
+ {"ProtectedContentAllocation", true}
+ });
+
+ auto& backendRegistry = BackendRegistryInstance();
+
+ // clean up from previous test runs
+ std::vector<BackendId> mockBackends = {"MockBackend", "MockBackendProtectedContent", "SillyMockBackend"};
+ for (auto& backend : mockBackends)
+ {
+ backendRegistry.Deregister(backend);
+ }
+
+ // Create a bunch of MockBackends with different capabilities
+ // 1. Doesn't support protected mode even though it knows about this capability
+ backendRegistry.Register("MockBackend", [mockBackendCapabilities]()
+ {
+ return std::make_unique<MockBackend<MockPolicy>>(mockBackendCapabilities);
+ });
+ // 2. Supports protected mode and has it implemented correctly
+ backendRegistry.Register("MockBackendProtectedContent", [mockProtectedBackendCapabilities]()
+ {
+ return std::make_unique<MockBackend<ProtectedPolicy>>(mockProtectedBackendCapabilities);
+ });
+ // 3. Claims to support protected mode but doesn't have the UseCustomMemoryAllocator function implemented
+ backendRegistry.Register("SillyMockBackend", [mockProtectedBackendCapabilities]()
+ {
+ return std::make_unique<NoProtectedModeMockBackend<SillyPolicy>>(mockProtectedBackendCapabilities);
+ });
+
+ // Creates a runtime that is not in protected mode
+ {
+ IRuntime::CreationOptions creationOptions;
+ creationOptions.m_ProtectedMode = false;
+
+ IRuntimePtr run = IRuntime::Create(creationOptions);
+
+ const armnn::BackendIdSet supportedDevices = run->GetDeviceSpec().GetSupportedBackends();
+ // Both MockBackends that are registered should show up in the runtimes supported backends list
+ for (auto& backend : mockBackends)
+ {
+ CHECK(std::find(supportedDevices.cbegin(), supportedDevices.cend(), backend) != supportedDevices.cend());
+ }
+ }
+
+ // If the runtime is in protected mode only backends that support protected content should be added
+ {
+ IRuntime::CreationOptions creationOptions;
+ creationOptions.m_ProtectedMode = true;
+
+ IRuntimePtr run = IRuntime::Create(creationOptions);
+
+ const armnn::BackendIdSet supportedDevices = run->GetDeviceSpec().GetSupportedBackends();
+ // Only the MockBackends that claims support for protected content should show up in the
+ // runtimes supported backends list
+ CHECK(std::find(supportedDevices.cbegin(),
+ supportedDevices.cend(),
+ "MockBackendProtectedContent") != supportedDevices.cend());
+ CHECK(std::find(supportedDevices.cbegin(),
+ supportedDevices.cend(),
+ "MockBackend") == supportedDevices.cend());
+ CHECK(std::find(supportedDevices.cbegin(),
+ supportedDevices.cend(),
+ "SillyMockBackend") == supportedDevices.cend());
+ }
+
+ // If the runtime is in protected mode only backends that support protected content should be added
+ {
+ IRuntime::CreationOptions creationOptions;
+ creationOptions.m_ProtectedMode = true;
+
+ IRuntimePtr run = IRuntime::Create(creationOptions);
+
+ const armnn::BackendIdSet supportedDevices = run->GetDeviceSpec().GetSupportedBackends();
+ // Only the MockBackend that claims support for protected content should show up in the
+ // runtimes supported backends list
+ CHECK(std::find(supportedDevices.cbegin(),
+ supportedDevices.cend(),
+ "MockBackendProtectedContent") != supportedDevices.cend());
+
+ CHECK(std::find(supportedDevices.cbegin(),
+ supportedDevices.cend(),
+ "MockBackend") == supportedDevices.cend());
+ }
+
+}
}
diff --git a/src/backends/backendsCommon/test/DynamicBackendTests.hpp b/src/backends/backendsCommon/test/DynamicBackendTests.hpp
index cfcdf8e59c..f49c36e5b1 100644
--- a/src/backends/backendsCommon/test/DynamicBackendTests.hpp
+++ b/src/backends/backendsCommon/test/DynamicBackendTests.hpp
@@ -560,7 +560,7 @@ void CreateDynamicBackendObjectInvalidInterface6TestImpl()
BackendVersion dynamicBackendVersion;
CHECK_NOTHROW(dynamicBackendVersion = dynamicBackend->GetBackendVersion());
- CHECK((dynamicBackendVersion == BackendVersion({ 1, 0 })));
+ CHECK((dynamicBackendVersion >= BackendVersion({ 1, 0 })));
IBackendInternalUniquePtr dynamicBackendInstance1;
CHECK_THROWS_AS(dynamicBackendInstance1 = dynamicBackend->GetBackend(), RuntimeException);
diff --git a/src/backends/cl/ClBackend.hpp b/src/backends/cl/ClBackend.hpp
index db03cfeff0..c742c0b204 100644
--- a/src/backends/cl/ClBackend.hpp
+++ b/src/backends/cl/ClBackend.hpp
@@ -13,13 +13,14 @@ namespace armnn
const BackendCapabilities gpuAccCapabilities("GpuAcc",
{
{"NonConstWeights", false},
- {"AsyncExecution", false}
+ {"AsyncExecution", false},
+ {"ProtectedContentAllocation", true}
});
class ClBackend : public IBackendInternal
{
public:
- ClBackend() = default;
+ ClBackend() : m_EnableCustomAllocator(false) {};
~ClBackend() = default;
static const BackendId& GetIdStatic();
@@ -70,6 +71,18 @@ public:
{
return gpuAccCapabilities;
};
+
+ virtual bool UseCustomMemoryAllocator(armnn::Optional<std::string&> errMsg) override
+ {
+ IgnoreUnused(errMsg);
+
+ // Set flag to signal the backend to use a custom memory allocator
+ m_EnableCustomAllocator = true;
+
+ return m_EnableCustomAllocator;
+ }
+
+ bool m_EnableCustomAllocator;
};
} // namespace armnn