From e8d7ccb1a18b5c39ecf17fb063fcc50baacc74b3 Mon Sep 17 00:00:00 2001 From: Francis Murtagh Date: Thu, 14 Oct 2021 17:30:24 +0100 Subject: IVGCVSW-6310 Update ICustomAllocator and add GetDefaultAllocator function to backends Signed-off-by: Francis Murtagh Change-Id: If2879e8a82692285e7fa3f4d09abd608ca28de12 --- include/armnn/backends/IBackendInternal.hpp | 20 ++-- include/armnn/backends/ICustomAllocator.hpp | 26 +++-- samples/CustomMemoryAllocatorSample.cpp | 12 +-- src/backends/backendsCommon/DefaultAllocator.hpp | 45 ++++++++ src/backends/backendsCommon/test/MockBackend.cpp | 6 ++ src/backends/backendsCommon/test/MockBackend.hpp | 2 + src/backends/cl/test/CMakeLists.txt | 1 + src/backends/cl/test/ClCustomAllocatorTests.cpp | 10 +- src/backends/cl/test/DefaultAllocatorTests.cpp | 124 +++++++++++++++++++++++ src/backends/neon/NeonBackend.cpp | 25 +++-- src/backends/neon/NeonBackend.hpp | 2 + src/backends/reference/RefBackend.cpp | 6 ++ src/backends/reference/RefBackend.hpp | 2 + 13 files changed, 244 insertions(+), 37 deletions(-) create mode 100644 src/backends/backendsCommon/DefaultAllocator.hpp create mode 100644 src/backends/cl/test/DefaultAllocatorTests.cpp diff --git a/include/armnn/backends/IBackendInternal.hpp b/include/armnn/backends/IBackendInternal.hpp index f4fe678a5b..7500e35897 100644 --- a/include/armnn/backends/IBackendInternal.hpp +++ b/include/armnn/backends/IBackendInternal.hpp @@ -13,12 +13,12 @@ #include #include -#include "IBackendContext.hpp" -#include "armnn/backends/profiling/IBackendProfiling.hpp" -#include "armnn/backends/profiling/IBackendProfilingContext.hpp" -#include "IMemoryManager.hpp" -#include "ITensorHandleFactory.hpp" -#include "OptimizationViews.hpp" +#include +#include +#include +#include +#include +#include #include #include @@ -198,6 +198,14 @@ public: } return false; } + + /// Returns the default memory allocator for the backend + /// + /// \return - Returns unique pointer to the Default Allocator of the Backend + virtual std::unique_ptr GetDefaultAllocator() const + { + throw armnn::Exception("GetDefaultAllocator: Function has not been implemented in backend."); + } }; using IBackendInternalUniquePtr = std::unique_ptr; diff --git a/include/armnn/backends/ICustomAllocator.hpp b/include/armnn/backends/ICustomAllocator.hpp index 2cb5f41f78..eb8dfe1459 100644 --- a/include/armnn/backends/ICustomAllocator.hpp +++ b/include/armnn/backends/ICustomAllocator.hpp @@ -8,6 +8,7 @@ #include #include #include +#include namespace armnn { @@ -31,13 +32,26 @@ public: /** Interface to be implemented by the child class to free the allocated bytes */ virtual void free(void* ptr) = 0; - // Used to specify what type of memory is being allocated by this allocator. - // Supported types are: - // MemorySource::Malloc - // MemorySource::DmaBuf - // Unsupported types are: - // MemorySource::DmaBufProtected + /** Used to specify what type of memory is being allocated by this allocator. + * Supported types are: + * MemorySource::Malloc + * MemorySource::DmaBuf + * Unsupported types are: + * MemorySource::DmaBufProtected + */ virtual armnn::MemorySource GetMemorySourceType() = 0; + /** Interface that may be implemented to allow retrieval of Memory Region + * from allocated buffer at a certain offset + */ + virtual void* GetMemoryRegionAtOffset(void* buffer, size_t offset, size_t alignment = 0) + { + IgnoreUnused(offset); + IgnoreUnused(alignment); + IgnoreUnused(buffer); + throw armnn::Exception( + "ICustomerAllocator::GetMemoryRegionAtOffset(): This function should be overridden in subclass."); + } + }; } // namespace armnn \ No newline at end of file diff --git a/samples/CustomMemoryAllocatorSample.cpp b/samples/CustomMemoryAllocatorSample.cpp index 51b3c81079..a21158b251 100644 --- a/samples/CustomMemoryAllocatorSample.cpp +++ b/samples/CustomMemoryAllocatorSample.cpp @@ -19,7 +19,7 @@ class SampleClBackendCustomAllocator : public armnn::ICustomAllocator public: SampleClBackendCustomAllocator() = default; - void* allocate(size_t size, size_t alignment) + void* allocate(size_t size, size_t alignment) override { // If alignment is 0 just use the CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE for alignment if (alignment == 0) @@ -35,16 +35,6 @@ public: } return allocatedMemPtr; } - - void free(void* ptr) - { - std::free(ptr); - } - - armnn::MemorySource GetMemorySourceType() - { - return armnn::MemorySource::Malloc; - } }; diff --git a/src/backends/backendsCommon/DefaultAllocator.hpp b/src/backends/backendsCommon/DefaultAllocator.hpp new file mode 100644 index 0000000000..2451db3ab8 --- /dev/null +++ b/src/backends/backendsCommon/DefaultAllocator.hpp @@ -0,0 +1,45 @@ +// +// Copyright © 2021 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include +#include +#include + +namespace armnn +{ + +/** Default Memory Allocator class returned from IBackendInternal::GetDefaultAllocator(MemorySource) */ +class DefaultAllocator : public armnn::ICustomAllocator +{ +public: + DefaultAllocator() = default; + + void* allocate(size_t size, size_t alignment = 0) override + { + IgnoreUnused(alignment); + return ::operator new(size); + } + + void free(void* ptr) override + { + std::free(ptr); + } + + armnn::MemorySource GetMemorySourceType() override + { + return armnn::MemorySource::Malloc; + } + + void* GetMemoryRegionAtOffset(void* buffer, size_t offset, size_t alignment = 0) override + { + IgnoreUnused(alignment); + return static_cast(buffer) + offset; + } +}; + +} // namespace armnn \ No newline at end of file diff --git a/src/backends/backendsCommon/test/MockBackend.cpp b/src/backends/backendsCommon/test/MockBackend.cpp index df1a5c19aa..4bdb8ce786 100644 --- a/src/backends/backendsCommon/test/MockBackend.cpp +++ b/src/backends/backendsCommon/test/MockBackend.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -258,4 +259,9 @@ OptimizationViews MockBackend::OptimizeSubgraphView(const SubgraphView& subgraph return optimizationViews; } +std::unique_ptr MockBackend::GetDefaultAllocator() const +{ + return std::make_unique(); +} + } // namespace armnn diff --git a/src/backends/backendsCommon/test/MockBackend.hpp b/src/backends/backendsCommon/test/MockBackend.hpp index c0624525dc..6761ce5f08 100644 --- a/src/backends/backendsCommon/test/MockBackend.hpp +++ b/src/backends/backendsCommon/test/MockBackend.hpp @@ -165,6 +165,8 @@ public: IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override; OptimizationViews OptimizeSubgraphView(const SubgraphView& subgraph) const override; + + std::unique_ptr GetDefaultAllocator() const override; }; class MockLayerSupport : public LayerSupportBase diff --git a/src/backends/cl/test/CMakeLists.txt b/src/backends/cl/test/CMakeLists.txt index 41cbe24c15..8ee532a323 100644 --- a/src/backends/cl/test/CMakeLists.txt +++ b/src/backends/cl/test/CMakeLists.txt @@ -17,6 +17,7 @@ list(APPEND armnnClBackendUnitTests_sources ClOptimizedNetworkTests.cpp ClRuntimeTests.cpp ClWorkloadFactoryHelper.hpp + DefaultAllocatorTests.cpp Fp16SupportTest.cpp OpenClTimerTest.cpp ) diff --git a/src/backends/cl/test/ClCustomAllocatorTests.cpp b/src/backends/cl/test/ClCustomAllocatorTests.cpp index e614f4c624..60145139ff 100644 --- a/src/backends/cl/test/ClCustomAllocatorTests.cpp +++ b/src/backends/cl/test/ClCustomAllocatorTests.cpp @@ -10,13 +10,13 @@ #include #include #include + #include #if defined(ARMCOMPUTENEON_ENABLED) #include #endif - #include - +#include // Contains the OpenCl interfaces for mapping memory in the Gpu Page Tables // Requires the OpenCl backend to be included (GpuAcc) #include @@ -31,7 +31,7 @@ class SampleClBackendCustomAllocator : public armnn::ICustomAllocator public: SampleClBackendCustomAllocator() = default; - void* allocate(size_t size, size_t alignment) + void* allocate(size_t size, size_t alignment) override { // If alignment is 0 just use the CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE for alignment if (alignment == 0) @@ -49,12 +49,12 @@ public: } /** Interface to be implemented by the child class to free the allocated tensor */ - void free(void* ptr) + void free(void* ptr) override { std::free(ptr); } - armnn::MemorySource GetMemorySourceType() + armnn::MemorySource GetMemorySourceType() override { return armnn::MemorySource::Malloc; } diff --git a/src/backends/cl/test/DefaultAllocatorTests.cpp b/src/backends/cl/test/DefaultAllocatorTests.cpp new file mode 100644 index 0000000000..196c0fb412 --- /dev/null +++ b/src/backends/cl/test/DefaultAllocatorTests.cpp @@ -0,0 +1,124 @@ +// +// Copyright © 2021 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include +#include +#include +#include +#include +// Requires the OpenCl backend to be included (GpuAcc) +#include +#include +#include +#include + +using namespace armnn; + + +namespace +{ + +TEST_SUITE("DefaultAllocatorTests") +{ + +TEST_CASE("DefaultAllocatorTest") +{ + float number = 3; + + TensorInfo inputTensorInfo(TensorShape({1, 1}), DataType::Float32); + + // Create ArmNN runtime + IRuntime::CreationOptions options; // default options + auto customAllocator = std::make_shared(); + options.m_CustomAllocatorMap = {{"GpuAcc", std::move(customAllocator)}}; + IRuntimePtr run = IRuntime::Create(options); + + // Creates structures for input & output + unsigned int numElements = inputTensorInfo.GetNumElements(); + size_t totalBytes = numElements * sizeof(float); + + void* alignedInputPtr = options.m_CustomAllocatorMap["GpuAcc"]->allocate(totalBytes, 0); + + auto* inputPtr = reinterpret_cast(alignedInputPtr); + std::fill_n(inputPtr, numElements, number); + CHECK(inputPtr[0] == 3); + + auto& backendRegistry = armnn::BackendRegistryInstance(); + backendRegistry.DeregisterAllocator(ClBackend::GetIdStatic()); +} + +TEST_CASE("DefaultAllocatorTestMulti") +{ + float number = 3; + + TensorInfo inputTensorInfo(TensorShape({2, 1}), DataType::Float32); + + // Create ArmNN runtime + IRuntime::CreationOptions options; // default options + auto customAllocator = std::make_shared(); + options.m_CustomAllocatorMap = {{"GpuAcc", std::move(customAllocator)}}; + IRuntimePtr run = IRuntime::Create(options); + + // Creates structures for input & output + unsigned int numElements = inputTensorInfo.GetNumElements(); + size_t totalBytes = numElements * sizeof(float); + + void* alignedInputPtr = options.m_CustomAllocatorMap["GpuAcc"]->allocate(totalBytes, 0); + void* alignedInputPtr2 = options.m_CustomAllocatorMap["GpuAcc"]->allocate(totalBytes, 0); + + auto* inputPtr = reinterpret_cast(alignedInputPtr); + std::fill_n(inputPtr, numElements, number); + CHECK(inputPtr[0] == 3); + CHECK(inputPtr[1] == 3); + + auto* inputPtr2 = reinterpret_cast(alignedInputPtr2); + std::fill_n(inputPtr2, numElements, number); + CHECK(inputPtr2[0] == 3); + CHECK(inputPtr2[1] == 3); + + // No overlap + CHECK(inputPtr[0] == 3); + CHECK(inputPtr[1] == 3); + + auto& backendRegistry = armnn::BackendRegistryInstance(); + backendRegistry.DeregisterAllocator(ClBackend::GetIdStatic()); +} + +TEST_CASE("DefaultAllocatorTestMock") +{ + // Create ArmNN runtime + IRuntime::CreationOptions options; // default options + IRuntimePtr run = IRuntime::Create(options); + + // Initialize Mock Backend + MockBackendInitialiser initialiser; + auto factoryFun = BackendRegistryInstance().GetFactory(MockBackend().GetIdStatic()); + ARMNN_ASSERT(factoryFun != nullptr); + auto backend = factoryFun(); + auto defaultAllocator = backend->GetDefaultAllocator(); + + // GetMemorySourceType + CHECK(defaultAllocator->GetMemorySourceType() == MemorySource::Malloc); + + size_t totalBytes = 1 * sizeof(float); + // Allocate + void* ptr = defaultAllocator->allocate(totalBytes, 0); + + // GetMemoryRegionAtOffset + CHECK(defaultAllocator->GetMemoryRegionAtOffset(ptr, 0, 0)); + + // Free + defaultAllocator->free(ptr); + + // Clean up + auto& backendRegistry = armnn::BackendRegistryInstance(); + backendRegistry.Deregister(MockBackend().GetIdStatic()); + backendRegistry.DeregisterAllocator(ClBackend::GetIdStatic()); +} + + +} + +} // namespace armnn \ No newline at end of file diff --git a/src/backends/neon/NeonBackend.cpp b/src/backends/neon/NeonBackend.cpp index 2c3abfd70d..0500ee3411 100644 --- a/src/backends/neon/NeonBackend.cpp +++ b/src/backends/neon/NeonBackend.cpp @@ -22,15 +22,16 @@ #include -#include "workloads/NeonAdditionWorkload.hpp" -#include "workloads/NeonBatchNormalizationWorkload.hpp" -#include "workloads/NeonConvolution2dWorkload.hpp" -#include "workloads/NeonDepthwiseConvolutionWorkload.hpp" -#include "workloads/NeonDivisionWorkload.hpp" -#include "workloads/NeonFullyConnectedWorkload.hpp" -#include "workloads/NeonMultiplicationWorkload.hpp" -#include "workloads/NeonReduceWorkload.hpp" -#include "workloads/NeonSubtractionWorkload.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include @@ -427,4 +428,10 @@ void NeonBackend::RegisterTensorHandleFactories(class TensorHandleFactoryRegistr registry.RegisterFactory(std::make_unique(memoryManager)); } +std::unique_ptr NeonBackend::GetDefaultAllocator() const +{ + return std::make_unique(); +} + + } // namespace armnn diff --git a/src/backends/neon/NeonBackend.hpp b/src/backends/neon/NeonBackend.hpp index 37e1722984..68d60a4c04 100644 --- a/src/backends/neon/NeonBackend.hpp +++ b/src/backends/neon/NeonBackend.hpp @@ -65,6 +65,8 @@ public: { return cpuAccCapabilities; }; + + std::unique_ptr GetDefaultAllocator() const override; }; } // namespace armnn diff --git a/src/backends/reference/RefBackend.cpp b/src/backends/reference/RefBackend.cpp index a3060f0798..ad52434ef8 100644 --- a/src/backends/reference/RefBackend.cpp +++ b/src/backends/reference/RefBackend.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -86,4 +87,9 @@ void RefBackend::RegisterTensorHandleFactories(class TensorHandleFactoryRegistry registry.RegisterFactory(std::make_unique(memoryManager)); } +std::unique_ptr RefBackend::GetDefaultAllocator() const +{ + return std::make_unique(); +} + } // namespace armnn diff --git a/src/backends/reference/RefBackend.hpp b/src/backends/reference/RefBackend.hpp index 4d4aba980b..6114ce6218 100644 --- a/src/backends/reference/RefBackend.hpp +++ b/src/backends/reference/RefBackend.hpp @@ -60,6 +60,8 @@ public: { return cpuRefCapabilities; }; + + std::unique_ptr GetDefaultAllocator() const override; }; } // namespace armnn -- cgit v1.2.1