ArmNN
 21.08
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  else
163  {
164  throw MemoryImportException("NeonTensorHandle::Import is disabled");
165  }
166  }
167  else
168  {
169  throw MemoryImportException("NeonTensorHandle::Incorrect import flag");
170  }
171  return false;
172  }
173 
174 private:
175  // Only used for testing
176  void CopyOutTo(void* memory) const override
177  {
178  switch (this->GetDataType())
179  {
180  case arm_compute::DataType::F32:
181  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
182  static_cast<float*>(memory));
183  break;
184  case arm_compute::DataType::U8:
185  case arm_compute::DataType::QASYMM8:
186  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
187  static_cast<uint8_t*>(memory));
188  break;
189  case arm_compute::DataType::QSYMM8:
190  case arm_compute::DataType::QASYMM8_SIGNED:
191  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
192  static_cast<int8_t*>(memory));
193  break;
194  case arm_compute::DataType::BFLOAT16:
195  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
196  static_cast<armnn::BFloat16*>(memory));
197  break;
198  case arm_compute::DataType::F16:
199  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
200  static_cast<armnn::Half*>(memory));
201  break;
202  case arm_compute::DataType::S16:
203  case arm_compute::DataType::QSYMM16:
204  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
205  static_cast<int16_t*>(memory));
206  break;
207  case arm_compute::DataType::S32:
208  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
209  static_cast<int32_t*>(memory));
210  break;
211  default:
212  {
214  }
215  }
216  }
217 
218  // Only used for testing
219  void CopyInFrom(const void* memory) override
220  {
221  switch (this->GetDataType())
222  {
223  case arm_compute::DataType::F32:
224  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const float*>(memory),
225  this->GetTensor());
226  break;
227  case arm_compute::DataType::U8:
228  case arm_compute::DataType::QASYMM8:
229  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const uint8_t*>(memory),
230  this->GetTensor());
231  break;
232  case arm_compute::DataType::QSYMM8:
233  case arm_compute::DataType::QASYMM8_SIGNED:
234  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int8_t*>(memory),
235  this->GetTensor());
236  break;
237  case arm_compute::DataType::BFLOAT16:
238  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const armnn::BFloat16*>(memory),
239  this->GetTensor());
240  break;
241  case arm_compute::DataType::F16:
242  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const armnn::Half*>(memory),
243  this->GetTensor());
244  break;
245  case arm_compute::DataType::S16:
246  case arm_compute::DataType::QSYMM16:
247  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int16_t*>(memory),
248  this->GetTensor());
249  break;
250  case arm_compute::DataType::S32:
251  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int32_t*>(memory),
252  this->GetTensor());
253  break;
254  default:
255  {
257  }
258  }
259  }
260 
261  arm_compute::Tensor m_Tensor;
262  std::shared_ptr<arm_compute::MemoryGroup> m_MemoryGroup;
263  MemorySourceFlags m_ImportFlags;
264  bool m_Imported;
265  bool m_IsImportEnabled;
266 };
267 
269 {
270 public:
272  const arm_compute::TensorShape& shape,
273  const arm_compute::Coordinates& coords)
274  : m_Tensor(&parent->GetTensor(), shape, coords)
275  {
276  parentHandle = parent;
277  }
278 
279  arm_compute::ITensor& GetTensor() override { return m_Tensor; }
280  arm_compute::ITensor const& GetTensor() const override { return m_Tensor; }
281 
282  virtual void Allocate() override {}
283  virtual void Manage() override {}
284 
285  virtual ITensorHandle* GetParent() const override { return parentHandle; }
286 
287  virtual arm_compute::DataType GetDataType() const override
288  {
289  return m_Tensor.info()->data_type();
290  }
291 
292  virtual void SetMemoryGroup(const std::shared_ptr<arm_compute::IMemoryGroup>&) override {}
293 
294  virtual const void* Map(bool /* blocking = true */) const override
295  {
296  return static_cast<const void*>(m_Tensor.buffer() + m_Tensor.info()->offset_first_element_in_bytes());
297  }
298  virtual void Unmap() const override {}
299 
300  TensorShape GetStrides() const override
301  {
302  return armcomputetensorutils::GetStrides(m_Tensor.info()->strides_in_bytes());
303  }
304 
305  TensorShape GetShape() const override
306  {
307  return armcomputetensorutils::GetShape(m_Tensor.info()->tensor_shape());
308  }
309 
310 private:
311  // Only used for testing
312  void CopyOutTo(void* memory) const override
313  {
314  switch (this->GetDataType())
315  {
316  case arm_compute::DataType::F32:
317  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
318  static_cast<float*>(memory));
319  break;
320  case arm_compute::DataType::U8:
321  case arm_compute::DataType::QASYMM8:
322  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
323  static_cast<uint8_t*>(memory));
324  break;
325  case arm_compute::DataType::QSYMM8:
326  case arm_compute::DataType::QASYMM8_SIGNED:
327  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
328  static_cast<int8_t*>(memory));
329  break;
330  case arm_compute::DataType::S16:
331  case arm_compute::DataType::QSYMM16:
332  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
333  static_cast<int16_t*>(memory));
334  break;
335  case arm_compute::DataType::S32:
336  armcomputetensorutils::CopyArmComputeITensorData(this->GetTensor(),
337  static_cast<int32_t*>(memory));
338  break;
339  default:
340  {
342  }
343  }
344  }
345 
346  // Only used for testing
347  void CopyInFrom(const void* memory) override
348  {
349  switch (this->GetDataType())
350  {
351  case arm_compute::DataType::F32:
352  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const float*>(memory),
353  this->GetTensor());
354  break;
355  case arm_compute::DataType::U8:
356  case arm_compute::DataType::QASYMM8:
357  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const uint8_t*>(memory),
358  this->GetTensor());
359  break;
360  case arm_compute::DataType::QSYMM8:
361  case arm_compute::DataType::QASYMM8_SIGNED:
362  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int8_t*>(memory),
363  this->GetTensor());
364  break;
365  case arm_compute::DataType::S16:
366  case arm_compute::DataType::QSYMM16:
367  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int16_t*>(memory),
368  this->GetTensor());
369  break;
370  case arm_compute::DataType::S32:
371  armcomputetensorutils::CopyArmComputeITensorData(static_cast<const int32_t*>(memory),
372  this->GetTensor());
373  break;
374  default:
375  {
377  }
378  }
379  }
380 
381  arm_compute::SubTensor m_Tensor;
382  ITensorHandle* parentHandle = nullptr;
383 };
384 
385 } // 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:53
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:198
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.