| // |
| // Copyright © 2019-2023 Arm Ltd. All rights reserved. |
| // SPDX-License-Identifier: MIT |
| // |
| |
| #include "RefTensorHandle.hpp" |
| |
| namespace armnn |
| { |
| |
| RefTensorHandle::RefTensorHandle(const TensorInfo& tensorInfo, std::shared_ptr<RefMemoryManager>& memoryManager): |
| m_TensorInfo(tensorInfo), |
| m_MemoryManager(memoryManager), |
| m_Pool(nullptr), |
| m_UnmanagedMemory(nullptr), |
| m_ImportedMemory(nullptr), |
| m_Decorated() |
| { |
| } |
| |
| RefTensorHandle::RefTensorHandle(const TensorInfo& tensorInfo) |
| : m_TensorInfo(tensorInfo), |
| m_Pool(nullptr), |
| m_UnmanagedMemory(nullptr), |
| m_ImportedMemory(nullptr), |
| m_Decorated() |
| { |
| } |
| |
| RefTensorHandle::RefTensorHandle(const TensorInfo& tensorInfo, const RefTensorHandle& parent) |
| : m_TensorInfo(tensorInfo), |
| m_MemoryManager(parent.m_MemoryManager), |
| m_Pool(parent.m_Pool), |
| m_UnmanagedMemory(parent.m_UnmanagedMemory), |
| m_ImportedMemory(parent.m_ImportedMemory), |
| m_Decorated() |
| { |
| } |
| |
| RefTensorHandle::~RefTensorHandle() |
| { |
| ::operator delete(m_UnmanagedMemory); |
| } |
| |
| void RefTensorHandle::Manage() |
| { |
| ARMNN_ASSERT_MSG(!m_Pool, "RefTensorHandle::Manage() called twice"); |
| ARMNN_ASSERT_MSG(!m_UnmanagedMemory, "RefTensorHandle::Manage() called after Allocate()"); |
| |
| if (m_MemoryManager) |
| { |
| m_Pool = m_MemoryManager->Manage(m_TensorInfo.GetNumBytes()); |
| } |
| } |
| |
| void RefTensorHandle::Allocate() |
| { |
| if (!m_UnmanagedMemory) |
| { |
| if (!m_Pool) |
| { |
| // unmanaged |
| m_UnmanagedMemory = ::operator new(m_TensorInfo.GetNumBytes()); |
| } |
| else |
| { |
| m_MemoryManager->Allocate(m_Pool); |
| } |
| } |
| else |
| { |
| throw InvalidArgumentException("RefTensorHandle::Allocate Trying to allocate a RefTensorHandle" |
| "that already has allocated memory."); |
| } |
| } |
| |
| const void* RefTensorHandle::Map(bool /*unused*/) const |
| { |
| return GetPointer(); |
| } |
| |
| void* RefTensorHandle::GetPointer() const |
| { |
| if (m_ImportedMemory) |
| { |
| return m_ImportedMemory; |
| } |
| else if (m_UnmanagedMemory) |
| { |
| return m_UnmanagedMemory; |
| } |
| else if (m_Pool) |
| { |
| return m_MemoryManager->GetPointer(m_Pool); |
| } |
| else |
| { |
| throw NullPointerException("RefTensorHandle::GetPointer called on unmanaged, unallocated tensor handle"); |
| } |
| } |
| |
| void RefTensorHandle::CopyOutTo(void* dest) const |
| { |
| const void* src = GetPointer(); |
| if (src == nullptr) |
| { |
| throw NullPointerException("TensorHandle::CopyOutTo called with a null src pointer"); |
| } |
| if (dest == nullptr) |
| { |
| throw NullPointerException("TensorHandle::CopyOutTo called with a null dest pointer"); |
| } |
| memcpy(dest, src, GetTensorInfo().GetNumBytes()); |
| } |
| |
| void RefTensorHandle::CopyInFrom(const void* src) |
| { |
| void* dest = GetPointer(); |
| if (dest == nullptr) |
| { |
| throw NullPointerException("RefTensorHandle::CopyInFrom called with a null dest pointer"); |
| } |
| if (src == nullptr) |
| { |
| throw NullPointerException("RefTensorHandle::CopyInFrom called with a null src pointer"); |
| } |
| memcpy(dest, src, GetTensorInfo().GetNumBytes()); |
| } |
| |
| MemorySourceFlags RefTensorHandle::GetImportFlags() const |
| { |
| return static_cast<MemorySourceFlags>(MemorySource::Malloc); |
| } |
| |
| bool RefTensorHandle::Import(void* memory, MemorySource source) |
| { |
| if (source == MemorySource::Malloc) |
| { |
| // Check memory alignment |
| if(!CanBeImported(memory, source)) |
| { |
| m_ImportedMemory = nullptr; |
| return false; |
| } |
| |
| m_ImportedMemory = memory; |
| return true; |
| } |
| |
| return false; |
| } |
| |
| bool RefTensorHandle::CanBeImported(void *memory, MemorySource source) |
| { |
| if (source == MemorySource::Malloc) |
| { |
| uintptr_t alignment = GetDataTypeSize(m_TensorInfo.GetDataType()); |
| if (reinterpret_cast<uintptr_t>(memory) % alignment) |
| { |
| return false; |
| } |
| return true; |
| } |
| return false; |
| } |
| |
| std::shared_ptr<ITensorHandle> RefTensorHandle::DecorateTensorHandle(const TensorInfo& tensorInfo) |
| { |
| auto decorated = std::make_shared<RefTensorHandleDecorator>(tensorInfo, *this); |
| m_Decorated.emplace_back(decorated); |
| return decorated; |
| } |
| |
| RefTensorHandleDecorator::RefTensorHandleDecorator(const TensorInfo& tensorInfo, const RefTensorHandle& parent) |
| : RefTensorHandle(tensorInfo) |
| , m_TensorInfo(tensorInfo) |
| , m_Parent(parent) |
| { |
| } |
| |
| void RefTensorHandleDecorator::Manage() |
| { |
| } |
| |
| void RefTensorHandleDecorator::Allocate() |
| { |
| } |
| |
| const void* RefTensorHandleDecorator::Map(bool unused) const |
| { |
| return m_Parent.Map(unused); |
| } |
| |
| MemorySourceFlags RefTensorHandleDecorator::GetImportFlags() const |
| { |
| return static_cast<MemorySourceFlags>(MemorySource::Malloc); |
| } |
| |
| bool RefTensorHandleDecorator::Import(void*, MemorySource ) |
| { |
| return false; |
| } |
| |
| bool RefTensorHandleDecorator::CanBeImported(void* , MemorySource) |
| { |
| return false; |
| } |
| |
| std::shared_ptr<ITensorHandle> RefTensorHandleDecorator::DecorateTensorHandle(const TensorInfo&) |
| { |
| return nullptr; |
| } |
| |
| |
| } |