blob: 1d2a866f23cf3e0613038918e03630d39772221d [file] [log] [blame]
arovir014424b0a2018-10-04 10:46:04 +01001//
Teresa Charlinee1497c2023-03-30 13:56:34 +01002// Copyright © 2017-2023 Arm Ltd and Contributors. All rights reserved.
arovir014424b0a2018-10-04 10:46:04 +01003// SPDX-License-Identifier: MIT
4//
5#pragma once
6
Matteo Martincighe5b8eb92019-11-28 15:45:42 +00007#include <armnn/backends/IBackendInternal.hpp>
arovir014424b0a2018-10-04 10:46:04 +01008
Jan Eilersc1c872f2021-07-22 13:17:04 +01009#include <arm_compute/core/Types.h>
10#include <arm_compute/runtime/CL/CLBufferAllocator.h>
11
12#include <aclCommon/BaseMemoryManager.hpp>
13#include <arm_compute/runtime/CL/CLMemoryRegion.h>
14
15#include <arm_compute/core/CL/CLKernelLibrary.h>
16#include <CL/cl_ext.h>
17
David Monahane9b12302021-08-12 10:20:21 +010018// System includes for mapping and unmapping memory
19#include <sys/mman.h>
20
arovir014424b0a2018-10-04 10:46:04 +010021namespace armnn
22{
23
24class ClBackend : public IBackendInternal
25{
26public:
Jan Eilersc1c872f2021-07-22 13:17:04 +010027 ClBackend() : m_CustomAllocator(nullptr) {};
28 ClBackend(std::shared_ptr<ICustomAllocator> allocator)
29 {
30 std::string err;
31 UseCustomMemoryAllocator(allocator, err);
32 }
David Beck9efb57d2018-11-05 13:40:33 +000033 ~ClBackend() = default;
arovir014424b0a2018-10-04 10:46:04 +010034
David Beck3cc9a622018-10-12 10:38:31 +010035 static const BackendId& GetIdStatic();
36 const BackendId& GetId() const override { return GetIdStatic(); }
arovir014424b0a2018-10-04 10:46:04 +010037
Aron Virginas-Tar56055192018-11-12 18:10:43 +000038 IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager() const override;
39
40 IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(
41 const IBackendInternal::IMemoryManagerSharedPtr& memoryManager = nullptr) const override;
42
Jan Eilerse9f0f0f2019-08-16 10:28:37 +010043 IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(
44 TensorHandleFactoryRegistry& registry) const override;
45
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +010046 IWorkloadFactoryPtr CreateWorkloadFactory(const IMemoryManagerSharedPtr& memoryManager,
47 const ModelOptions& modelOptions) const override;
Sadik Armagan04a72972020-09-14 15:44:18 +010048
49 IWorkloadFactoryPtr CreateWorkloadFactory(class TensorHandleFactoryRegistry& tensorHandleFactoryRegistry,
50 const ModelOptions& modelOptions) const override;
51
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +010052 IWorkloadFactoryPtr CreateWorkloadFactory(class TensorHandleFactoryRegistry& tensorHandleFactoryRegistry,
53 const ModelOptions& modelOptions,
54 MemorySourceFlags inputFlags,
55 MemorySourceFlags outputFlags) const override;
56
Jan Eilerse9f0f0f2019-08-16 10:28:37 +010057 std::vector<ITensorHandleFactory::FactoryId> GetHandleFactoryPreferences() const override;
58
59 void RegisterTensorHandleFactories(TensorHandleFactoryRegistry& registry) override;
60
Narumol Prangnawarate5f0b242021-05-07 17:52:36 +010061 void RegisterTensorHandleFactories(TensorHandleFactoryRegistry& registry,
62 MemorySourceFlags inputFlags,
63 MemorySourceFlags outputFlags) override;
64
David Beck1b61be52018-11-08 09:19:14 +000065 IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const override;
Colm Donelan1aff3932020-02-05 17:48:59 +000066 IBackendInternal::IBackendProfilingContextPtr CreateBackendProfilingContext(
67 const IRuntime::CreationOptions&, IBackendProfilingPtr& backendProfiling) override;
Aron Virginas-Tar56055192018-11-12 18:10:43 +000068
David Beck111b5d92018-11-12 14:59:37 +000069 IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override;
Sadik Armagan045f6be2020-09-10 13:37:32 +010070 IBackendInternal::ILayerSupportSharedPtr GetLayerSupport(const ModelOptions& modelOptions) const override;
Matteo Martincighadddddb2019-01-24 14:06:23 +000071
Mike Kelly07810fc2020-11-12 10:58:48 +000072 OptimizationViews OptimizeSubgraphView(const SubgraphView& subgraph,
73 const ModelOptions& modelOptions) const override;
Sadik Armagan045f6be2020-09-10 13:37:32 +010074
75 IBackendInternal::IBackendSpecificModelContextPtr CreateBackendSpecificModelContext(
76 const ModelOptions& modelOptions) const override;
Sadik Armaganaede8ca2021-03-31 16:12:13 +010077
David Monahan6642b8a2021-11-04 16:31:46 +000078 std::unique_ptr<ICustomAllocator> GetDefaultAllocator() const override;
79
Ryan OSheab4c49342023-07-25 14:28:27 +010080 BackendCapabilities GetCapabilities() const override;
Jan Eilers15fcc7e2021-07-14 13:50:15 +010081
Jan Eilersc1c872f2021-07-22 13:17:04 +010082 virtual bool UseCustomMemoryAllocator(std::shared_ptr<ICustomAllocator> allocator,
83 armnn::Optional<std::string&> errMsg) override
Jan Eilers15fcc7e2021-07-14 13:50:15 +010084 {
85 IgnoreUnused(errMsg);
Jan Eilersc1c872f2021-07-22 13:17:04 +010086 ARMNN_LOG(info) << "Using Custom Allocator for ClBackend";
Jan Eilers15fcc7e2021-07-14 13:50:15 +010087
88 // Set flag to signal the backend to use a custom memory allocator
Jan Eilersc1c872f2021-07-22 13:17:04 +010089 m_CustomAllocator = std::make_shared<ClBackendCustomAllocatorWrapper>(std::move(allocator));
90 m_UsingCustomAllocator = true;
91 return m_UsingCustomAllocator;
Jan Eilers15fcc7e2021-07-14 13:50:15 +010092 }
93
Sadik Armaganb7851f92021-10-06 16:37:02 +010094 virtual unsigned int GetNumberOfCacheFiles() const override { return 1; }
95
Jan Eilersc1c872f2021-07-22 13:17:04 +010096 // Cl requires a arm_compute::IAllocator we wrap the Arm NN ICustomAllocator to achieve this
97 class ClBackendCustomAllocatorWrapper : public arm_compute::IAllocator
98 {
99 public:
100 ClBackendCustomAllocatorWrapper(std::shared_ptr<ICustomAllocator> alloc) : m_CustomAllocator(alloc)
101 {}
102 // Inherited methods overridden:
103 void* allocate(size_t size, size_t alignment) override
104 {
105 auto alloc = m_CustomAllocator->allocate(size, alignment);
106 return MapAllocatedMemory(alloc, size, m_CustomAllocator->GetMemorySourceType());
107 }
108 void free(void* ptr) override
109 {
110 auto hostMemPtr = m_AllocatedBufferMappings[ptr];
111 clReleaseMemObject(static_cast<cl_mem>(ptr));
112 m_CustomAllocator->free(hostMemPtr);
113 }
114 std::unique_ptr<arm_compute::IMemoryRegion> make_region(size_t size, size_t alignment) override
115 {
116 auto hostMemPtr = m_CustomAllocator->allocate(size, alignment);
117 cl_mem buffer = MapAllocatedMemory(hostMemPtr, size, m_CustomAllocator->GetMemorySourceType());
118
David Monahane9b12302021-08-12 10:20:21 +0100119 return std::make_unique<ClBackendCustomAllocatorMemoryRegion>(cl::Buffer(buffer),
120 hostMemPtr,
121 m_CustomAllocator->GetMemorySourceType());
Jan Eilersc1c872f2021-07-22 13:17:04 +0100122 }
123 private:
124 cl_mem MapAllocatedMemory(void* memory, size_t size, MemorySource source)
125 {
126 // Round the size of the buffer to a multiple of the CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE
127 auto cachelineAlignment =
128 arm_compute::CLKernelLibrary::get().get_device().getInfo<CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE>();
129 auto roundedSize = cachelineAlignment + size - (size % cachelineAlignment);
130
131 if (source == MemorySource::Malloc)
132 {
133 const cl_import_properties_arm importProperties[] =
134 {
Francis Murtagh9db96e02021-08-13 16:15:09 +0100135 CL_IMPORT_TYPE_ARM,
136 CL_IMPORT_TYPE_HOST_ARM,
137 0
Jan Eilersc1c872f2021-07-22 13:17:04 +0100138 };
139 cl_int error = CL_SUCCESS;
140 cl_mem buffer = clImportMemoryARM(arm_compute::CLKernelLibrary::get().context().get(),
141 CL_MEM_READ_WRITE,
142 importProperties,
143 memory,
144 roundedSize,
145 &error);
146 if (error == CL_SUCCESS)
147 {
148 m_AllocatedBufferMappings.insert(std::make_pair(static_cast<void *>(buffer), memory));
149 return buffer;
150 }
151 throw armnn::Exception(
152 "Mapping allocated memory from CustomMemoryAllocator failed, errcode: " + std::to_string(error));
153 }
David Monahane9b12302021-08-12 10:20:21 +0100154 else if (source == MemorySource::DmaBuf)
155 {
156 const cl_import_properties_arm importProperties[] =
157 {
Francis Murtagh9db96e02021-08-13 16:15:09 +0100158 CL_IMPORT_TYPE_ARM,
159 CL_IMPORT_TYPE_DMA_BUF_ARM,
160 CL_IMPORT_DMA_BUF_DATA_CONSISTENCY_WITH_HOST_ARM,
161 CL_TRUE,
162 0
163 };
164 cl_int error = CL_SUCCESS;
165 cl_mem buffer = clImportMemoryARM(arm_compute::CLKernelLibrary::get().context().get(),
166 CL_MEM_READ_WRITE,
167 importProperties,
168 memory,
169 roundedSize,
170 &error);
171 if (error == CL_SUCCESS)
172 {
173 m_AllocatedBufferMappings.insert(std::make_pair(static_cast<void *>(buffer), memory));
174 return buffer;
175 }
176 throw armnn::Exception(
177 "Mapping allocated memory from CustomMemoryAllocator failed, errcode: "
178 + std::to_string(error));
179 }
180 else if (source == MemorySource::DmaBufProtected)
181 {
182 const cl_import_properties_arm importProperties[] =
183 {
184 CL_IMPORT_TYPE_ARM,
185 CL_IMPORT_TYPE_DMA_BUF_ARM,
186 CL_IMPORT_TYPE_PROTECTED_ARM,
187 CL_TRUE,
188 0
David Monahane9b12302021-08-12 10:20:21 +0100189 };
190 cl_int error = CL_SUCCESS;
191 cl_mem buffer = clImportMemoryARM(arm_compute::CLKernelLibrary::get().context().get(),
192 CL_MEM_READ_WRITE,
193 importProperties,
194 memory,
195 roundedSize,
196 &error);
197 if (error == CL_SUCCESS)
198 {
199 m_AllocatedBufferMappings.insert(std::make_pair(static_cast<void *>(buffer), memory));
200 return buffer;
201 }
202 throw armnn::Exception(
203 "Mapping allocated memory from CustomMemoryAllocator failed, errcode: "
204 + std::to_string(error));
205 }
Jan Eilersc1c872f2021-07-22 13:17:04 +0100206 throw armnn::Exception(
207 "Attempting to allocate memory with unsupported MemorySource type in CustomAllocator");
208 }
209 std::shared_ptr<ICustomAllocator> m_CustomAllocator;
210 std::map<void*, void*> m_AllocatedBufferMappings;
211 };
212
213 class ClBackendCustomAllocatorMemoryRegion : public arm_compute::ICLMemoryRegion
214 {
215 public:
216 // We need to have a new version of ICLMemoryRegion which holds a hostMemPtr to allow for cpu copy access
David Monahane9b12302021-08-12 10:20:21 +0100217 ClBackendCustomAllocatorMemoryRegion(const cl::Buffer &buffer, void* hostMemPtr, armnn::MemorySource source)
Jan Eilersc1c872f2021-07-22 13:17:04 +0100218 : ICLMemoryRegion(buffer.getInfo<CL_MEM_SIZE>())
219 {
220 _mem = buffer;
221 m_HostMemPtr = hostMemPtr;
David Monahane9b12302021-08-12 10:20:21 +0100222 m_MemorySource = source;
Jan Eilersc1c872f2021-07-22 13:17:04 +0100223 }
224
225 // Inherited methods overridden :
226 void* ptr() override
227 {
228 return nullptr;
229 }
230
231 void* map(cl::CommandQueue &q, bool blocking) override
232 {
233 armnn::IgnoreUnused(q, blocking);
234 if (m_HostMemPtr == nullptr)
235 {
236 throw armnn::Exception("ClBackend: Attempting to map memory with an invalid host ptr");
237 }
David Monahane9b12302021-08-12 10:20:21 +0100238 if (_mapping != nullptr)
239 {
240 throw armnn::Exception("ClBackend: Attempting to map memory which has not yet been unmapped");
241 }
242 switch (m_MemorySource)
243 {
244 case armnn::MemorySource::Malloc:
245 _mapping = m_HostMemPtr;
246 return _mapping;
247 break;
248 case armnn::MemorySource::DmaBuf:
Francis Murtagh9db96e02021-08-13 16:15:09 +0100249 case armnn::MemorySource::DmaBufProtected:
David Monahane9b12302021-08-12 10:20:21 +0100250 // If the source is a Dmabuf then the memory ptr should be pointing to an integer value for the fd
251 _mapping = mmap(NULL, _size, PROT_WRITE, MAP_SHARED, *(reinterpret_cast<int*>(m_HostMemPtr)), 0);
252 return _mapping;
253 break;
254 default:
255 throw armnn::Exception("ClBackend: Attempting to map imported memory without a valid source");
256 break;
257 }
Jan Eilersc1c872f2021-07-22 13:17:04 +0100258 }
259
260 void unmap(cl::CommandQueue &q) override
261 {
262 armnn::IgnoreUnused(q);
David Monahane9b12302021-08-12 10:20:21 +0100263 switch (m_MemorySource)
264 {
265 case armnn::MemorySource::Malloc:
266 _mapping = nullptr;
267 break;
268 case armnn::MemorySource::DmaBuf:
Francis Murtagh9db96e02021-08-13 16:15:09 +0100269 case armnn::MemorySource::DmaBufProtected:
David Monahane9b12302021-08-12 10:20:21 +0100270 munmap(_mapping, _size);
271 _mapping = nullptr;
272 break;
273 default:
274 throw armnn::Exception("ClBackend: Attempting to unmap imported memory without a valid source");
275 break;
276 }
Jan Eilersc1c872f2021-07-22 13:17:04 +0100277 }
David Monahane9b12302021-08-12 10:20:21 +0100278 private:
Jan Eilersc1c872f2021-07-22 13:17:04 +0100279 void* m_HostMemPtr = nullptr;
David Monahane9b12302021-08-12 10:20:21 +0100280 armnn::MemorySource m_MemorySource;
Jan Eilersc1c872f2021-07-22 13:17:04 +0100281 };
282
283 std::shared_ptr<ClBackendCustomAllocatorWrapper> m_CustomAllocator;
284 bool m_UsingCustomAllocator = false;
arovir014424b0a2018-10-04 10:46:04 +0100285};
286
Matteo Martincighadddddb2019-01-24 14:06:23 +0000287} // namespace armnn