blob: 249b915ce12b27c6153bd78392c55b2713859b47 [file] [log] [blame]
//
// Copyright © 2022-2023 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//
#include "GpuFsaTensorHandle.hpp"
namespace armnn
{
GpuFsaTensorHandle::GpuFsaTensorHandle(const TensorInfo& tensorInfo,
std::shared_ptr<GpuFsaMemoryManager>& memoryManager)
: m_TensorInfo(tensorInfo)
, m_MemoryManager(memoryManager)
, m_Pool(nullptr)
, m_UnmanagedMemory(nullptr)
, m_ImportFlags(static_cast<MemorySourceFlags>(MemorySource::Undefined))
, m_Imported(false)
, m_IsImportEnabled(false)
{}
GpuFsaTensorHandle::GpuFsaTensorHandle(const TensorInfo& tensorInfo,
MemorySourceFlags importFlags)
: m_TensorInfo(tensorInfo)
, m_Pool(nullptr)
, m_UnmanagedMemory(nullptr)
, m_ImportFlags(importFlags)
, m_Imported(false)
, m_IsImportEnabled(true)
{}
GpuFsaTensorHandle::~GpuFsaTensorHandle()
{
if (!m_Pool)
{
// unmanaged
if (!m_Imported)
{
::operator delete(m_UnmanagedMemory);
}
}
}
void GpuFsaTensorHandle::Manage()
{
if (!m_IsImportEnabled)
{
if (m_Pool == nullptr)
{
throw MemoryValidationException("GpuFsaTensorHandle::Manage() called twice");
}
if (m_UnmanagedMemory == nullptr)
{
throw MemoryValidationException("GpuFsaTensorHandle::Manage() called after Allocate()");
}
m_Pool = m_MemoryManager->Manage(m_TensorInfo.GetNumBytes());
}
}
void GpuFsaTensorHandle::Allocate()
{
// If import is enabled, do not allocate the tensor
if (!m_IsImportEnabled)
{
if (!m_UnmanagedMemory)
{
if (!m_Pool)
{
// unmanaged
m_UnmanagedMemory = ::operator new(m_TensorInfo.GetNumBytes());
}
else
{
m_MemoryManager->Allocate(m_Pool);
}
}
else
{
throw InvalidArgumentException("GpuFsaTensorHandle::Allocate Trying to allocate a GpuFsaTensorHandle"
"that already has allocated memory.");
}
}
}
const void* GpuFsaTensorHandle::Map(bool /*unused*/) const
{
return GetPointer();
}
void* GpuFsaTensorHandle::GetPointer() const
{
if (m_UnmanagedMemory)
{
return m_UnmanagedMemory;
}
else if (m_Pool)
{
return m_MemoryManager->GetPointer(m_Pool);
}
else
{
throw NullPointerException("GpuFsaTensorHandle::GetPointer called on unmanaged, unallocated tensor handle");
}
}
void GpuFsaTensorHandle::CopyOutTo(void* dest) const
{
const void *src = GetPointer();
if (src == nullptr)
{
throw MemoryValidationException("GpuFsaTensorhandle: CopyOutTo: Invalid memory src pointer");
}
memcpy(dest, src, m_TensorInfo.GetNumBytes());
}
void GpuFsaTensorHandle::CopyInFrom(const void* src)
{
void *dest = GetPointer();
if (dest == nullptr)
{
throw MemoryValidationException("GpuFsaTensorhandle: CopyInFrom: Invalid memory dest pointer");
}
memcpy(dest, src, m_TensorInfo.GetNumBytes());
}
bool GpuFsaTensorHandle::Import(void* memory, MemorySource source)
{
if (m_ImportFlags & static_cast<MemorySourceFlags>(source))
{
if (m_IsImportEnabled && source == MemorySource::Malloc)
{
// Check memory alignment
if(!CanBeImported(memory, source))
{
if (m_Imported)
{
m_Imported = false;
m_UnmanagedMemory = nullptr;
}
return false;
}
// m_UnmanagedMemory not yet allocated.
if (!m_Imported && !m_UnmanagedMemory)
{
m_UnmanagedMemory = memory;
m_Imported = true;
return true;
}
// m_UnmanagedMemory initially allocated with Allocate().
if (!m_Imported && m_UnmanagedMemory)
{
return false;
}
// m_UnmanagedMemory previously imported.
if (m_Imported)
{
m_UnmanagedMemory = memory;
return true;
}
}
}
return false;
}
bool GpuFsaTensorHandle::CanBeImported(void* memory, MemorySource source)
{
if (m_ImportFlags & static_cast<MemorySourceFlags>(source))
{
if (m_IsImportEnabled && source == MemorySource::Malloc)
{
uintptr_t alignment = GetDataTypeSize(m_TensorInfo.GetDataType());
if (reinterpret_cast<uintptr_t>(memory) % alignment)
{
return false;
}
return true;
}
}
return false;
}
}