IVGCVSW-6470 Create MemoryStrategyBenchmark
* Refactor the strategy library to be more generic
* Shorten the names of the current strategies
* Change validatorStrat to throw exceptions
Change-Id: I0d9c9ef609b2d8675e5788610d1accac6767c660
Signed-off-by: Finn Williams <finwil01@e127804.cambridge.arm.com>
Signed-off-by: Jim Flynn <jim.flynn@arm.com>
diff --git a/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/ConstantMemoryStrategy.cpp b/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/ConstantMemoryStrategy.cpp
new file mode 100644
index 0000000..55f7f89
--- /dev/null
+++ b/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/ConstantMemoryStrategy.cpp
@@ -0,0 +1,43 @@
+//
+// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ConstantMemoryStrategy.hpp"
+
+namespace armnn
+{
+
+std::string ConstantMemoryStrategy::GetName() const
+{
+ return m_Name;
+}
+
+MemBlockStrategyType ConstantMemoryStrategy::GetMemBlockStrategyType() const
+{
+ return m_MemBlockStrategyType;
+}
+
+// A IMemoryOptimizerStrategy must ensure that
+// 1: All MemBlocks have been assigned to a MemBin
+// 2: No MemBlock is assigned to multiple MemBins
+// 3: No two Memblocks in a MemBin overlap in both the X and Y axis
+std::vector<MemBin> ConstantMemoryStrategy::Optimize(std::vector<MemBlock>& memBlocks)
+{
+ std::vector<MemBin> memBins;
+ memBins.reserve(memBlocks.size());
+
+ for (auto& memBlock : memBlocks)
+ {
+ MemBin memBin;
+ memBin.m_MemSize = memBlock.m_MemSize;
+ memBin.m_MemBlocks.reserve(1);
+ memBlock.m_Offset = 0;
+ memBin.m_MemBlocks.push_back(memBlock);
+ memBins.push_back(memBin);
+ }
+
+ return memBins;
+}
+
+} // namespace armnn
\ No newline at end of file
diff --git a/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/ConstantMemoryStrategy.hpp b/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/ConstantMemoryStrategy.hpp
new file mode 100644
index 0000000..249c133
--- /dev/null
+++ b/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/ConstantMemoryStrategy.hpp
@@ -0,0 +1,31 @@
+//
+// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <armnn/Types.hpp>
+#include <armnn/backends/IMemoryOptimizerStrategy.hpp>
+
+namespace armnn
+{
+// ConstLayerMemoryOptimizer: Create a unique MemBin for each MemBlock and assign it an offset of 0
+class ConstantMemoryStrategy : public IMemoryOptimizerStrategy
+{
+public:
+ ConstantMemoryStrategy()
+ : m_Name(std::string("ConstantMemoryStrategy"))
+ , m_MemBlockStrategyType(MemBlockStrategyType::SingleAxisPacking) {}
+
+ std::string GetName() const override;
+
+ MemBlockStrategyType GetMemBlockStrategyType() const override;
+
+ std::vector<MemBin> Optimize(std::vector<MemBlock>& memBlocks) override;
+
+private:
+ std::string m_Name;
+ MemBlockStrategyType m_MemBlockStrategyType;
+};
+
+} // namespace armnn
\ No newline at end of file
diff --git a/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/StrategyValidator.cpp b/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/StrategyValidator.cpp
new file mode 100644
index 0000000..48cdfb0
--- /dev/null
+++ b/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/StrategyValidator.cpp
@@ -0,0 +1,132 @@
+//
+// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include <unordered_map>
+#include <iostream>
+#include "StrategyValidator.hpp"
+
+namespace armnn
+{
+
+std::vector<MemBin> StrategyValidator::Optimize(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
+
+ std::unordered_map<unsigned int, bool> validationMap;
+
+ for (auto memBlock : memBlocks)
+ {
+ validationMap[memBlock.m_Index] = false;
+ }
+
+ 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 memBin : memBinVect)
+ {
+ for (auto block : memBin.m_MemBlocks)
+ {
+ try
+ {
+ if (!validationMap.at(block.m_Index))
+ {
+ validationMap.at(block.m_Index) = true;
+ }
+ else
+ {
+ throw MemoryValidationException("Condition #2: Memblock is assigned to multiple MemBins");
+ }
+ }
+ catch (const std::out_of_range&)
+ {
+ throw MemoryValidationException("Unknown index ");
+ }
+ }
+ }
+
+ for (auto memBlock : memBlocks)
+ {
+ if (!validationMap.at(memBlock.m_Index))
+ {
+ throw MemoryValidationException("Condition #1: Block not found in any bin");
+ }
+ }
+
+ // 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
+ throw MemoryValidationException("Condition #3: two Memblocks overlap on both the X and Y axis");
+ }
+
+ 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))
+ {
+ throw MemoryValidationException("Condition #3: "
+ "invalid as two Memblocks overlap on the Y axis for SingleAxisPacking");
+
+ }
+ break;
+ }
+ case (MemBlockStrategyType::MultiAxisPacking):
+ {
+ break;
+ }
+ default:
+ throw MemoryValidationException("Unknown MemBlockStrategyType");
+ }
+ }
+ }
+ }
+
+ // None of the conditions broken so return true
+ return memBinVect;
+}
+
+} // namespace armnn
\ No newline at end of file
diff --git a/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/StrategyValidator.hpp b/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/StrategyValidator.hpp
new file mode 100644
index 0000000..e1f9111
--- /dev/null
+++ b/src/backends/backendsCommon/memoryOptimizerStrategyLibrary/strategies/StrategyValidator.hpp
@@ -0,0 +1,41 @@
+//
+// Copyright © 2021 Arm Ltd and Contributors. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+#pragma once
+
+#include <armnn/Types.hpp>
+#include <armnn/Exceptions.hpp>
+#include <armnn/backends/IMemoryOptimizerStrategy.hpp>
+
+namespace armnn
+{
+
+class StrategyValidator : public IMemoryOptimizerStrategy
+{
+public:
+
+ void SetStrategy(std::shared_ptr<IMemoryOptimizerStrategy> strategy)
+ {
+ m_Strategy = strategy;
+ m_MemBlockStrategyType = strategy->GetMemBlockStrategyType();
+ }
+
+ std::string GetName() const override
+ {
+ return "StrategyValidator";
+ }
+
+ MemBlockStrategyType GetMemBlockStrategyType() const override
+ {
+ return m_MemBlockStrategyType;
+ }
+
+ std::vector<MemBin> Optimize(std::vector<MemBlock>& memBlocks) override;
+
+private:
+ std::shared_ptr<IMemoryOptimizerStrategy> m_Strategy;
+ MemBlockStrategyType m_MemBlockStrategyType;
+};
+
+} // namespace armnn
\ No newline at end of file