blob: 48cdfb040c25ca926a36d9c8c7a244129ec4d490 [file] [log] [blame]
Francis Murtaghca49a242021-09-28 15:30:31 +01001//
2// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
Jim Flynne1fdd282021-10-26 21:26:10 +01006#include <unordered_map>
7#include <iostream>
8#include "StrategyValidator.hpp"
Francis Murtaghca49a242021-09-28 15:30:31 +01009
10namespace armnn
11{
12
Jim Flynne1fdd282021-10-26 21:26:10 +010013std::vector<MemBin> StrategyValidator::Optimize(std::vector<MemBlock>& memBlocks)
Francis Murtaghca49a242021-09-28 15:30:31 +010014{
15 // Condition #1: All Memblocks have been assigned to a MemBin
16
17 // Condition #2: No Memblock is assigned to multiple MemBins
18
19 // Condition #3: No two Memblocks in a MemBin overlap in both the X and Y axis
20 // Memblocks in a MemBin can overlap on the X axis for SingleAxisPacking
21 // Memblocks in a MemBin can overlap on the Y axis or the X for MultiAxisPacking but not both
22
Jim Flynne1fdd282021-10-26 21:26:10 +010023 std::unordered_map<unsigned int, bool> validationMap;
24
25 for (auto memBlock : memBlocks)
26 {
27 validationMap[memBlock.m_Index] = false;
28 }
29
Francis Murtaghca49a242021-09-28 15:30:31 +010030 auto memBinVect = m_Strategy->Optimize(memBlocks);
31
32 // Compare each of the input memblocks against every assignedBlock in each bin
33 // if we get through all bins without finding a block return
34 // if at any stage the block is found twice return
35
Jim Flynne1fdd282021-10-26 21:26:10 +010036 for (auto memBin : memBinVect)
Francis Murtaghca49a242021-09-28 15:30:31 +010037 {
Jim Flynne1fdd282021-10-26 21:26:10 +010038 for (auto block : memBin.m_MemBlocks)
Francis Murtaghca49a242021-09-28 15:30:31 +010039 {
Jim Flynne1fdd282021-10-26 21:26:10 +010040 try
Francis Murtaghca49a242021-09-28 15:30:31 +010041 {
Jim Flynne1fdd282021-10-26 21:26:10 +010042 if (!validationMap.at(block.m_Index))
Francis Murtaghca49a242021-09-28 15:30:31 +010043 {
Jim Flynne1fdd282021-10-26 21:26:10 +010044 validationMap.at(block.m_Index) = true;
45 }
46 else
47 {
48 throw MemoryValidationException("Condition #2: Memblock is assigned to multiple MemBins");
Francis Murtaghca49a242021-09-28 15:30:31 +010049 }
50 }
Jim Flynne1fdd282021-10-26 21:26:10 +010051 catch (const std::out_of_range&)
52 {
53 throw MemoryValidationException("Unknown index ");
54 }
Francis Murtaghca49a242021-09-28 15:30:31 +010055 }
Jim Flynne1fdd282021-10-26 21:26:10 +010056 }
57
58 for (auto memBlock : memBlocks)
59 {
60 if (!validationMap.at(memBlock.m_Index))
Francis Murtaghca49a242021-09-28 15:30:31 +010061 {
Jim Flynne1fdd282021-10-26 21:26:10 +010062 throw MemoryValidationException("Condition #1: Block not found in any bin");
Francis Murtaghca49a242021-09-28 15:30:31 +010063 }
64 }
65
66 // Check for overlaps once we know blocks are all assigned and no duplicates
67 for (auto bin : memBinVect)
68 {
69 for (unsigned int i = 0; i < bin.m_MemBlocks.size(); ++i)
70 {
71 auto assignedBlock = bin.m_MemBlocks[i];
72 auto xStart = assignedBlock.m_Offset;
73 auto xEnd = assignedBlock.m_Offset + assignedBlock.m_MemSize;
74
75 auto yStart = assignedBlock.m_StartOfLife;
76 auto yEnd = assignedBlock.m_EndOfLife;
77 auto assignedIndex = assignedBlock.m_Index;
78
79 // Only compare with blocks after the current one as previous have already been checked
80 for (unsigned int j = i + 1; j < bin.m_MemBlocks.size(); ++j)
81 {
82 auto otherAssignedBlock = bin.m_MemBlocks[j];
83 auto xStartAssigned = otherAssignedBlock.m_Offset;
84 auto xEndAssigned = otherAssignedBlock.m_Offset + otherAssignedBlock.m_MemSize;
85
86 auto yStartAssigned = otherAssignedBlock.m_StartOfLife;
87 auto yEndAssigned = otherAssignedBlock.m_EndOfLife;
88 auto otherIndex = otherAssignedBlock.m_Index;
89
90 // If overlapping on both X and Y then invalid
91 // Inside left of rectangle & Inside right of rectangle
92 if ((((xStart >= xStartAssigned) && (xEnd <= xEndAssigned)) &&
93 // Inside bottom of rectangle & Inside top of rectangle
94 ((yStart >= yStartAssigned) && (yEnd <= yEndAssigned))) &&
95 // Cant overlap with itself
96 (assignedIndex != otherIndex))
97 {
98 // Condition #3: two Memblocks overlap on both the X and Y axis
Jim Flynne1fdd282021-10-26 21:26:10 +010099 throw MemoryValidationException("Condition #3: two Memblocks overlap on both the X and Y axis");
Francis Murtaghca49a242021-09-28 15:30:31 +0100100 }
101
102 switch (m_Strategy->GetMemBlockStrategyType())
103 {
104 case (MemBlockStrategyType::SingleAxisPacking):
105 {
106 // Inside bottom of rectangle & Inside top of rectangle
107 if (((yStart >= yStartAssigned) && (yEnd <= yEndAssigned)) &&
108 // Cant overlap with itself
109 (assignedIndex != otherIndex))
110 {
Jim Flynne1fdd282021-10-26 21:26:10 +0100111 throw MemoryValidationException("Condition #3: "
112 "invalid as two Memblocks overlap on the Y axis for SingleAxisPacking");
113
Francis Murtaghca49a242021-09-28 15:30:31 +0100114 }
115 break;
116 }
117 case (MemBlockStrategyType::MultiAxisPacking):
118 {
119 break;
120 }
121 default:
Jim Flynne1fdd282021-10-26 21:26:10 +0100122 throw MemoryValidationException("Unknown MemBlockStrategyType");
Francis Murtaghca49a242021-09-28 15:30:31 +0100123 }
124 }
Francis Murtaghca49a242021-09-28 15:30:31 +0100125 }
126 }
127
128 // None of the conditions broken so return true
Jim Flynne1fdd282021-10-26 21:26:10 +0100129 return memBinVect;
Francis Murtaghca49a242021-09-28 15:30:31 +0100130}
131
132} // namespace armnn