aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeresa Charlin <teresa.charlinreyes@arm.com>2021-10-01 11:29:08 +0100
committerTeresaARM <teresa.charlinreyes@arm.com>2021-10-26 16:15:13 +0000
commitca5883951ab51191eb19502459f0936fc96e14f1 (patch)
tree03973265a28e489719cc51a826c1531006823c83
parentfea41d70385fec1d9e1c3367cfad2736ed7d20b2 (diff)
downloadarmnn-ca5883951ab51191eb19502459f0936fc96e14f1.tar.gz
IVGCVSW-6301 Create the MemoryManager class
Signed-off-by: Teresa Charlin <teresa.charlinreyes@arm.com> Signed-off-by: Finn Williams <finn.williams@arm.com> Change-Id: Ia41b5252d695daabd5afaf1b2267444d24be173a
-rw-r--r--src/backends/backendsCommon/CMakeLists.txt8
-rw-r--r--src/backends/backendsCommon/MemoryManager.cpp53
-rw-r--r--src/backends/backendsCommon/MemoryManager.hpp60
-rw-r--r--src/backends/backendsCommon/test/CMakeLists.txt3
-rw-r--r--src/backends/backendsCommon/test/MemoryManagerTests.cpp107
5 files changed, 227 insertions, 4 deletions
diff --git a/src/backends/backendsCommon/CMakeLists.txt b/src/backends/backendsCommon/CMakeLists.txt
index a18ee330d4..90fb376dae 100644
--- a/src/backends/backendsCommon/CMakeLists.txt
+++ b/src/backends/backendsCommon/CMakeLists.txt
@@ -1,11 +1,9 @@
#
-# Copyright © 2017 Arm Ltd. All rights reserved.
+# Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
# SPDX-License-Identifier: MIT
#
list(APPEND armnnBackendsCommon_sources
- TensorHandle.cpp
- TensorHandle.hpp
DynamicBackend.cpp
DynamicBackend.hpp
DynamicBackendUtils.cpp
@@ -29,10 +27,14 @@ list(APPEND armnnBackendsCommon_sources
MemoryOptimizerStrategyFactory.hpp
MemoryOptimizerStrategyLibrary.cpp
MemoryOptimizerStrategyLibrary.hpp
+ MemoryManager.cpp
+ MemoryManager.hpp
MemSyncWorkload.cpp
MemSyncWorkload.hpp
OptimizationViews.cpp
OptimizationViews.hpp
+ TensorHandle.cpp
+ TensorHandle.hpp
TensorHandleFactoryRegistry.cpp
TensorHandleFactoryRegistry.hpp
UnmapWorkload.cpp
diff --git a/src/backends/backendsCommon/MemoryManager.cpp b/src/backends/backendsCommon/MemoryManager.cpp
new file mode 100644
index 0000000000..1c109c3c91
--- /dev/null
+++ b/src/backends/backendsCommon/MemoryManager.cpp
@@ -0,0 +1,53 @@
+//
+// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "MemoryManager.hpp"
+
+#include <armnn/utility/IgnoreUnused.hpp>
+
+namespace armnn
+{
+
+void MemoryManager::StoreMemToAllocate(std::vector<BufferStorage> bufferStorageVector,
+ ICustomAllocator* customAllocator,
+ const size_t typeAlignment)
+{
+ IgnoreUnused(typeAlignment);
+ m_AllocatorBufferStoragePairVector.emplace_back(std::make_pair<Allocator, std::vector<BufferStorage>>(
+ Allocator{customAllocator},
+ std::move(bufferStorageVector)));
+}
+
+void MemoryManager::Allocate()
+{
+ for (auto& m_AllocatorBufferStoragePair : m_AllocatorBufferStoragePairVector)
+ {
+ auto& allocator = m_AllocatorBufferStoragePair.first;
+ for (auto&& bufferStorage : m_AllocatorBufferStoragePair.second)
+ {
+ bufferStorage.m_Buffer = allocator.m_CustomAllocator->allocate(bufferStorage.m_BufferSize, 0);
+
+ for (auto tensorMemory : bufferStorage.m_TensorMemoryVector)
+ {
+ tensorMemory->m_Data = allocator.m_CustomAllocator->GetMemoryRegionAtOffset(bufferStorage.m_Buffer,
+ tensorMemory->m_Offset);
+ }
+ }
+ }
+}
+
+void MemoryManager::Deallocate()
+{
+ for (auto& m_AllocatorBufferStoragePair : m_AllocatorBufferStoragePairVector)
+ {
+ auto& allocator = m_AllocatorBufferStoragePair.first;
+ for (auto&& bufferStorage : m_AllocatorBufferStoragePair.second)
+ {
+ allocator.m_CustomAllocator->free(bufferStorage.m_Buffer);
+ }
+ }
+}
+
+} // namespace armnn \ No newline at end of file
diff --git a/src/backends/backendsCommon/MemoryManager.hpp b/src/backends/backendsCommon/MemoryManager.hpp
new file mode 100644
index 0000000000..cbd6fcf9bc
--- /dev/null
+++ b/src/backends/backendsCommon/MemoryManager.hpp
@@ -0,0 +1,60 @@
+//
+// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <armnn/backends/ICustomAllocator.hpp>
+
+namespace armnn
+{
+struct Allocator
+{
+ /// Pointer to @ICustomAllocator.
+ ICustomAllocator* m_CustomAllocator{};
+ /// Value which the size of each buffer (actual data size + padding) has to be a multiple of.
+ size_t m_Alignment = 0 ;
+};
+
+struct TensorMemory
+{
+ /// Number of bytes the value is away from the @BufferStorage.m_Buffer.
+ size_t m_Offset{};
+ /// Pointer to the tensor value.
+ void* m_Data = nullptr;
+ /// Identifier to be used by the @LoadedNetwork to order the tensors.
+ unsigned int m_OutputSlotId{};
+};
+
+struct BufferStorage
+{
+ /// Vector of pointer to @TensorMemory.
+ std::vector<TensorMemory*> m_TensorMemoryVector;
+ /// Total size of the buffer.
+ size_t m_BufferSize;
+ /// Pointer to the first element of the buffer.
+ void* m_Buffer = nullptr;
+};
+
+class MemoryManager
+{
+public:
+ /// Initialization method to store in @m_AllocatorBufferStoragePairVector all information needed.
+ /// @param[in] bufferStorageVector - Vector of @BufferStorage.
+ /// @param[in] customAllocator - Pointer to @ICustomAllocator.
+ /// @param[in] typeAlignment - Optional parameter. Value of which the size of each value has to be multiple of.
+ void StoreMemToAllocate(std::vector<BufferStorage> bufferStorageVector,
+ ICustomAllocator* customAllocator,
+ size_t typeAlignment = 0);
+
+ /// Allocate the amount of memory indicated by @m_BufferSize, and
+ /// point each @m_Data to each correspondent Tensor so that they are @m_Offset bytes separated.
+ void Allocate();
+
+ /// Deallocate memory
+ void Deallocate();
+
+private:
+ std::vector<std::pair<Allocator, std::vector<BufferStorage>>> m_AllocatorBufferStoragePairVector;
+};
+
+} // namespace armnn
diff --git a/src/backends/backendsCommon/test/CMakeLists.txt b/src/backends/backendsCommon/test/CMakeLists.txt
index b90407fd7c..9272ae749c 100644
--- a/src/backends/backendsCommon/test/CMakeLists.txt
+++ b/src/backends/backendsCommon/test/CMakeLists.txt
@@ -13,6 +13,7 @@ list(APPEND armnnBackendsCommonUnitTests_sources
ChannelShuffleEndToEndTestImpl.hpp
ComparisonEndToEndTestImpl.hpp
CompatibilityTests.cpp
+ ConcatEndToEndTestImpl.hpp
Convolution3dEndToEndTestImpl.hpp
CustomMemoryOptimizerStrategyTests.cpp
DefaultAsyncExecuteTest.cpp
@@ -35,7 +36,7 @@ list(APPEND armnnBackendsCommonUnitTests_sources
LayerTests.hpp
LogSoftmaxEndToEndTestImpl.cpp
LogSoftmaxEndToEndTestImpl.hpp
- ConcatEndToEndTestImpl.hpp
+ MemoryManagerTests.cpp
MockBackend.cpp
MockBackend.hpp
MockBackendId.hpp
diff --git a/src/backends/backendsCommon/test/MemoryManagerTests.cpp b/src/backends/backendsCommon/test/MemoryManagerTests.cpp
new file mode 100644
index 0000000000..b5f2db4009
--- /dev/null
+++ b/src/backends/backendsCommon/test/MemoryManagerTests.cpp
@@ -0,0 +1,107 @@
+//
+// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <backendsCommon/MemoryManager.hpp>
+#include <armnn/utility/IgnoreUnused.hpp>
+
+#include <doctest/doctest.h>
+#include <numeric>
+
+namespace armnn
+{
+/// @brief Class that implements a sample custom allocator.
+class SampleCustomAllocator : public armnn::ICustomAllocator
+{
+public:
+ SampleCustomAllocator() = default;
+
+ void* allocate(size_t size, size_t alignment) override
+ {
+ IgnoreUnused(alignment);
+ CHECK(size == m_Values.size());
+ m_CounterAllocate+=1;
+ return m_Values.data();
+ }
+
+ void free(void* ptr) override
+ {
+ CHECK(ptr == m_Values.data());
+ m_CounterFree+=1;
+ }
+
+ armnn::MemorySource GetMemorySourceType() override
+ {
+ return armnn::MemorySource::Malloc;
+ }
+
+ virtual void* GetMemoryRegionAtOffset(void* buffer, size_t offset, size_t alignment = 0 ) override
+ {
+ IgnoreUnused(alignment);
+ return (static_cast<char*>(buffer) + offset);
+ }
+
+ /// Holds the data in the tensors. Create for testing purposes.
+ std::vector<uint8_t> m_Values;
+ /// Counts the number of times the function allocate is called.
+ unsigned long m_CounterAllocate= 0;
+ /// Counts the number of times the function free is called.
+ unsigned long m_CounterFree = 0;
+};
+
+TEST_SUITE("MemoryManagerTests")
+{
+/// Unit test Storing, Allocating and Deallocating with a custom allocator.
+TEST_CASE("MemoryManagerTest")
+{
+ using namespace armnn;
+
+ // Create mock up bufferStorageVector with 2 BufferStorage with the same TensorMemory
+ size_t numTensors = 5;
+ std::vector<TensorMemory*> tensorMemoryPointerVector(numTensors);
+ std::vector<TensorMemory> tensorMemoryVector;
+ tensorMemoryVector.reserve(numTensors);
+
+ std::vector<size_t> offsets(numTensors);
+ std::iota(std::begin(offsets), std::end(offsets), 0);
+
+ for (uint idx = 0; idx < tensorMemoryPointerVector.size(); ++idx)
+ {
+ tensorMemoryVector.emplace_back(TensorMemory{offsets[idx], nullptr, 0});
+ tensorMemoryPointerVector[idx] = &tensorMemoryVector[idx];
+ }
+
+ std::vector<BufferStorage> bufferStorageVector;
+ bufferStorageVector.emplace_back(BufferStorage{tensorMemoryPointerVector, numTensors});
+ bufferStorageVector.emplace_back(BufferStorage{tensorMemoryPointerVector, numTensors});
+
+ // Create an instance of the SampleCustomAllocator
+ SampleCustomAllocator customAllocator = SampleCustomAllocator();
+ customAllocator.m_Values = {10, 11, 12, 13, 14};
+ // Check that the test was set up correctly
+ CHECK(customAllocator.m_Values.size() == numTensors);
+
+ // Utilise 3 functions in the MemoryManager. Check the counters and the pointer to the values are correct.
+ MemoryManager memoryManager;
+ memoryManager.StoreMemToAllocate(bufferStorageVector, &customAllocator);
+
+ memoryManager.Allocate();
+ CHECK(customAllocator.m_CounterAllocate == bufferStorageVector.size());
+ for (const auto& bufferStorage : bufferStorageVector)
+ {
+ uint idx = 0;
+ for (auto tensorMemory : bufferStorage.m_TensorMemoryVector)
+ {
+ auto value = reinterpret_cast<uint8_t *>(tensorMemory->m_Data);
+ CHECK(customAllocator.m_Values[idx] == *value);
+ idx += 1;
+ }
+ }
+
+ memoryManager.Deallocate();
+ CHECK(customAllocator.m_CounterFree == bufferStorageVector.size());
+}
+}
+
+} // namespace armnn \ No newline at end of file