From 6642b8a1f23c5f7333abf1133983eb3134af7c00 Mon Sep 17 00:00:00 2001 From: David Monahan Date: Thu, 4 Nov 2021 16:31:46 +0000 Subject: IVGCVSW-6412 Implement CLBackend ICustomAllocator * Added implementation of ClBackendDefaultAllocator * Added back in some pure virtual functions that were mistakenly removed from the CustomMemoryAllocatorSample * Added a new Gralloc MemorySource for memory which originates from the gpu * Added unittests Signed-off-by: David Monahan Change-Id: Id2abb33d82697df36426f5709756c616af3e8ed7 --- include/armnn/Types.hpp | 3 +- include/armnn/backends/ICustomAllocator.hpp | 3 +- samples/CustomMemoryAllocatorSample.cpp | 10 ++++ src/backends/cl/CMakeLists.txt | 1 + src/backends/cl/ClBackend.cpp | 6 +++ src/backends/cl/ClBackend.hpp | 2 + src/backends/cl/ClBackendDefaultAllocator.hpp | 47 ++++++++++++++++++ src/backends/cl/ClImportTensorHandle.hpp | 45 ++++++++++++++++- src/backends/cl/test/DefaultAllocatorTests.cpp | 69 ++++++++++++++++++++++++++ 9 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 src/backends/cl/ClBackendDefaultAllocator.hpp diff --git a/include/armnn/Types.hpp b/include/armnn/Types.hpp index f61a1fdca8..72c59d9daa 100644 --- a/include/armnn/Types.hpp +++ b/include/armnn/Types.hpp @@ -219,7 +219,8 @@ enum class MemorySource : uint32_t Undefined = 0, Malloc = 1, DmaBuf = 2, - DmaBufProtected = 4 + DmaBufProtected = 4, + Gralloc = 5 }; enum class MemBlockStrategyType diff --git a/include/armnn/backends/ICustomAllocator.hpp b/include/armnn/backends/ICustomAllocator.hpp index eb8dfe1459..59ad27c6f4 100644 --- a/include/armnn/backends/ICustomAllocator.hpp +++ b/include/armnn/backends/ICustomAllocator.hpp @@ -36,8 +36,7 @@ public: * Supported types are: * MemorySource::Malloc * MemorySource::DmaBuf - * Unsupported types are: - * MemorySource::DmaBufProtected + * MemorySource::DmaBufProtected */ virtual armnn::MemorySource GetMemorySourceType() = 0; diff --git a/samples/CustomMemoryAllocatorSample.cpp b/samples/CustomMemoryAllocatorSample.cpp index a21158b251..171d8e2b5d 100644 --- a/samples/CustomMemoryAllocatorSample.cpp +++ b/samples/CustomMemoryAllocatorSample.cpp @@ -35,6 +35,16 @@ public: } return allocatedMemPtr; } + + void free(void* ptr) override + { + std::free(ptr); + } + + armnn::MemorySource GetMemorySourceType() override + { + return armnn::MemorySource::Malloc; + } }; diff --git a/src/backends/cl/CMakeLists.txt b/src/backends/cl/CMakeLists.txt index 0005c8178b..3fef51cdcd 100644 --- a/src/backends/cl/CMakeLists.txt +++ b/src/backends/cl/CMakeLists.txt @@ -23,6 +23,7 @@ if(ARMCOMPUTECL) ClBackend.hpp ClBackendContext.cpp ClBackendContext.hpp + ClBackendDefaultAllocator.hpp ClBackendId.hpp ClBackendModelContext.cpp ClBackendModelContext.hpp diff --git a/src/backends/cl/ClBackend.cpp b/src/backends/cl/ClBackend.cpp index dd58e002be..5c582695e5 100644 --- a/src/backends/cl/ClBackend.cpp +++ b/src/backends/cl/ClBackend.cpp @@ -5,6 +5,7 @@ #include "ClBackend.hpp" #include "ClBackendContext.hpp" +#include "ClBackendDefaultAllocator.hpp" #include "ClBackendId.hpp" #include "ClBackendModelContext.hpp" #include "ClImportTensorHandleFactory.hpp" @@ -216,6 +217,11 @@ IBackendInternal::ILayerSupportSharedPtr ClBackend::GetLayerSupport(const ModelO return layerSupport; } +std::unique_ptr ClBackend::GetDefaultAllocator() const +{ + return std::make_unique(); +} + OptimizationViews ClBackend::OptimizeSubgraphView(const SubgraphView& subgraph, const ModelOptions& modelOptions) const { diff --git a/src/backends/cl/ClBackend.hpp b/src/backends/cl/ClBackend.hpp index ffce800261..7597d093be 100644 --- a/src/backends/cl/ClBackend.hpp +++ b/src/backends/cl/ClBackend.hpp @@ -88,6 +88,8 @@ public: IBackendInternal::IBackendSpecificModelContextPtr CreateBackendSpecificModelContext( const ModelOptions& modelOptions) const override; + std::unique_ptr GetDefaultAllocator() const override; + BackendCapabilities GetCapabilities() const override { return gpuAccCapabilities; diff --git a/src/backends/cl/ClBackendDefaultAllocator.hpp b/src/backends/cl/ClBackendDefaultAllocator.hpp new file mode 100644 index 0000000000..300f560000 --- /dev/null +++ b/src/backends/cl/ClBackendDefaultAllocator.hpp @@ -0,0 +1,47 @@ +// +// 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 ClBackendDefaultAllocator : public armnn::ICustomAllocator +{ +public: + ClBackendDefaultAllocator() = default; + + void* allocate(size_t size, size_t alignment = 0) override + { + IgnoreUnused(alignment); + cl_mem buf{ clCreateBuffer(arm_compute::CLScheduler::get().context().get(), + CL_MEM_ALLOC_HOST_PTR | CL_MEM_READ_WRITE, + size, + nullptr, + nullptr)}; + return static_cast(buf); + } + + void free(void* ptr) override + { + ARM_COMPUTE_ERROR_ON(ptr == nullptr); + clReleaseMemObject(static_cast(ptr)); + } + + armnn::MemorySource GetMemorySourceType() override + { + return armnn::MemorySource::Gralloc; + } + + 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/cl/ClImportTensorHandle.hpp b/src/backends/cl/ClImportTensorHandle.hpp index 48fb2f7d30..a24ab5656e 100644 --- a/src/backends/cl/ClImportTensorHandle.hpp +++ b/src/backends/cl/ClImportTensorHandle.hpp @@ -46,7 +46,7 @@ public: ClImportTensorHandle(const TensorInfo& tensorInfo, DataLayout dataLayout, MemorySourceFlags importFlags) - : m_ImportFlags(importFlags) + : m_ImportFlags(importFlags), m_Imported(false) { armnn::armcomputetensorutils::BuildArmComputeTensor(m_Tensor, tensorInfo, dataLayout); } @@ -139,6 +139,48 @@ public: return ClImport(importProperties, memory, true); } + // Case for importing memory allocated by OpenCl externally directly into the tensor + else if (source == MemorySource::Gralloc) + { + // m_Tensor not yet Allocated + if (!m_Imported && !m_Tensor.buffer()) + { + // Importing memory allocated by OpenCl into the tensor directly. + arm_compute::Status status = + m_Tensor.allocator()->import_memory(cl::Buffer(static_cast(memory))); + m_Imported = bool(status); + if (!m_Imported) + { + throw MemoryImportException(status.error_description()); + } + return m_Imported; + } + + // m_Tensor.buffer() initially allocated with Allocate(). + else if (!m_Imported && m_Tensor.buffer()) + { + throw MemoryImportException( + "ClImportTensorHandle::Import Attempting to import on an already allocated tensor"); + } + + // m_Tensor.buffer() previously imported. + else if (m_Imported) + { + // Importing memory allocated by OpenCl into the tensor directly. + arm_compute::Status status = + m_Tensor.allocator()->import_memory(cl::Buffer(static_cast(memory))); + m_Imported = bool(status); + if (!m_Imported) + { + throw MemoryImportException(status.error_description()); + } + return m_Imported; + } + else + { + throw MemoryImportException("ClImportTensorHandle::Failed to Import Gralloc Memory"); + } + } else { throw MemoryImportException("ClImportTensorHandle::Import flag is not supported"); @@ -276,6 +318,7 @@ private: arm_compute::CLTensor m_Tensor; MemorySourceFlags m_ImportFlags; + bool m_Imported; }; class ClImportSubTensorHandle : public IClImportTensorHandle diff --git a/src/backends/cl/test/DefaultAllocatorTests.cpp b/src/backends/cl/test/DefaultAllocatorTests.cpp index 196c0fb412..3132bc2acb 100644 --- a/src/backends/cl/test/DefaultAllocatorTests.cpp +++ b/src/backends/cl/test/DefaultAllocatorTests.cpp @@ -13,6 +13,7 @@ #include #include #include +#include using namespace armnn; @@ -118,6 +119,74 @@ TEST_CASE("DefaultAllocatorTestMock") backendRegistry.DeregisterAllocator(ClBackend::GetIdStatic()); } +} + + +TEST_SUITE("ClDefaultAllocatorTests") +{ + +TEST_CASE("ClDefaultAllocatorTest") +{ + 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("ClDefaultAllocatorTestMulti") +{ + 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()); +} } -- cgit v1.2.1