ArmNN
 21.11
NeonTensorHandle.hpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #pragma once
6 
7 #include <BFloat16.hpp>
8 #include <Half.hpp>
9 
10 #include <armnn/utility/Assert.hpp>
11 
15 
16 #include <arm_compute/runtime/MemoryGroup.h>
17 #include <arm_compute/runtime/IMemoryGroup.h>
18 #include <arm_compute/runtime/Tensor.h>
19 #include <arm_compute/runtime/SubTensor.h>
20 #include <arm_compute/core/TensorShape.h>
21 #include <arm_compute/core/Coordinates.h>
22 
23 namespace armnn
24 {
25 
27 {
28 public:
29  NeonTensorHandle(const TensorInfo& tensorInfo)
30  : m_ImportFlags(static_cast<MemorySourceFlags>(MemorySource::Malloc)),
31  m_Imported(false),
32  m_IsImportEnabled(false),
33  m_TypeAlignment(GetDataTypeSize(tensorInfo.GetDataType()))
34  {
35  armnn::armcomputetensorutils::BuildArmComputeTensor(m_Tensor, tensorInfo);
36  }
37 
38  NeonTensorHandle(const TensorInfo& tensorInfo,
39  DataLayout dataLayout,
40  MemorySourceFlags importFlags = static_cast<MemorySourceFlags>(MemorySource::Malloc))
41  : m_ImportFlags(importFlags),
42  m_Imported(false),
43  m_IsImportEnabled(false),
44  m_TypeAlignment(GetDataTypeSize(tensorInfo.GetDataType()))
45 
46 
47  {
48  armnn::armcomputetensorutils::BuildArmComputeTensor(m_Tensor, tensorInfo, dataLayout);
49  }
50 
51  arm_compute::ITensor& GetTensor() override { return m_Tensor; }
52  arm_compute::ITensor const& GetTensor() const override { return m_Tensor; }
53 
54  virtual void Allocate() override
55  {
56  // If we have enabled Importing, don't Allocate the tensor
57  if (!m_IsImportEnabled)
58  {
59  armnn::armcomputetensorutils::InitialiseArmComputeTensorEmpty(m_Tensor);
60  }
61  };
62 
63  virtual void Manage() override
64  {
65  // If we have enabled Importing, don't manage the tensor
66  if (!m_IsImportEnabled)
67  {
68  ARMNN_ASSERT(m_MemoryGroup != nullptr);
69  m_MemoryGroup->manage(&m_Tensor);
70  }
71  }
72 
73  virtual ITensorHandle* GetParent() const override { return nullptr; }
74 
75  virtual arm_compute::DataType GetDataType() const override
76  {
77  return m_Tensor.info()->data_type();
78  }
79 
80  virtual void SetMemoryGroup(const std::shared_ptr<arm_compute::IMemoryGroup>& memoryGroup) override
81  {
82  m_MemoryGroup = PolymorphicPointerDowncast<arm_compute::MemoryGroup>(memoryGroup);
83  }
84 
85  virtual const void* Map(bool /* blocking = true */) const override
86  {
87  return static_cast<const void*>(m_Tensor.buffer() + m_Tensor.info()->offset_first_element_in_bytes());
88  }
89 
90  virtual void Unmap() const override {}
91 
92  TensorShape GetStrides() const override
93  {
94  return armcomputetensorutils::GetStrides(m_Tensor.info()->strides_in_bytes());
95  }
96 
97  TensorShape GetShape() const override
98  {
99  return armcomputetensorutils::GetShape(m_Tensor.info()->tensor_shape());
100  }
101 
103  {
104  m_ImportFlags = importFlags;
105  }
106 
108  {
109  return m_ImportFlags;
110  }
111 
112  void SetImportEnabledFlag(bool importEnabledFlag)
113  {
114  m_IsImportEnabled = importEnabledFlag;
115  }
116 
117  virtual bool Import(void* memory, MemorySource source) override
118  {
119  if (m_ImportFlags & static_cast<MemorySourceFlags>(source))
120  {
121  if (source == MemorySource::Malloc && m_IsImportEnabled)
122  {
123  if (reinterpret_cast<uintptr_t>(memory) % m_TypeAlignment)
124  {
125  throw MemoryImportException("NeonTensorHandle::Import Attempting to import unaligned memory");
126  }
127 
128  // m_Tensor not yet Allocated
129  if (!m_Imported && !m_Tensor.buffer())
130  {
131  arm_compute::Status status = m_Tensor.allocator()->import_memory(memory);
132  // Use the overloaded bool operator of Status to check if it worked, if not throw an exception
133  // with the Status error message
134  m_Imported = bool(status);
135  if (!m_Imported)
136  {
137  throw MemoryImportException(status.error_description());
138  }
139  return m_Imported;
140  }
141 
142  // m_Tensor.buffer() initially allocated with Allocate().
143  if (!m_Imported && m_Tensor.buffer())
144  {
145  throw MemoryImportException(
146  "NeonTensorHandle::Import Attempting to import on an already allocated tensor");
147  }
148 
149  // m_Tensor.buffer() previously imported.
150  if (m_Imported)
151  {
152  arm_compute::Status status = m_Tensor.allocator()->import_memory(memory);
153  // Use the overloaded bool operator of Status to check if it worked, if not throw an exception
154  // with the Status error message
155  m_Imported = bool(status);
156  if (!m_Imported)
157  {
158  throw MemoryImportException(status.error_description());
159  }
160  return m_Imported;
161  }
162  }
163  else
164  {
165  throw MemoryImportException("NeonTensorHandle::Import is disabled");
166  }
167  }
168  else
169  {
170  throw MemoryImportException("NeonTensorHandle::Incorrect import flag");
171  }
172  return false;
173  }
174 
175 private:
176  // Only used for testing
177  void CopyOutTo(void* memory) const override
178  {
179  switch (this->GetDataType())
180  {
181  case arm_compute::DataType::F32:
182  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
183  static_cast<float*>(memory));
184  break;
185  case arm_compute::DataType::U8:
186  case arm_compute::DataType::QASYMM8:
187  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
188  static_cast<uint8_t*>(memory));
189  break;
190  case arm_compute::DataType::QSYMM8:
191  case arm_compute::DataType::QASYMM8_SIGNED:
192  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
193  static_cast<int8_t*>(memory));
194  break;
195  case arm_compute::DataType::BFLOAT16:
196  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
197  static_cast<armnn::BFloat16*>(memory));
198  break;
199  case arm_compute::DataType::F16:
200  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
201  static_cast<armnn::Half*>(memory));
202  break;
203  case arm_compute::DataType::S16:
204  case arm_compute::DataType::QSYMM16:
205  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
206  static_cast<int16_t*>(memory));
207  break;
208  case arm_compute::DataType::S32:
209  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
210  static_cast<int32_t*>(memory));
211  break;
212  default:
213  {
215  }
216  }
217  }
218 
219  // Only used for testing
220  void CopyInFrom(const void* memory) override
221  {
222  switch (this->GetDataType())
223  {
224  case arm_compute::DataType::F32:
225  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const float*>(memory),
226  this->GetTensor());
227  break;
228  case arm_compute::DataType::U8:
229  case arm_compute::DataType::QASYMM8:
230  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const uint8_t*>(memory),
231  this->GetTensor());
232  break;
233  case arm_compute::DataType::QSYMM8:
234  case arm_compute::DataType::QASYMM8_SIGNED:
235  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int8_t*>(memory),
236  this->GetTensor());
237  break;
238  case arm_compute::DataType::BFLOAT16:
239  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const armnn::BFloat16*>(memory),
240  this->GetTensor());
241  break;
242  case arm_compute::DataType::F16:
243  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const armnn::Half*>(memory),
244  this->GetTensor());
245  break;
246  case arm_compute::DataType::S16:
247  case arm_compute::DataType::QSYMM16:
248  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int16_t*>(memory),
249  this->GetTensor());
250  break;
251  case arm_compute::DataType::S32:
252  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int32_t*>(memory),
253  this->GetTensor());
254  break;
255  default:
256  {
258  }
259  }
260  }
261 
262  arm_compute::Tensor m_Tensor;
263  std::shared_ptr<arm_compute::MemoryGroup> m_MemoryGroup;
264  MemorySourceFlags m_ImportFlags;
265  bool m_Imported;
266  bool m_IsImportEnabled;
267  const uintptr_t m_TypeAlignment;
268 };
269 
271 {
272 public:
274  const arm_compute::TensorShape& shape,
275  const arm_compute::Coordinates& coords)
276  : m_Tensor(&parent->GetTensor(), shape, coords)
277  {
278  parentHandle = parent;
279  }
280 
281  arm_compute::ITensor& GetTensor() override { return m_Tensor; }
282  arm_compute::ITensor const& GetTensor() const override { return m_Tensor; }
283 
284  virtual void Allocate() override {}
285  virtual void Manage() override {}
286 
287  virtual ITensorHandle* GetParent() const override { return parentHandle; }
288 
289  virtual arm_compute::DataType GetDataType() const override
290  {
291  return m_Tensor.info()->data_type();
292  }
293 
294  virtual void SetMemoryGroup(const std::shared_ptr<arm_compute::IMemoryGroup>&) override {}
295 
296  virtual const void* Map(bool /* blocking = true */) const override
297  {
298  return static_cast<const void*>(m_Tensor.buffer() + m_Tensor.info()->offset_first_element_in_bytes());
299  }
300  virtual void Unmap() const override {}
301 
302  TensorShape GetStrides() const override
303  {
304  return armcomputetensorutils::GetStrides(m_Tensor.info()->strides_in_bytes());
305  }
306 
307  TensorShape GetShape() const override
308  {
309  return armcomputetensorutils::GetShape(m_Tensor.info()->tensor_shape());
310  }
311 
312 private:
313  // Only used for testing
314  void CopyOutTo(void* memory) const override
315  {
316  switch (this->GetDataType())
317  {
318  case arm_compute::DataType::F32:
319  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
320  static_cast<float*>(memory));
321  break;
322  case arm_compute::DataType::U8:
323  case arm_compute::DataType::QASYMM8:
324  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
325  static_cast<uint8_t*>(memory));
326  break;
327  case arm_compute::DataType::QSYMM8:
328  case arm_compute::DataType::QASYMM8_SIGNED:
329  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
330  static_cast<int8_t*>(memory));
331  break;
332  case arm_compute::DataType::S16:
333  case arm_compute::DataType::QSYMM16:
334  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
335  static_cast<int16_t*>(memory));
336  break;
337  case arm_compute::DataType::S32:
338  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
339  static_cast<int32_t*>(memory));
340  break;
341  default:
342  {
344  }
345  }
346  }
347 
348  // Only used for testing
349  void CopyInFrom(const void* memory) override
350  {
351  switch (this->GetDataType())
352  {
353  case arm_compute::DataType::F32:
354  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const float*>(memory),
355  this->GetTensor());
356  break;
357  case arm_compute::DataType::U8:
358  case arm_compute::DataType::QASYMM8:
359  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const uint8_t*>(memory),
360  this->GetTensor());
361  break;
362  case arm_compute::DataType::QSYMM8:
363  case arm_compute::DataType::QASYMM8_SIGNED:
364  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int8_t*>(memory),
365  this->GetTensor());
366  break;
367  case arm_compute::DataType::S16:
368  case arm_compute::DataType::QSYMM16:
369  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int16_t*>(memory),
370  this->GetTensor());
371  break;
372  case arm_compute::DataType::S32:
373  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int32_t*>(memory),
374  this->GetTensor());
375  break;
376  default:
377  {
379  }
380  }
381  }
382 
383  arm_compute::SubTensor m_Tensor;
384  ITensorHandle* parentHandle = nullptr;
385 };
386 
387 } // namespace armnn
TensorShape GetShape() const override
Get the number of elements for each dimension ordered from slowest iterating dimension to fastest ite...
TensorShape GetStrides() const override
Get the strides for each dimension ordered from largest to smallest where the smallest value is the s...
virtual void Allocate() override
Indicate to the memory manager that this resource is no longer active.
virtual void SetMemoryGroup(const std::shared_ptr< arm_compute::IMemoryGroup > &) override
DataLayout
Definition: Types.hpp:49
virtual arm_compute::DataType GetDataType() const override
virtual void SetMemoryGroup(const std::shared_ptr< arm_compute::IMemoryGroup > &memoryGroup) override
virtual arm_compute::DataType GetDataType() const override
std::array< unsigned int, MaxNumOfTensorDimensions > Coordinates
virtual void Manage() override
Indicate to the memory manager that this resource is active.
virtual void Unmap() const override
Unmap the tensor data.
arm_compute::ITensor const & GetTensor() const override
virtual ITensorHandle * GetParent() const override
Get the parent tensor if this is a subtensor.
unsigned int MemorySourceFlags
arm_compute::ITensor const & GetTensor() const override
virtual void Unmap() const override
Unmap the tensor data.
Copyright (c) 2021 ARM Limited and Contributors.
virtual bool Import(void *memory, MemorySource source) override
Import externally allocated memory.
DataType
Definition: Types.hpp:35
TensorShape GetShape() const override
Get the number of elements for each dimension ordered from slowest iterating dimension to fastest ite...
NeonSubTensorHandle(IAclTensorHandle *parent, const arm_compute::TensorShape &shape, const arm_compute::Coordinates &coords)
Status
enumeration
Definition: Types.hpp:29
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
arm_compute::ITensor & GetTensor() override
MemorySourceFlags GetImportFlags() const override
Get flags describing supported import sources.
TensorShape GetStrides() const override
Get the strides for each dimension ordered from largest to smallest where the smallest value is the s...
virtual const void * Map(bool) const override
Map the tensor data for access.
NeonTensorHandle(const TensorInfo &tensorInfo, DataLayout dataLayout, MemorySourceFlags importFlags=static_cast< MemorySourceFlags >(MemorySource::Malloc))
virtual ITensorHandle * GetParent() const override
Get the parent tensor if this is a subtensor.
MemorySource
Define the Memory Source to reduce copies.
Definition: Types.hpp:217
virtual void Allocate() override
Indicate to the memory manager that this resource is no longer active.
NeonTensorHandle(const TensorInfo &tensorInfo)
virtual const void * Map(bool) const override
Map the tensor data for access.
void SetImportFlags(MemorySourceFlags importFlags)
arm_compute::ITensor & GetTensor() override
void SetImportEnabledFlag(bool importEnabledFlag)
constexpr unsigned int GetDataTypeSize(DataType dataType)
Definition: TypesUtils.hpp:151
virtual void Manage() override
Indicate to the memory manager that this resource is active.