aboutsummaryrefslogtreecommitdiff
path: root/src/dynamic/sample
diff options
context:
space:
mode:
Diffstat (limited to 'src/dynamic/sample')
-rw-r--r--src/dynamic/sample/CMakeLists.txt34
-rw-r--r--src/dynamic/sample/SampleDynamicAdditionWorkload.cpp54
-rw-r--r--src/dynamic/sample/SampleDynamicAdditionWorkload.hpp21
-rw-r--r--src/dynamic/sample/SampleDynamicBackend.cpp91
-rw-r--r--src/dynamic/sample/SampleDynamicBackend.hpp15
-rw-r--r--src/dynamic/sample/SampleDynamicLayerSupport.cpp51
-rw-r--r--src/dynamic/sample/SampleDynamicLayerSupport.hpp28
-rw-r--r--src/dynamic/sample/SampleDynamicWorkloadFactory.cpp75
-rw-r--r--src/dynamic/sample/SampleDynamicWorkloadFactory.hpp62
-rw-r--r--src/dynamic/sample/SampleMemoryManager.cpp95
-rw-r--r--src/dynamic/sample/SampleMemoryManager.hpp59
-rw-r--r--src/dynamic/sample/SampleTensorHandle.cpp137
-rw-r--r--src/dynamic/sample/SampleTensorHandle.hpp78
13 files changed, 800 insertions, 0 deletions
diff --git a/src/dynamic/sample/CMakeLists.txt b/src/dynamic/sample/CMakeLists.txt
new file mode 100644
index 0000000000..aeb870c32d
--- /dev/null
+++ b/src/dynamic/sample/CMakeLists.txt
@@ -0,0 +1,34 @@
+#
+# Copyright © 2020 Arm Ltd. All rights reserved.
+# SPDX-License-Identifier: MIT
+#
+
+cmake_minimum_required (VERSION 3.0.2)
+project(sample-dynamic)
+
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+list(APPEND armnnSampleDynamicBackend_sources
+ SampleDynamicAdditionWorkload.cpp
+ SampleDynamicAdditionWorkload.hpp
+ SampleDynamicBackend.cpp
+ SampleDynamicBackend.hpp
+ SampleDynamicLayerSupport.cpp
+ SampleDynamicLayerSupport.hpp
+ SampleDynamicWorkloadFactory.cpp
+ SampleDynamicWorkloadFactory.hpp
+ SampleMemoryManager.cpp
+ SampleMemoryManager.hpp
+ SampleTensorHandle.cpp
+ SampleTensorHandle.hpp
+)
+
+add_library(Arm_SampleDynamic_backend MODULE ${armnnSampleDynamicBackend_sources})
+
+target_include_directories(Arm_SampleDynamic_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../include)
+target_include_directories(Arm_SampleDynamic_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../third-party)
+target_include_directories(Arm_SampleDynamic_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../src/armnn)
+target_include_directories(Arm_SampleDynamic_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../src/armnnUtils)
+target_include_directories(Arm_SampleDynamic_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../src/backends)
+target_include_directories(Arm_SampleDynamic_backend PRIVATE ${PROJECT_SOURCE_DIR}/../../../src/profiling)
+
diff --git a/src/dynamic/sample/SampleDynamicAdditionWorkload.cpp b/src/dynamic/sample/SampleDynamicAdditionWorkload.cpp
new file mode 100644
index 0000000000..0fa57a7e07
--- /dev/null
+++ b/src/dynamic/sample/SampleDynamicAdditionWorkload.cpp
@@ -0,0 +1,54 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <armnn/backends/ITensorHandle.hpp>
+
+#include "SampleDynamicAdditionWorkload.hpp"
+#include "SampleTensorHandle.hpp"
+
+namespace armnn
+{
+
+inline const TensorInfo& GetTensorInfo(const ITensorHandle* tensorHandle)
+{
+ // We know that reference workloads use RefTensorHandles for inputs and outputs
+ const SampleTensorHandle* sampleTensorHandle =
+ static_cast<const SampleTensorHandle*>(tensorHandle);
+ return sampleTensorHandle->GetTensorInfo();
+}
+
+const float* GetInputTensorData(unsigned int idx, const AdditionQueueDescriptor& data)
+{
+ const ITensorHandle* tensorHandle = data.m_Inputs[idx];
+ return reinterpret_cast<const float*>(tensorHandle->Map());
+}
+
+float* GetOutputTensorData(unsigned int idx, const AdditionQueueDescriptor& data)
+{
+ ITensorHandle* tensorHandle = data.m_Outputs[idx];
+ return reinterpret_cast<float*>(tensorHandle->Map());
+}
+
+SampleDynamicAdditionWorkload::SampleDynamicAdditionWorkload(const AdditionQueueDescriptor& descriptor,
+ const WorkloadInfo& info)
+ : BaseWorkload(descriptor, info)
+{}
+
+void SampleDynamicAdditionWorkload::Execute() const
+{
+ const TensorInfo& info = GetTensorInfo(m_Data.m_Inputs[0]);
+ unsigned int num = info.GetNumElements();
+
+ const float* inputData0 = GetInputTensorData(0, m_Data);
+ const float* inputData1 = GetInputTensorData(1, m_Data);
+ float* outputData = GetOutputTensorData(0, m_Data);
+
+ for (unsigned int i = 0; i < num; ++i)
+ {
+ outputData[i] = inputData0[i] + inputData1[i];
+ }
+}
+
+} // namespace armnn
diff --git a/src/dynamic/sample/SampleDynamicAdditionWorkload.hpp b/src/dynamic/sample/SampleDynamicAdditionWorkload.hpp
new file mode 100644
index 0000000000..8362588c39
--- /dev/null
+++ b/src/dynamic/sample/SampleDynamicAdditionWorkload.hpp
@@ -0,0 +1,21 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <backendsCommon/Workload.hpp>
+#include <backendsCommon/WorkloadData.hpp>
+
+namespace armnn
+{
+
+class SampleDynamicAdditionWorkload : public BaseWorkload<AdditionQueueDescriptor>
+{
+public:
+ SampleDynamicAdditionWorkload(const AdditionQueueDescriptor& descriptor, const WorkloadInfo& info);
+
+ void Execute() const override;
+};
+
+} // namespace armnn
diff --git a/src/dynamic/sample/SampleDynamicBackend.cpp b/src/dynamic/sample/SampleDynamicBackend.cpp
new file mode 100644
index 0000000000..1863c1c98c
--- /dev/null
+++ b/src/dynamic/sample/SampleDynamicBackend.cpp
@@ -0,0 +1,91 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "SampleDynamicBackend.hpp"
+#include "SampleDynamicLayerSupport.hpp"
+#include "SampleDynamicWorkloadFactory.hpp"
+#include "SampleMemoryManager.hpp"
+
+#include <armnn/backends/IBackendInternal.hpp>
+#include <armnn/backends/OptimizationViews.hpp>
+
+namespace armnn
+{
+
+constexpr const char * SampleDynamicBackendId() { return "SampleDynamic"; }
+
+class SampleDynamicBackend : public IBackendInternal
+{
+public:
+ SampleDynamicBackend() = default;
+ ~SampleDynamicBackend() = default;
+
+ static const BackendId& GetIdStatic()
+ {
+ static const BackendId s_Id{SampleDynamicBackendId()};
+ return s_Id;
+ }
+
+ const BackendId& GetId() const override { return GetIdStatic(); }
+
+ IBackendInternal::IMemoryManagerUniquePtr CreateMemoryManager() const override
+ {
+ return std::make_unique<SampleMemoryManager>();
+ }
+
+ IBackendInternal::IWorkloadFactoryPtr CreateWorkloadFactory(
+ const IMemoryManagerSharedPtr& memoryManager) const override
+ {
+ return std::make_unique<SampleDynamicWorkloadFactory>();
+ }
+
+ IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override
+ {
+ static ILayerSupportSharedPtr layerSupport{new SampleDynamicLayerSupport};
+ return layerSupport;
+ }
+
+ IBackendInternal::IBackendContextPtr CreateBackendContext(const IRuntime::CreationOptions&) const override
+ {
+ return IBackendContextPtr{};
+ }
+
+ OptimizationViews OptimizeSubgraphView(const SubgraphView& subgraph) const override
+ {
+ OptimizationViews optimizationViews;
+
+ optimizationViews.AddUntouchedSubgraph(SubgraphView(subgraph));
+
+ return optimizationViews;
+ }
+
+};
+
+} // namespace armnn
+
+const char* GetBackendId()
+{
+ return armnn::SampleDynamicBackend::GetIdStatic().Get().c_str();
+}
+
+void GetVersion(uint32_t* outMajor, uint32_t* outMinor)
+{
+ if (!outMajor || !outMinor)
+ {
+ return;
+ }
+
+ armnn::BackendVersion apiVersion = armnn::IBackendInternal::GetApiVersion();
+
+ *outMajor = apiVersion.m_Major;
+ *outMinor = apiVersion.m_Minor;
+}
+
+void* BackendFactory()
+{
+ return new armnn::SampleDynamicBackend();
+}
+
+
diff --git a/src/dynamic/sample/SampleDynamicBackend.hpp b/src/dynamic/sample/SampleDynamicBackend.hpp
new file mode 100644
index 0000000000..8be1038e03
--- /dev/null
+++ b/src/dynamic/sample/SampleDynamicBackend.hpp
@@ -0,0 +1,15 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <cstdint>
+
+extern "C"
+{
+const char* GetBackendId();
+void GetVersion(uint32_t* outMajor, uint32_t* outMinor);
+void* BackendFactory();
+}
diff --git a/src/dynamic/sample/SampleDynamicLayerSupport.cpp b/src/dynamic/sample/SampleDynamicLayerSupport.cpp
new file mode 100644
index 0000000000..031d39cbae
--- /dev/null
+++ b/src/dynamic/sample/SampleDynamicLayerSupport.cpp
@@ -0,0 +1,51 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "SampleDynamicLayerSupport.hpp"
+
+#include <InternalTypes.hpp>
+#include <LayerSupportCommon.hpp>
+#include <armnn/Types.hpp>
+
+namespace armnn
+{
+
+bool SampleDynamicLayerSupport::IsInputSupported(const TensorInfo& input,
+ Optional<std::string&> reasonIfUnsupported) const
+{
+ return true;
+}
+
+bool SampleDynamicLayerSupport::IsOutputSupported(const TensorInfo& output,
+ Optional<std::string&> reasonIfUnsupported) const
+{
+ return true;
+}
+
+bool SampleDynamicLayerSupport::IsAdditionSupported(const TensorInfo& input0,
+ const TensorInfo& input1,
+ const TensorInfo& output,
+ Optional<std::string&> reasonIfUnsupported) const
+{
+
+ if (input0.GetDataType() != armnn::DataType::Float32)
+ {
+ return false;
+ }
+
+ if (input0.GetDataType() != input1.GetDataType())
+ {
+ return false;
+ }
+
+ if (input0.GetDataType() != output.GetDataType())
+ {
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace armnn
diff --git a/src/dynamic/sample/SampleDynamicLayerSupport.hpp b/src/dynamic/sample/SampleDynamicLayerSupport.hpp
new file mode 100644
index 0000000000..f6aa0cb91f
--- /dev/null
+++ b/src/dynamic/sample/SampleDynamicLayerSupport.hpp
@@ -0,0 +1,28 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#pragma once
+
+#include <backendsCommon/LayerSupportBase.hpp>
+
+namespace armnn
+{
+
+class SampleDynamicLayerSupport : public LayerSupportBase
+{
+public:
+ bool IsAdditionSupported(const TensorInfo& input0,
+ const TensorInfo& input1,
+ const TensorInfo& output,
+ Optional<std::string&> reasonIfUnsupported = EmptyOptional()) const override;
+
+ bool IsInputSupported(const TensorInfo& input,
+ Optional<std::string&> reasonIfUnsupported) const override;
+
+ bool IsOutputSupported(const TensorInfo& output,
+ Optional<std::string&> reasonIfUnsupported) const override;
+};
+
+} // namespace armnn
diff --git a/src/dynamic/sample/SampleDynamicWorkloadFactory.cpp b/src/dynamic/sample/SampleDynamicWorkloadFactory.cpp
new file mode 100644
index 0000000000..0fb5504f41
--- /dev/null
+++ b/src/dynamic/sample/SampleDynamicWorkloadFactory.cpp
@@ -0,0 +1,75 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <backendsCommon/CpuTensorHandle.hpp>
+#include <backendsCommon/MemCopyWorkload.hpp>
+
+#include "SampleDynamicAdditionWorkload.hpp"
+#include "SampleDynamicBackend.hpp"
+#include "SampleDynamicWorkloadFactory.hpp"
+#include "SampleTensorHandle.hpp"
+
+namespace armnn
+{
+
+namespace
+{
+static const BackendId s_Id{ GetBackendId() };
+}
+
+SampleDynamicWorkloadFactory::SampleDynamicWorkloadFactory(const std::shared_ptr<SampleMemoryManager>& memoryManager)
+ : m_MemoryManager(memoryManager)
+{
+}
+
+SampleDynamicWorkloadFactory::SampleDynamicWorkloadFactory()
+ : m_MemoryManager(new SampleMemoryManager())
+{
+}
+
+const BackendId& SampleDynamicWorkloadFactory::GetBackendId() const
+{
+ return s_Id;
+}
+
+bool SampleDynamicWorkloadFactory::IsLayerSupported(const IConnectableLayer& layer,
+ Optional<DataType> dataType,
+ std::string& outReasonIfUnsupported)
+{
+ return IWorkloadFactory::IsLayerSupported(s_Id, layer, dataType, outReasonIfUnsupported);
+}
+
+std::unique_ptr<ITensorHandle> SampleDynamicWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo,
+ const bool isMemoryManaged) const
+{
+ return std::make_unique<ScopedCpuTensorHandle>(tensorInfo);
+}
+
+std::unique_ptr<ITensorHandle> SampleDynamicWorkloadFactory::CreateTensorHandle(const TensorInfo& tensorInfo,
+ DataLayout dataLayout,
+ const bool isMemoryManaged) const
+{
+ return std::make_unique<ScopedCpuTensorHandle>(tensorInfo);
+}
+
+std::unique_ptr<IWorkload> SampleDynamicWorkloadFactory::CreateAddition(const AdditionQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const
+{
+ return std::make_unique<SampleDynamicAdditionWorkload>(descriptor, info);
+}
+
+std::unique_ptr<IWorkload> SampleDynamicWorkloadFactory::CreateInput(const InputQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const
+{
+ return std::make_unique<CopyMemGenericWorkload>(descriptor, info);
+}
+
+std::unique_ptr<IWorkload> SampleDynamicWorkloadFactory::CreateOutput(const OutputQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const
+{
+ return std::make_unique<CopyMemGenericWorkload>(descriptor, info);
+}
+
+} // namespace armnn
diff --git a/src/dynamic/sample/SampleDynamicWorkloadFactory.hpp b/src/dynamic/sample/SampleDynamicWorkloadFactory.hpp
new file mode 100644
index 0000000000..88b67987e1
--- /dev/null
+++ b/src/dynamic/sample/SampleDynamicWorkloadFactory.hpp
@@ -0,0 +1,62 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include "SampleMemoryManager.hpp"
+
+#include <armnn/Optional.hpp>
+#include <backendsCommon/WorkloadFactory.hpp>
+
+namespace armnn
+{
+
+// Sample Dynamic workload factory.
+class SampleDynamicWorkloadFactory : public IWorkloadFactory
+{
+public:
+ explicit SampleDynamicWorkloadFactory(const std::shared_ptr<SampleMemoryManager>& memoryManager);
+ SampleDynamicWorkloadFactory();
+
+ ~SampleDynamicWorkloadFactory() {}
+
+ const BackendId& GetBackendId() const override;
+
+ static bool IsLayerSupported(const IConnectableLayer& layer,
+ Optional<DataType> dataType,
+ std::string& outReasonIfUnsupported);
+
+ bool SupportsSubTensors() const override { return false; }
+
+ std::unique_ptr<ITensorHandle> CreateSubTensorHandle(ITensorHandle& parent,
+ TensorShape const& subTensorShape,
+ unsigned int const* subTensorOrigin) const override
+ {
+ boost::ignore_unused(parent, subTensorShape, subTensorOrigin);
+ return nullptr;
+ }
+
+ std::unique_ptr<ITensorHandle> CreateTensorHandle(const TensorInfo& tensorInfo,
+ const bool IsMemoryManaged = true) const override;
+
+ std::unique_ptr<ITensorHandle> CreateTensorHandle(const TensorInfo& tensorInfo,
+ DataLayout dataLayout,
+ const bool IsMemoryManaged = true) const override;
+
+ std::unique_ptr<IWorkload> CreateAddition(const AdditionQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const override;
+
+
+ std::unique_ptr<IWorkload> CreateInput(const InputQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const override;
+
+ std::unique_ptr<IWorkload> CreateOutput(const OutputQueueDescriptor& descriptor,
+ const WorkloadInfo& info) const override;
+
+private:
+ mutable std::shared_ptr<SampleMemoryManager> m_MemoryManager;
+
+};
+
+} // namespace armnn
diff --git a/src/dynamic/sample/SampleMemoryManager.cpp b/src/dynamic/sample/SampleMemoryManager.cpp
new file mode 100644
index 0000000000..30a7548b02
--- /dev/null
+++ b/src/dynamic/sample/SampleMemoryManager.cpp
@@ -0,0 +1,95 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "SampleMemoryManager.hpp"
+
+#include <algorithm>
+
+namespace armnn
+{
+
+SampleMemoryManager::SampleMemoryManager()
+{}
+
+SampleMemoryManager::~SampleMemoryManager()
+{}
+
+SampleMemoryManager::Pool* SampleMemoryManager::Manage(unsigned int numBytes)
+{
+ if (!m_FreePools.empty())
+ {
+ Pool* res = m_FreePools.back();
+ m_FreePools.pop_back();
+ res->Reserve(numBytes);
+ return res;
+ }
+ else
+ {
+ m_Pools.push_front(Pool(numBytes));
+ return &m_Pools.front();
+ }
+}
+
+void SampleMemoryManager::Allocate(SampleMemoryManager::Pool* pool)
+{
+ m_FreePools.push_back(pool);
+}
+
+void* SampleMemoryManager::GetPointer(SampleMemoryManager::Pool* pool)
+{
+ return pool->GetPointer();
+}
+
+void SampleMemoryManager::Acquire()
+{
+ for (Pool &pool: m_Pools)
+ {
+ pool.Acquire();
+ }
+}
+
+void SampleMemoryManager::Release()
+{
+ for (Pool &pool: m_Pools)
+ {
+ pool.Release();
+ }
+}
+
+SampleMemoryManager::Pool::Pool(unsigned int numBytes)
+ : m_Size(numBytes),
+ m_Pointer(nullptr)
+{}
+
+SampleMemoryManager::Pool::~Pool()
+{
+ if (m_Pointer)
+ {
+ Release();
+ }
+}
+
+void* SampleMemoryManager::Pool::GetPointer()
+{
+ return m_Pointer;
+}
+
+void SampleMemoryManager::Pool::Reserve(unsigned int numBytes)
+{
+ m_Size = std::max(m_Size, numBytes);
+}
+
+void SampleMemoryManager::Pool::Acquire()
+{
+ m_Pointer = ::operator new(size_t(m_Size));
+}
+
+void SampleMemoryManager::Pool::Release()
+{
+ ::operator delete(m_Pointer);
+ m_Pointer = nullptr;
+}
+
+}
diff --git a/src/dynamic/sample/SampleMemoryManager.hpp b/src/dynamic/sample/SampleMemoryManager.hpp
new file mode 100644
index 0000000000..0993bc1e2b
--- /dev/null
+++ b/src/dynamic/sample/SampleMemoryManager.hpp
@@ -0,0 +1,59 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <armnn/backends/IMemoryManager.hpp>
+
+#include <forward_list>
+#include <vector>
+
+namespace armnn
+{
+
+// An implementation of IMemoryManager to be used with SampleTensorHandle
+class SampleMemoryManager : public IMemoryManager
+{
+public:
+ SampleMemoryManager();
+ virtual ~SampleMemoryManager();
+
+ class Pool;
+
+ Pool* Manage(unsigned int numBytes);
+
+ void Allocate(Pool *pool);
+
+ void* GetPointer(Pool *pool);
+
+ void Acquire() override;
+ void Release() override;
+
+ class Pool
+ {
+ public:
+ Pool(unsigned int numBytes);
+ ~Pool();
+
+ void Acquire();
+ void Release();
+
+ void* GetPointer();
+
+ void Reserve(unsigned int numBytes);
+
+ private:
+ unsigned int m_Size;
+ void* m_Pointer;
+ };
+
+private:
+ SampleMemoryManager(const SampleMemoryManager&) = delete; // Noncopyable
+ SampleMemoryManager& operator=(const SampleMemoryManager&) = delete; // Noncopyable
+
+ std::forward_list<Pool> m_Pools;
+ std::vector<Pool*> m_FreePools;
+};
+
+}
diff --git a/src/dynamic/sample/SampleTensorHandle.cpp b/src/dynamic/sample/SampleTensorHandle.cpp
new file mode 100644
index 0000000000..48f8cf44fa
--- /dev/null
+++ b/src/dynamic/sample/SampleTensorHandle.cpp
@@ -0,0 +1,137 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "SampleTensorHandle.hpp"
+
+namespace armnn
+{
+
+SampleTensorHandle::SampleTensorHandle(const TensorInfo &tensorInfo,
+ std::shared_ptr<SampleMemoryManager> &memoryManager)
+ : m_TensorInfo(tensorInfo),
+ m_MemoryManager(memoryManager),
+ m_Pool(nullptr),
+ m_UnmanagedMemory(nullptr),
+ m_ImportFlags(static_cast<MemorySourceFlags>(MemorySource::Undefined)),
+ m_Imported(false)
+{
+
+}
+
+SampleTensorHandle::SampleTensorHandle(const TensorInfo& tensorInfo,
+ std::shared_ptr<SampleMemoryManager> &memoryManager,
+ MemorySourceFlags importFlags)
+ : m_TensorInfo(tensorInfo),
+ m_MemoryManager(memoryManager),
+ m_Pool(nullptr),
+ m_UnmanagedMemory(nullptr),
+ m_ImportFlags(importFlags),
+ m_Imported(false)
+{
+
+}
+
+SampleTensorHandle::~SampleTensorHandle()
+{
+ if (!m_Pool)
+ {
+ // unmanaged
+ if (!m_Imported)
+ {
+ ::operator delete(m_UnmanagedMemory);
+ }
+ }
+}
+
+void SampleTensorHandle::Manage()
+{
+ m_Pool = m_MemoryManager->Manage(m_TensorInfo.GetNumBytes());
+}
+
+void SampleTensorHandle::Allocate()
+{
+ if (!m_UnmanagedMemory)
+ {
+ if (!m_Pool)
+ {
+ // unmanaged
+ m_UnmanagedMemory = ::operator new(m_TensorInfo.GetNumBytes());
+ }
+ else
+ {
+ m_MemoryManager->Allocate(m_Pool);
+ }
+ }
+ else
+ {
+ throw InvalidArgumentException("SampleTensorHandle::Allocate Trying to allocate a SampleTensorHandle"
+ "that already has allocated memory.");
+ }
+}
+
+const void* SampleTensorHandle::Map(bool /*unused*/) const
+{
+ return GetPointer();
+}
+
+void* SampleTensorHandle::GetPointer() const
+{
+ if (m_UnmanagedMemory)
+ {
+ return m_UnmanagedMemory;
+ }
+ else
+ {
+ return m_MemoryManager->GetPointer(m_Pool);
+ }
+}
+
+bool SampleTensorHandle::Import(void* memory, MemorySource source)
+{
+
+ if (m_ImportFlags & static_cast<MemorySourceFlags>(source))
+ {
+ if (source == MemorySource::Malloc)
+ {
+ // Check memory alignment
+ constexpr uintptr_t alignment = sizeof(size_t);
+ if (reinterpret_cast<uintptr_t>(memory) % alignment)
+ {
+ 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;
+}
+
+}
diff --git a/src/dynamic/sample/SampleTensorHandle.hpp b/src/dynamic/sample/SampleTensorHandle.hpp
new file mode 100644
index 0000000000..c08edc69b7
--- /dev/null
+++ b/src/dynamic/sample/SampleTensorHandle.hpp
@@ -0,0 +1,78 @@
+//
+// Copyright © 2020 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <backendsCommon/CpuTensorHandle.hpp>
+
+#include "SampleMemoryManager.hpp"
+
+namespace armnn
+{
+
+// An implementation of ITensorHandle with simple "bump the pointer" memory-management behaviour
+class SampleTensorHandle : public ITensorHandle
+{
+public:
+ SampleTensorHandle(const TensorInfo& tensorInfo, std::shared_ptr<SampleMemoryManager> &memoryManager);
+
+ SampleTensorHandle(const TensorInfo& tensorInfo,
+ std::shared_ptr<SampleMemoryManager> &memoryManager,
+ MemorySourceFlags importFlags);
+
+ ~SampleTensorHandle();
+
+ virtual void Manage() override;
+
+ virtual void Allocate() override;
+
+ virtual ITensorHandle* GetParent() const override
+ {
+ return nullptr;
+ }
+
+ virtual const void* Map(bool /* blocking = true */) const override;
+ using ITensorHandle::Map;
+
+ virtual void Unmap() const override
+ {}
+
+ TensorShape GetStrides() const override
+ {
+ return GetUnpaddedTensorStrides(m_TensorInfo);
+ }
+
+ TensorShape GetShape() const override
+ {
+ return m_TensorInfo.GetShape();
+ }
+
+ const TensorInfo& GetTensorInfo() const
+ {
+ return m_TensorInfo;
+ }
+
+ virtual MemorySourceFlags GetImportFlags() const override
+ {
+ return m_ImportFlags;
+ }
+
+ virtual bool Import(void* memory, MemorySource source) override;
+
+private:
+ void* GetPointer() const;
+
+ SampleTensorHandle(const SampleTensorHandle& other) = delete; // noncopyable
+ SampleTensorHandle& operator=(const SampleTensorHandle& other) = delete; //noncopyable
+
+ TensorInfo m_TensorInfo;
+
+ std::shared_ptr<SampleMemoryManager> m_MemoryManager;
+ SampleMemoryManager::Pool* m_Pool;
+ mutable void *m_UnmanagedMemory;
+ MemorySourceFlags m_ImportFlags;
+ bool m_Imported;
+};
+
+}