From c1c872f12797ef6fe52c4589113e7efc353e56eb Mon Sep 17 00:00:00 2001 From: Jan Eilers Date: Thu, 22 Jul 2021 13:17:04 +0100 Subject: Adds CustomAllocator interface and Sample App * Updates the runtime options with a CustomAllocatorMap which allows to define a CustomAllocator for specific backends * Change IBackendInternal interface to use a shared pointer to a custom allocator * Update ClBackend.hpp/cpp to use the CustomAllocator * Adds an example application and unit test which uses a CustomAllocator for GpuAcc * Refactor of the interface to use MemorySource instead of the user Mapping cl_mem directly * Modify the BackendRegistry to also hold a registry of CustomAllocators * BackendRegistry Deregister will also deregister any allocators associated with that backend id * set_global_allocator within the BaseMemoryManager so that it always matches the currently used allocator Signed-off-by: Jan Eilers Change-Id: I156d819686021865f4375e6cb7a5c5dec8fee9e8 Signed-off-by: David Monahan --- src/armnn/BackendRegistry.cpp | 21 ++++++ src/armnn/Runtime.cpp | 64 +++++++++++++++--- src/armnn/test/OptimizerTests.cpp | 133 +------------------------------------- 3 files changed, 80 insertions(+), 138 deletions(-) (limited to 'src/armnn') diff --git a/src/armnn/BackendRegistry.cpp b/src/armnn/BackendRegistry.cpp index ff63c8236a..80daed9896 100644 --- a/src/armnn/BackendRegistry.cpp +++ b/src/armnn/BackendRegistry.cpp @@ -39,6 +39,7 @@ void BackendRegistry::Register(const BackendId& id, BackendRegistry::FactoryFunc void BackendRegistry::Deregister(const BackendId& id) { m_Factories.erase(id); + DeregisterAllocator(id); if (m_ProfilingService.has_value() && m_ProfilingService.value().IsProfilingEnabled()) { @@ -106,5 +107,25 @@ void BackendRegistry::SetProfilingService(armnn::Optional alloc) +{ + if (m_CustomMemoryAllocatorMap.find(id) != m_CustomMemoryAllocatorMap.end()) + { + throw InvalidArgumentException( + std::string(id) + " already has an allocator associated with it", + CHECK_LOCATION()); + } + m_CustomMemoryAllocatorMap[id] = alloc; +} + +void BackendRegistry::DeregisterAllocator(const BackendId& id) +{ + m_CustomMemoryAllocatorMap.erase(id); +} + +std::unordered_map> BackendRegistry::GetAllocators() +{ + return m_CustomMemoryAllocatorMap; +} } // namespace armnn diff --git a/src/armnn/Runtime.cpp b/src/armnn/Runtime.cpp index c2b748653d..9fe58287c3 100644 --- a/src/armnn/Runtime.cpp +++ b/src/armnn/Runtime.cpp @@ -130,7 +130,8 @@ Status RuntimeImpl::LoadNetwork(NetworkId& networkIdOut, IOptimizedNetworkPtr inNetwork, std::string& errorMessage) { - INetworkProperties networkProperties(false, MemorySource::Undefined, MemorySource::Undefined); + INetworkProperties networkProperties( + false, MemorySource::Undefined, MemorySource::Undefined); return LoadNetwork(networkIdOut, std::move(inNetwork), errorMessage, networkProperties); } @@ -267,7 +268,8 @@ RuntimeImpl::RuntimeImpl(const IRuntime::CreationOptions& options) if ( options.m_ProfilingOptions.m_TimelineEnabled && !options.m_ProfilingOptions.m_EnableProfiling ) { - throw RuntimeException("It is not possible to enable timeline reporting without profiling being enabled"); + throw RuntimeException( + "It is not possible to enable timeline reporting without profiling being enabled"); } // Load any available/compatible dynamic backend before the runtime @@ -283,6 +285,8 @@ RuntimeImpl::RuntimeImpl(const IRuntime::CreationOptions& options) auto backend = factoryFun(); ARMNN_ASSERT(backend.get() != nullptr); + auto customAllocatorMapIterator = options.m_CustomAllocatorMap.find(id); + // If the runtime is created in protected mode only add backends that support this mode if (options.m_ProtectedMode) { @@ -298,17 +302,61 @@ RuntimeImpl::RuntimeImpl(const IRuntime::CreationOptions& options) << " is not registered as does not support protected content allocation \n"; continue; } - std::string err; - if (!backend->UseCustomMemoryAllocator(err)) + // The user is responsible to provide a custom memory allocator which allows to allocate + // protected memory + if (customAllocatorMapIterator != options.m_CustomAllocatorMap.end()) { - ARMNN_LOG(error) << "The backend " + std::string err; + if (customAllocatorMapIterator->second->GetMemorySourceType() + == armnn::MemorySource::DmaBufProtected) + { + if (!backend->UseCustomMemoryAllocator(customAllocatorMapIterator->second, err)) + { + ARMNN_LOG(error) << "The backend " + << id + << " reported an error when entering protected mode. Backend won't be" + << " used. ErrorMsg: " << err; + continue; + } + // No errors so register the Custom Allocator with the BackendRegistry + BackendRegistryInstance().RegisterAllocator(id, customAllocatorMapIterator->second); + } + else + { + ARMNN_LOG(error) << "The CustomAllocator provided with the runtime options doesn't support " + "protected memory. Protected mode can't be activated. The backend " << id - << " reported an error when entering protected mode. Backend won't be used." - << " ErrorMsg: " << err; + << " is not going to be used. MemorySource must be MemorySource::DmaBufProtected"; + continue; + } + } + else + { + ARMNN_LOG(error) << "Protected mode can't be activated for backend: " + << id + << " no custom allocator was provided to the runtime options."; continue; } } - + else + { + // If a custom memory allocator is provided make the backend use that instead of the default + if (customAllocatorMapIterator != options.m_CustomAllocatorMap.end()) + { + std::string err; + if (!backend->UseCustomMemoryAllocator(customAllocatorMapIterator->second, err)) + { + ARMNN_LOG(error) << "The backend " + << id + << " reported an error when trying to use the provided custom allocator." + " Backend won't be used." + << " ErrorMsg: " << err; + continue; + } + // No errors so register the Custom Allocator with the BackendRegistry + BackendRegistryInstance().RegisterAllocator(id, customAllocatorMapIterator->second); + } + } 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 19bd58193a..38aef671d2 100644 --- a/src/armnn/test/OptimizerTests.cpp +++ b/src/armnn/test/OptimizerTests.cpp @@ -220,9 +220,10 @@ public: return m_BackendCapabilities; }; - virtual bool UseCustomMemoryAllocator(armnn::Optional errMsg) override + virtual bool UseCustomMemoryAllocator(std::shared_ptr allocator, + armnn::Optional errMsg) override { - IgnoreUnused(errMsg); + IgnoreUnused(errMsg, allocator); m_CustomAllocator = true; return m_CustomAllocator; } @@ -925,131 +926,3 @@ TEST_CASE("OptimizeForExclusiveConnectionsWithoutFuseTest") &IsLayerOfType)); } } // 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 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>(mockBackendCapabilities); - }); - // 2. Supports protected mode and has it implemented correctly - backendRegistry.Register("MockBackendProtectedContent", [mockProtectedBackendCapabilities]() - { - return std::make_unique>(mockProtectedBackendCapabilities); - }); - // 3. Claims to support protected mode but doesn't have the UseCustomMemoryAllocator function implemented - backendRegistry.Register("SillyMockBackend", [mockProtectedBackendCapabilities]() - { - return std::make_unique>(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()); - } - -} -} -- cgit v1.2.1