aboutsummaryrefslogtreecommitdiff
path: root/src/backends/backendsCommon/test/MemoryManagerTests.cpp
blob: c873499ef3b2e4a692e0fb2e06c16fa839a3b2e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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 (uint32_t 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)
    {
        uint32_t 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