From 17948b5eb666f0ca17b40ccaf6712361bbfe6a44 Mon Sep 17 00:00:00 2001 From: Colm Donelan Date: Tue, 1 Feb 2022 23:37:04 +0000 Subject: IVGCVSW-6635 Expose a new MockWorkloadFactory and MockMemManager (Part 1) * Create a MockBackend in armnnTestUtils. * Create corresponding WorkloadFactory, TensorHandle, TensorHandleFactory MemoryManager and WorkloadFactoryHelper classes. Signed-off-by: Colm Donelan Change-Id: I884731b109bc623a7272e5ad333ff754f8c13ae1 --- include/armnnTestUtils/MockBackend.hpp | 115 +++++++++++++++ include/armnnTestUtils/MockMemoryManager.hpp | 59 ++++++++ include/armnnTestUtils/MockTensorHandle.hpp | 81 +++++++++++ src/armnnTestUtils/CMakeLists.txt | 9 ++ src/armnnTestUtils/MockBackend.cpp | 55 +++++++ src/armnnTestUtils/MockMemoryManager.cpp | 93 ++++++++++++ src/armnnTestUtils/MockTensorHandle.cpp | 176 +++++++++++++++++++++++ src/armnnTestUtils/MockTensorHandleFactory.cpp | 87 +++++++++++ src/armnnTestUtils/MockTensorHandleFactory.hpp | 61 ++++++++ src/armnnTestUtils/MockWorkloadFactoryHelper.hpp | 41 ++++++ 10 files changed, 777 insertions(+) create mode 100644 include/armnnTestUtils/MockBackend.hpp create mode 100644 include/armnnTestUtils/MockMemoryManager.hpp create mode 100644 include/armnnTestUtils/MockTensorHandle.hpp create mode 100644 src/armnnTestUtils/MockBackend.cpp create mode 100644 src/armnnTestUtils/MockMemoryManager.cpp create mode 100644 src/armnnTestUtils/MockTensorHandle.cpp create mode 100644 src/armnnTestUtils/MockTensorHandleFactory.cpp create mode 100644 src/armnnTestUtils/MockTensorHandleFactory.hpp create mode 100644 src/armnnTestUtils/MockWorkloadFactoryHelper.hpp diff --git a/include/armnnTestUtils/MockBackend.hpp b/include/armnnTestUtils/MockBackend.hpp new file mode 100644 index 0000000000..8bc41b3f3f --- /dev/null +++ b/include/armnnTestUtils/MockBackend.hpp @@ -0,0 +1,115 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// +#pragma once + +#include +#include +#include + +namespace armnn +{ + +// A bare bones Mock backend to enable unit testing of simple tensor manipulation features. +class MockBackend : public IBackendInternal +{ +public: + MockBackend() = default; + + ~MockBackend() = default; + + static const BackendId& GetIdStatic(); + + const BackendId& GetId() const override + { + return GetIdStatic(); + } + IBackendInternal::IWorkloadFactoryPtr + CreateWorkloadFactory(const IBackendInternal::IMemoryManagerSharedPtr& memoryManager = nullptr) const override + { + IgnoreUnused(memoryManager); + return nullptr; + } + + IBackendInternal::ILayerSupportSharedPtr GetLayerSupport() const override + { + return nullptr; + }; +}; + +class MockWorkloadFactory : public IWorkloadFactory +{ + +public: + explicit MockWorkloadFactory(const std::shared_ptr& memoryManager); + MockWorkloadFactory(); + + ~MockWorkloadFactory() + {} + + const BackendId& GetBackendId() const override; + + bool SupportsSubTensors() const override + { + return false; + } + + ARMNN_DEPRECATED_MSG("Use ITensorHandleFactory::CreateSubTensorHandle instead") + std::unique_ptr CreateSubTensorHandle(ITensorHandle&, + TensorShape const&, + unsigned int const*) const override + { + return nullptr; + } + + ARMNN_DEPRECATED_MSG("Use ITensorHandleFactory::CreateTensorHandle instead") + std::unique_ptr CreateTensorHandle(const TensorInfo& tensorInfo, + const bool IsMemoryManaged = true) const override + { + IgnoreUnused(IsMemoryManaged); + return std::make_unique(tensorInfo, m_MemoryManager); + }; + + ARMNN_DEPRECATED_MSG("Use ITensorHandleFactory::CreateTensorHandle instead") + std::unique_ptr CreateTensorHandle(const TensorInfo& tensorInfo, + DataLayout dataLayout, + const bool IsMemoryManaged = true) const override + { + IgnoreUnused(dataLayout, IsMemoryManaged); + return std::make_unique(tensorInfo, static_cast(MemorySource::Malloc)); + }; + + ARMNN_DEPRECATED_MSG_REMOVAL_DATE( + "Use ABI stable " + "CreateWorkload(LayerType, const QueueDescriptor&, const WorkloadInfo& info) instead.", + "22.11") + std::unique_ptr CreateInput(const InputQueueDescriptor& descriptor, + const WorkloadInfo& info) const override + { + if (info.m_InputTensorInfos.empty()) + { + throw InvalidArgumentException("MockWorkloadFactory::CreateInput: Input cannot be zero length"); + } + if (info.m_OutputTensorInfos.empty()) + { + throw InvalidArgumentException("MockWorkloadFactory::CreateInput: Output cannot be zero length"); + } + + if (info.m_InputTensorInfos[0].GetNumBytes() != info.m_OutputTensorInfos[0].GetNumBytes()) + { + throw InvalidArgumentException( + "MockWorkloadFactory::CreateInput: data input and output differ in byte count."); + } + + return std::make_unique(descriptor, info); + }; + + std::unique_ptr + CreateWorkload(LayerType type, const QueueDescriptor& descriptor, const WorkloadInfo& info) const override; + +private: + mutable std::shared_ptr m_MemoryManager; +}; + +} // namespace armnn diff --git a/include/armnnTestUtils/MockMemoryManager.hpp b/include/armnnTestUtils/MockMemoryManager.hpp new file mode 100644 index 0000000000..38cd56747a --- /dev/null +++ b/include/armnnTestUtils/MockMemoryManager.hpp @@ -0,0 +1,59 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// +#pragma once + +#include + +#include +#include + +namespace armnn +{ + +// An implementation of IMemoryManager to be used with MockTensorHandle +class MockMemoryManager : public IMemoryManager +{ +public: + MockMemoryManager(); + virtual ~MockMemoryManager(); + + 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: + MockMemoryManager(const MockMemoryManager&) = delete; // Noncopyable + MockMemoryManager& operator=(const MockMemoryManager&) = delete; // Noncopyable + + std::forward_list m_Pools; + std::vector m_FreePools; +}; + +} // namespace armnn diff --git a/include/armnnTestUtils/MockTensorHandle.hpp b/include/armnnTestUtils/MockTensorHandle.hpp new file mode 100644 index 0000000000..9a7518b21a --- /dev/null +++ b/include/armnnTestUtils/MockTensorHandle.hpp @@ -0,0 +1,81 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// +#pragma once + +#include "MockMemoryManager.hpp" +#include + +namespace armnn +{ + +// An implementation of ITensorHandle with simple "bump the pointer" memory-management behaviour +class MockTensorHandle : public ITensorHandle +{ +public: + MockTensorHandle(const TensorInfo& tensorInfo, std::shared_ptr& memoryManager); + + MockTensorHandle(const TensorInfo& tensorInfo, MemorySourceFlags importFlags); + + ~MockTensorHandle() override; + + void Manage() override; + + void Allocate() override; + + ITensorHandle* GetParent() const override + { + return nullptr; + } + + const void* Map(bool /* blocking = true */) const override; + using ITensorHandle::Map; + + 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; + } + + MemorySourceFlags GetImportFlags() const override + { + return m_ImportFlags; + } + + bool Import(void* memory, MemorySource source) override; + bool CanBeImported(void* memory, MemorySource source) override; + +private: + // Only used for testing + void CopyOutTo(void*) const override; + void CopyInFrom(const void*) override; + + void* GetPointer() const; + + MockTensorHandle(const MockTensorHandle& other) = delete; // noncopyable + MockTensorHandle& operator=(const MockTensorHandle& other) = delete; //noncopyable + + TensorInfo m_TensorInfo; + + std::shared_ptr m_MemoryManager; + MockMemoryManager::Pool* m_Pool; + mutable void* m_UnmanagedMemory; + MemorySourceFlags m_ImportFlags; + bool m_Imported; + bool m_IsImportEnabled; +}; + +} // namespace armnn diff --git a/src/armnnTestUtils/CMakeLists.txt b/src/armnnTestUtils/CMakeLists.txt index fae745256f..cab0ba353e 100755 --- a/src/armnnTestUtils/CMakeLists.txt +++ b/src/armnnTestUtils/CMakeLists.txt @@ -8,6 +8,9 @@ set(armnnTestUtils_sources) list(APPEND armnnTestUtils_sources ../../include/armnnTestUtils/DataLayoutUtils.hpp ../../include/armnnTestUtils/LayerTestResult.hpp + ../../include/armnnTestUtils/MockBackend.hpp + ../../include/armnnTestUtils/MockMemoryManager.hpp + ../../include/armnnTestUtils/MockTensorHandle.hpp ../../include/armnnTestUtils/PredicateResult.hpp ../../include/armnnTestUtils/TensorCopyUtils.hpp ../../include/armnnTestUtils/WorkloadTestUtils.hpp @@ -18,6 +21,12 @@ list(APPEND armnnTestUtils_sources DataTypeUtils.hpp GraphUtils.cpp GraphUtils.hpp + MockBackend.cpp + MockMemoryManager.cpp + MockTensorHandle.cpp + MockTensorHandleFactory.hpp + MockTensorHandleFactory.cpp + MockWorkloadFactoryHelper.hpp TensorCopyUtils.cpp TestUtils.cpp TestUtils.hpp diff --git a/src/armnnTestUtils/MockBackend.cpp b/src/armnnTestUtils/MockBackend.cpp new file mode 100644 index 0000000000..40f97cd28e --- /dev/null +++ b/src/armnnTestUtils/MockBackend.cpp @@ -0,0 +1,55 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include +#include +#include + +namespace armnn +{ + +constexpr const char* MockBackendId() +{ + return "CpuMock"; +} + +namespace +{ +static const BackendId s_Id{ MockBackendId() }; +} + +MockWorkloadFactory::MockWorkloadFactory(const std::shared_ptr& memoryManager) + : m_MemoryManager(memoryManager) +{} + +MockWorkloadFactory::MockWorkloadFactory() + : m_MemoryManager(new MockMemoryManager()) +{} + +const BackendId& MockWorkloadFactory::GetBackendId() const +{ + return s_Id; +} + +std::unique_ptr MockWorkloadFactory::CreateWorkload(LayerType type, + const QueueDescriptor& descriptor, + const WorkloadInfo& info) const +{ + switch (type) + { + case LayerType::MemCopy: { + auto memCopyQueueDescriptor = PolymorphicDowncast(&descriptor); + if (descriptor.m_Inputs.empty()) + { + throw InvalidArgumentException("MockWorkloadFactory: CreateMemCopy() expected an input tensor."); + } + return std::make_unique(*memCopyQueueDescriptor, info); + } + default: + return nullptr; + } +} + +} // namespace armnn \ No newline at end of file diff --git a/src/armnnTestUtils/MockMemoryManager.cpp b/src/armnnTestUtils/MockMemoryManager.cpp new file mode 100644 index 0000000000..3ff6ec85d9 --- /dev/null +++ b/src/armnnTestUtils/MockMemoryManager.cpp @@ -0,0 +1,93 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "armnnTestUtils/MockMemoryManager.hpp" + +namespace armnn +{ + +MockMemoryManager::MockMemoryManager() +{} + +MockMemoryManager::~MockMemoryManager() +{} + +MockMemoryManager::Pool* MockMemoryManager::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 MockMemoryManager::Allocate(MockMemoryManager::Pool* pool) +{ + m_FreePools.push_back(pool); +} + +void* MockMemoryManager::GetPointer(MockMemoryManager::Pool* pool) +{ + return pool->GetPointer(); +} + +void MockMemoryManager::Acquire() +{ + for (Pool& pool : m_Pools) + { + pool.Acquire(); + } +} + +void MockMemoryManager::Release() +{ + for (Pool& pool : m_Pools) + { + pool.Release(); + } +} + +MockMemoryManager::Pool::Pool(unsigned int numBytes) + : m_Size(numBytes) + , m_Pointer(nullptr) +{} + +MockMemoryManager::Pool::~Pool() +{ + if (m_Pointer) + { + Release(); + } +} + +void* MockMemoryManager::Pool::GetPointer() +{ + return m_Pointer; +} + +void MockMemoryManager::Pool::Reserve(unsigned int numBytes) +{ + m_Size = std::max(m_Size, numBytes); +} + +void MockMemoryManager::Pool::Acquire() +{ + m_Pointer = ::operator new(size_t(m_Size)); +} + +void MockMemoryManager::Pool::Release() +{ + ::operator delete(m_Pointer); + m_Pointer = nullptr; +} + +} // namespace armnn diff --git a/src/armnnTestUtils/MockTensorHandle.cpp b/src/armnnTestUtils/MockTensorHandle.cpp new file mode 100644 index 0000000000..be4d5a8d92 --- /dev/null +++ b/src/armnnTestUtils/MockTensorHandle.cpp @@ -0,0 +1,176 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "armnnTestUtils/MockTensorHandle.hpp" + +namespace armnn +{ + +MockTensorHandle::MockTensorHandle(const TensorInfo& tensorInfo, std::shared_ptr& memoryManager) + : m_TensorInfo(tensorInfo) + , m_MemoryManager(memoryManager) + , m_Pool(nullptr) + , m_UnmanagedMemory(nullptr) + , m_ImportFlags(static_cast(MemorySource::Undefined)) + , m_Imported(false) + , m_IsImportEnabled(false) +{} + +MockTensorHandle::MockTensorHandle(const TensorInfo& tensorInfo, MemorySourceFlags importFlags) + : m_TensorInfo(tensorInfo) + , m_Pool(nullptr) + , m_UnmanagedMemory(nullptr) + , m_ImportFlags(importFlags) + , m_Imported(false) + , m_IsImportEnabled(true) +{} + +MockTensorHandle::~MockTensorHandle() +{ + if (!m_Pool) + { + // unmanaged + if (!m_Imported) + { + ::operator delete(m_UnmanagedMemory); + } + } +} + +void MockTensorHandle::Manage() +{ + if (!m_IsImportEnabled) + { + ARMNN_ASSERT_MSG(!m_Pool, "MockTensorHandle::Manage() called twice"); + ARMNN_ASSERT_MSG(!m_UnmanagedMemory, "MockTensorHandle::Manage() called after Allocate()"); + + m_Pool = m_MemoryManager->Manage(m_TensorInfo.GetNumBytes()); + } +} + +void MockTensorHandle::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("MockTensorHandle::Allocate Trying to allocate a MockTensorHandle" + "that already has allocated memory."); + } + } +} + +const void* MockTensorHandle::Map(bool /*unused*/) const +{ + return GetPointer(); +} + +void* MockTensorHandle::GetPointer() const +{ + if (m_UnmanagedMemory) + { + return m_UnmanagedMemory; + } + else if (m_Pool) + { + return m_MemoryManager->GetPointer(m_Pool); + } + else + { + throw NullPointerException("MockTensorHandle::GetPointer called on unmanaged, unallocated tensor handle"); + } +} + +void MockTensorHandle::CopyOutTo(void* dest) const +{ + const void* src = GetPointer(); + ARMNN_ASSERT(src); + memcpy(dest, src, m_TensorInfo.GetNumBytes()); +} + +void MockTensorHandle::CopyInFrom(const void* src) +{ + void* dest = GetPointer(); + ARMNN_ASSERT(dest); + memcpy(dest, src, m_TensorInfo.GetNumBytes()); +} + +bool MockTensorHandle::Import(void* memory, MemorySource source) +{ + if (m_ImportFlags & static_cast(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 MockTensorHandle::CanBeImported(void* memory, MemorySource source) +{ + if (m_ImportFlags & static_cast(source)) + { + if (m_IsImportEnabled && source == MemorySource::Malloc) + { + uintptr_t alignment = GetDataTypeSize(m_TensorInfo.GetDataType()); + if (reinterpret_cast(memory) % alignment) + { + return false; + } + + return true; + } + } + return false; +} + +} // namespace armnn diff --git a/src/armnnTestUtils/MockTensorHandleFactory.cpp b/src/armnnTestUtils/MockTensorHandleFactory.cpp new file mode 100644 index 0000000000..e90f318296 --- /dev/null +++ b/src/armnnTestUtils/MockTensorHandleFactory.cpp @@ -0,0 +1,87 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include "MockTensorHandleFactory.hpp" +#include + +namespace armnn +{ + +using FactoryId = ITensorHandleFactory::FactoryId; + +const FactoryId& MockTensorHandleFactory::GetIdStatic() +{ + static const FactoryId s_Id(MockTensorHandleFactoryId()); + return s_Id; +} + +std::unique_ptr MockTensorHandleFactory::CreateSubTensorHandle(ITensorHandle&, + TensorShape const&, + unsigned int const*) const +{ + return nullptr; +} + +std::unique_ptr MockTensorHandleFactory::CreateTensorHandle(const TensorInfo& tensorInfo) const +{ + return std::make_unique(tensorInfo, m_MemoryManager); +} + +std::unique_ptr MockTensorHandleFactory::CreateTensorHandle(const TensorInfo& tensorInfo, + DataLayout dataLayout) const +{ + IgnoreUnused(dataLayout); + return std::make_unique(tensorInfo, m_MemoryManager); +} + +std::unique_ptr MockTensorHandleFactory::CreateTensorHandle(const TensorInfo& tensorInfo, + const bool IsMemoryManaged) const +{ + if (IsMemoryManaged) + { + return std::make_unique(tensorInfo, m_MemoryManager); + } + else + { + return std::make_unique(tensorInfo, m_ImportFlags); + } +} + +std::unique_ptr MockTensorHandleFactory::CreateTensorHandle(const TensorInfo& tensorInfo, + DataLayout dataLayout, + const bool IsMemoryManaged) const +{ + IgnoreUnused(dataLayout); + if (IsMemoryManaged) + { + return std::make_unique(tensorInfo, m_MemoryManager); + } + else + { + return std::make_unique(tensorInfo, m_ImportFlags); + } +} + +const FactoryId& MockTensorHandleFactory::GetId() const +{ + return GetIdStatic(); +} + +bool MockTensorHandleFactory::SupportsSubTensors() const +{ + return false; +} + +MemorySourceFlags MockTensorHandleFactory::GetExportFlags() const +{ + return m_ExportFlags; +} + +MemorySourceFlags MockTensorHandleFactory::GetImportFlags() const +{ + return m_ImportFlags; +} + +} // namespace armnn \ No newline at end of file diff --git a/src/armnnTestUtils/MockTensorHandleFactory.hpp b/src/armnnTestUtils/MockTensorHandleFactory.hpp new file mode 100644 index 0000000000..ffe7c8bc97 --- /dev/null +++ b/src/armnnTestUtils/MockTensorHandleFactory.hpp @@ -0,0 +1,61 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include + +namespace armnn +{ + +constexpr const char* MockTensorHandleFactoryId() +{ + return "Arm/Mock/TensorHandleFactory"; +} + +class MockTensorHandleFactory : public ITensorHandleFactory +{ + +public: + explicit MockTensorHandleFactory(std::shared_ptr mgr) + : m_MemoryManager(mgr) + , m_ImportFlags(static_cast(MemorySource::Malloc)) + , m_ExportFlags(static_cast(MemorySource::Malloc)) + {} + + std::unique_ptr CreateSubTensorHandle(ITensorHandle& parent, + TensorShape const& subTensorShape, + unsigned int const* subTensorOrigin) const override; + + std::unique_ptr CreateTensorHandle(const TensorInfo& tensorInfo) const override; + + std::unique_ptr CreateTensorHandle(const TensorInfo& tensorInfo, + DataLayout dataLayout) const override; + + std::unique_ptr CreateTensorHandle(const TensorInfo& tensorInfo, + const bool IsMemoryManaged) const override; + + std::unique_ptr CreateTensorHandle(const TensorInfo& tensorInfo, + DataLayout dataLayout, + const bool IsMemoryManaged) const override; + + static const FactoryId& GetIdStatic(); + + const FactoryId& GetId() const override; + + bool SupportsSubTensors() const override; + + MemorySourceFlags GetExportFlags() const override; + + MemorySourceFlags GetImportFlags() const override; + +private: + mutable std::shared_ptr m_MemoryManager; + MemorySourceFlags m_ImportFlags; + MemorySourceFlags m_ExportFlags; +}; + +} // namespace armnn diff --git a/src/armnnTestUtils/MockWorkloadFactoryHelper.hpp b/src/armnnTestUtils/MockWorkloadFactoryHelper.hpp new file mode 100644 index 0000000000..6b61cf6474 --- /dev/null +++ b/src/armnnTestUtils/MockWorkloadFactoryHelper.hpp @@ -0,0 +1,41 @@ +// +// Copyright © 2022 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#pragma once + +#include +#include +#include + +namespace +{ + +template <> +struct WorkloadFactoryHelper +{ + static armnn::IBackendInternal::IMemoryManagerSharedPtr GetMemoryManager() + { + armnn::MockBackend backend; + return backend.CreateMemoryManager(); + } + + static armnn::MockWorkloadFactory + GetFactory(const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager = nullptr) + { + IgnoreUnused(memoryManager); + return armnn::MockWorkloadFactory(); + } + + static armnn::MockTensorHandleFactory + GetTensorHandleFactory(const armnn::IBackendInternal::IMemoryManagerSharedPtr& memoryManager = nullptr) + { + + return armnn::MockTensorHandleFactory(std::static_pointer_cast(memoryManager)); + } +}; + +using MockWorkloadFactoryHelper = WorkloadFactoryHelper; + +} // anonymous namespace -- cgit v1.2.1