aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Monahan <David.Monahan@arm.com>2021-11-04 16:31:46 +0000
committerTeresaARM <teresa.charlinreyes@arm.com>2021-11-05 17:23:24 +0000
commit6642b8a1f23c5f7333abf1133983eb3134af7c00 (patch)
tree01a37677720ee4e959367f53b7873322721adbba
parent0f13284d702b3a37f56ffce1412867b5ad9eda89 (diff)
downloadarmnn-6642b8a1f23c5f7333abf1133983eb3134af7c00.tar.gz
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 <David.Monahan@arm.com> Change-Id: Id2abb33d82697df36426f5709756c616af3e8ed7
-rw-r--r--include/armnn/Types.hpp3
-rw-r--r--include/armnn/backends/ICustomAllocator.hpp3
-rw-r--r--samples/CustomMemoryAllocatorSample.cpp10
-rw-r--r--src/backends/cl/CMakeLists.txt1
-rw-r--r--src/backends/cl/ClBackend.cpp6
-rw-r--r--src/backends/cl/ClBackend.hpp2
-rw-r--r--src/backends/cl/ClBackendDefaultAllocator.hpp47
-rw-r--r--src/backends/cl/ClImportTensorHandle.hpp45
-rw-r--r--src/backends/cl/test/DefaultAllocatorTests.cpp69
9 files changed, 182 insertions, 4 deletions
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<ICustomAllocator> ClBackend::GetDefaultAllocator() const
+{
+ return std::make_unique<ClBackendDefaultAllocator>();
+}
+
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<ICustomAllocator> 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 <cstddef>
+#include <memory>
+#include <armnn/MemorySources.hpp>
+#include <armnn/utility/IgnoreUnused.hpp>
+
+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<void *>(buf);
+ }
+
+ void free(void* ptr) override
+ {
+ ARM_COMPUTE_ERROR_ON(ptr == nullptr);
+ clReleaseMemObject(static_cast<cl_mem>(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<char*>(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<cl_mem>(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<cl_mem>(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 <doctest/doctest.h>
#include <backendsCommon/DefaultAllocator.hpp>
#include <backendsCommon/test/MockBackend.hpp>
+#include <cl/ClBackendDefaultAllocator.hpp>
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<ClBackendDefaultAllocator>();
+ 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<float*>(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<ClBackendDefaultAllocator>();
+ 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<float*>(alignedInputPtr);
+ std::fill_n(inputPtr, numElements, number);
+ CHECK(inputPtr[0] == 3);
+ CHECK(inputPtr[1] == 3);
+
+ auto* inputPtr2 = reinterpret_cast<float*>(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());
+}
}