aboutsummaryrefslogtreecommitdiff
path: root/src/backends/backendsCommon/memoryOptimizationStrategies/MemoryOptimizerStrategyValidator.cpp
blob: 876ad90cd454e20a3150c79b9dbb410b351b16a4 (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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//
// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
// SPDX-License-Identifier: MIT
//

#include <backendsCommon/memoryOptimizationStrategies/MemoryOptimizerStrategyValidator.hpp>

namespace armnn
{

bool MemoryOptimizerValidator::Validate(std::vector<MemBlock>& memBlocks)
{
    // Condition #1: All Memblocks have been assigned to a MemBin

    // Condition #2: No Memblock is assigned to multiple MemBins

    // Condition #3: No two Memblocks in a MemBin overlap in both the X and Y axis
    //               Memblocks in a MemBin can overlap on the X axis for SingleAxisPacking
    //               Memblocks in a MemBin can overlap on the Y axis or the X for MultiAxisPacking but not both

    auto memBinVect = m_Strategy->Optimize(memBlocks);

    // Compare each of the input memblocks against every assignedBlock in each bin
    // if we get through all bins without finding a block return
    // if at any stage the block is found twice return

    for (auto memBlock : memBlocks)
    {
        auto found = false;

        for (auto bin : memBinVect)
        {
            for (auto assignedBlock : bin.m_MemBlocks)
            {
                if (memBlock.m_Index == assignedBlock.m_Index)
                {
                    if (found)
                    {
                        // Condition #2: Memblock is assigned to multiple MemBins
                        return false;
                    }

                    found = true;
                }
            }
        }
        // Condition #1: Block not found in any bin so return false as strategy is invalid
        if (!found)
        {
            return false;
        }
    }

    // Check for overlaps once we know blocks are all assigned and no duplicates
    for (auto bin : memBinVect)
    {
        for (unsigned int i = 0; i < bin.m_MemBlocks.size(); ++i)
        {
            auto assignedBlock = bin.m_MemBlocks[i];
            auto xStart = assignedBlock.m_Offset;
            auto xEnd = assignedBlock.m_Offset + assignedBlock.m_MemSize;

            auto yStart = assignedBlock.m_StartOfLife;
            auto yEnd = assignedBlock.m_EndOfLife;
            auto assignedIndex = assignedBlock.m_Index;

            // Only compare with blocks after the current one as previous have already been checked
            for (unsigned int j = i + 1; j < bin.m_MemBlocks.size(); ++j)
            {
                auto otherAssignedBlock = bin.m_MemBlocks[j];
                auto xStartAssigned = otherAssignedBlock.m_Offset;
                auto xEndAssigned = otherAssignedBlock.m_Offset + otherAssignedBlock.m_MemSize;

                auto yStartAssigned = otherAssignedBlock.m_StartOfLife;
                auto yEndAssigned = otherAssignedBlock.m_EndOfLife;
                auto otherIndex = otherAssignedBlock.m_Index;

                // If overlapping on both X and Y then invalid
                // Inside left of rectangle & Inside right of rectangle
                if ((((xStart >= xStartAssigned) && (xEnd <= xEndAssigned)) &&
                     // Inside bottom of rectangle & Inside top of rectangle
                     ((yStart >= yStartAssigned) && (yEnd <= yEndAssigned))) &&
                     // Cant overlap with itself
                     (assignedIndex != otherIndex))
                {
                    // Condition #3: two Memblocks overlap on both the X and Y axis
                    return false;
                }

                switch (m_Strategy->GetMemBlockStrategyType())
                {
                    case (MemBlockStrategyType::SingleAxisPacking):
                    {
                        // Inside bottom of rectangle  & Inside top of rectangle
                        if (((yStart >= yStartAssigned) && (yEnd <= yEndAssigned)) &&
                            // Cant overlap with itself
                            (assignedIndex != otherIndex))
                        {
                            // Condition #3: invalid as two Memblocks overlap on the Y axis for SingleAxisPacking
                            return false;
                        }
                        break;
                    }
                    case (MemBlockStrategyType::MultiAxisPacking):
                    {
                        break;
                    }
                    default:
                        // Unknown MemBlockStrategyType
                        return false;
                }
            }

        }
    }

    // None of the conditions broken so return true
    return true;
}

} // namespace armnn