ArmNN
 20.05
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  {
34  armnn::armcomputetensorutils::BuildArmComputeTensor(m_Tensor, tensorInfo);
35  }
36 
37  NeonTensorHandle(const TensorInfo& tensorInfo,
38  DataLayout dataLayout,
39  MemorySourceFlags importFlags = static_cast<MemorySourceFlags>(MemorySource::Malloc))
40  : m_ImportFlags(importFlags),
41  m_Imported(false),
42  m_IsImportEnabled(false)
43 
44  {
45  armnn::armcomputetensorutils::BuildArmComputeTensor(m_Tensor, tensorInfo, dataLayout);
46  }
47 
48  arm_compute::ITensor& GetTensor() override { return m_Tensor; }
49  arm_compute::ITensor const& GetTensor() const override { return m_Tensor; }
50 
51  virtual void Allocate() override
52  {
53  // If we have enabled Importing, don't Allocate the tensor
54  if (!m_IsImportEnabled)
55  {
56  armnn::armcomputetensorutils::InitialiseArmComputeTensorEmpty(m_Tensor);
57  }
58  };
59 
60  virtual void Manage() override
61  {
62  // If we have enabled Importing, don't manage the tensor
63  if (!m_IsImportEnabled)
64  {
65  ARMNN_ASSERT(m_MemoryGroup != nullptr);
66  m_MemoryGroup->manage(&m_Tensor);
67  }
68  }
69 
70  virtual ITensorHandle* GetParent() const override { return nullptr; }
71 
72  virtual arm_compute::DataType GetDataType() const override
73  {
74  return m_Tensor.info()->data_type();
75  }
76 
77  virtual void SetMemoryGroup(const std::shared_ptr<arm_compute::IMemoryGroup>& memoryGroup) override
78  {
79  m_MemoryGroup = PolymorphicPointerDowncast<arm_compute::MemoryGroup>(memoryGroup);
80  }
81 
82  virtual const void* Map(bool /* blocking = true */) const override
83  {
84  return static_cast<const void*>(m_Tensor.buffer() + m_Tensor.info()->offset_first_element_in_bytes());
85  }
86 
87  virtual void Unmap() const override {}
88 
89  TensorShape GetStrides() const override
90  {
91  return armcomputetensorutils::GetStrides(m_Tensor.info()->strides_in_bytes());
92  }
93 
94  TensorShape GetShape() const override
95  {
96  return armcomputetensorutils::GetShape(m_Tensor.info()->tensor_shape());
97  }
98 
100  {
101  m_ImportFlags = importFlags;
102  }
103 
105  {
106  return m_ImportFlags;
107  }
108 
109  void SetImportEnabledFlag(bool importEnabledFlag)
110  {
111  m_IsImportEnabled = importEnabledFlag;
112  }
113 
114  virtual bool Import(void* memory, MemorySource source) override
115  {
116  if (m_ImportFlags & static_cast<MemorySourceFlags>(source))
117  {
118  if (source == MemorySource::Malloc && m_IsImportEnabled)
119  {
120  // Checks the 16 byte memory alignment
121  constexpr uintptr_t alignment = sizeof(size_t);
122  if (reinterpret_cast<uintptr_t>(memory) % alignment)
123  {
124  throw MemoryImportException("NeonTensorHandle::Import Attempting to import unaligned memory");
125  }
126 
127  // m_Tensor not yet Allocated
128  if (!m_Imported && !m_Tensor.buffer())
129  {
130  arm_compute::Status status = m_Tensor.allocator()->import_memory(memory);
131  // Use the overloaded bool operator of Status to check if it worked, if not throw an exception
132  // with the Status error message
133  m_Imported = bool(status);
134  if (!m_Imported)
135  {
136  throw MemoryImportException(status.error_description());
137  }
138  return m_Imported;
139  }
140 
141  // m_Tensor.buffer() initially allocated with Allocate().
142  if (!m_Imported && m_Tensor.buffer())
143  {
144  throw MemoryImportException(
145  "NeonTensorHandle::Import Attempting to import on an already allocated tensor");
146  }
147 
148  // m_Tensor.buffer() previously imported.
149  if (m_Imported)
150  {
151  arm_compute::Status status = m_Tensor.allocator()->import_memory(memory);
152  // Use the overloaded bool operator of Status to check if it worked, if not throw an exception
153  // with the Status error message
154  m_Imported = bool(status);
155  if (!m_Imported)
156  {
157  throw MemoryImportException(status.error_description());
158  }
159  return m_Imported;
160  }
161  }
162  }
163  return false;
164  }
165 
166 private:
167  // Only used for testing
168  void CopyOutTo(void* memory) const override
169  {
170  switch (this->GetDataType())
171  {
172  case arm_compute::DataType::F32:
173  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
174  static_cast<float*>(memory));
175  break;
176  case arm_compute::DataType::U8:
177  case arm_compute::DataType::QASYMM8:
178  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
179  static_cast<uint8_t*>(memory));
180  break;
181  case arm_compute::DataType::QASYMM8_SIGNED:
182  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
183  static_cast<int8_t*>(memory));
184  break;
185  case arm_compute::DataType::BFLOAT16:
186  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
187  static_cast<armnn::BFloat16*>(memory));
188  break;
189  case arm_compute::DataType::F16:
190  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
191  static_cast<armnn::Half*>(memory));
192  break;
193  case arm_compute::DataType::S16:
194  case arm_compute::DataType::QSYMM16:
195  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
196  static_cast<int16_t*>(memory));
197  break;
198  case arm_compute::DataType::S32:
199  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
200  static_cast<int32_t*>(memory));
201  break;
202  default:
203  {
205  }
206  }
207  }
208 
209  // Only used for testing
210  void CopyInFrom(const void* memory) override
211  {
212  switch (this->GetDataType())
213  {
214  case arm_compute::DataType::F32:
215  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const float*>(memory),
216  this->GetTensor());
217  break;
218  case arm_compute::DataType::U8:
219  case arm_compute::DataType::QASYMM8:
220  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const uint8_t*>(memory),
221  this->GetTensor());
222  break;
223  case arm_compute::DataType::QASYMM8_SIGNED:
224  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int8_t*>(memory),
225  this->GetTensor());
226  break;
227  case arm_compute::DataType::BFLOAT16:
228  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const armnn::BFloat16*>(memory),
229  this->GetTensor());
230  break;
231  case arm_compute::DataType::F16:
232  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const armnn::Half*>(memory),
233  this->GetTensor());
234  break;
235  case arm_compute::DataType::S16:
236  case arm_compute::DataType::QSYMM16:
237  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int16_t*>(memory),
238  this->GetTensor());
239  break;
240  case arm_compute::DataType::S32:
241  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int32_t*>(memory),
242  this->GetTensor());
243  break;
244  default:
245  {
247  }
248  }
249  }
250 
251  arm_compute::Tensor m_Tensor;
252  std::shared_ptr<arm_compute::MemoryGroup> m_MemoryGroup;
253  MemorySourceFlags m_ImportFlags;
254  bool m_Imported;
255  bool m_IsImportEnabled;
256 };
257 
259 {
260 public:
262  const arm_compute::TensorShape& shape,
263  const arm_compute::Coordinates& coords)
264  : m_Tensor(&parent->GetTensor(), shape, coords)
265  {
266  parentHandle = parent;
267  }
268 
269  arm_compute::ITensor& GetTensor() override { return m_Tensor; }
270  arm_compute::ITensor const& GetTensor() const override { return m_Tensor; }
271 
272  virtual void Allocate() override {}
273  virtual void Manage() override {}
274 
275  virtual ITensorHandle* GetParent() const override { return parentHandle; }
276 
277  virtual arm_compute::DataType GetDataType() const override
278  {
279  return m_Tensor.info()->data_type();
280  }
281 
282  virtual void SetMemoryGroup(const std::shared_ptr<arm_compute::IMemoryGroup>&) override {}
283 
284  virtual const void* Map(bool /* blocking = true */) const override
285  {
286  return static_cast<const void*>(m_Tensor.buffer() + m_Tensor.info()->offset_first_element_in_bytes());
287  }
288  virtual void Unmap() const override {}
289 
290  TensorShape GetStrides() const override
291  {
292  return armcomputetensorutils::GetStrides(m_Tensor.info()->strides_in_bytes());
293  }
294 
295  TensorShape GetShape() const override
296  {
297  return armcomputetensorutils::GetShape(m_Tensor.info()->tensor_shape());
298  }
299 
300 private:
301  // Only used for testing
302  void CopyOutTo(void* memory) const override
303  {
304  switch (this->GetDataType())
305  {
306  case arm_compute::DataType::F32:
307  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
308  static_cast<float*>(memory));
309  break;
310  case arm_compute::DataType::U8:
311  case arm_compute::DataType::QASYMM8:
312  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
313  static_cast<uint8_t*>(memory));
314  break;
315  case arm_compute::DataType::QASYMM8_SIGNED:
316  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
317  static_cast<int8_t*>(memory));
318  break;
319  case arm_compute::DataType::S16:
320  case arm_compute::DataType::QSYMM16:
321  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
322  static_cast<int16_t*>(memory));
323  break;
324  case arm_compute::DataType::S32:
325  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
326  static_cast<int32_t*>(memory));
327  break;
328  default:
329  {
331  }
332  }
333  }
334 
335  // Only used for testing
336  void CopyInFrom(const void* memory) override
337  {
338  switch (this->GetDataType())
339  {
340  case arm_compute::DataType::F32:
341  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const float*>(memory),
342  this->GetTensor());
343  break;
344  case arm_compute::DataType::U8:
345  case arm_compute::DataType::QASYMM8:
346  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const uint8_t*>(memory),
347  this->GetTensor());
348  break;
349  case arm_compute::DataType::QASYMM8_SIGNED:
350  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int8_t*>(memory),
351  this->GetTensor());
352  break;
353  case arm_compute::DataType::S16:
354  case arm_compute::DataType::QSYMM16:
355  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int16_t*>(memory),
356  this->GetTensor());
357  break;
358  case arm_compute::DataType::S32:
359  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int32_t*>(memory),
360  this->GetTensor());
361  break;
362  default:
363  {
365  }
366  }
367  }
368 
369  arm_compute::SubTensor m_Tensor;
370  ITensorHandle* parentHandle = nullptr;
371 };
372 
373 } // 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
DataLayout::NHWC false
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) 2020 ARM Limited.
virtual bool Import(void *memory, MemorySource source) override
Import externally allocated memory.
DataType
Definition: Types.hpp:32
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:26
#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.
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)
virtual void Manage() override
Indicate to the memory manager that this resource is active.