From ca49a24a2b19e4d8e45efc53e336223c5895f25a Mon Sep 17 00:00:00 2001 From: Francis Murtagh Date: Tue, 28 Sep 2021 15:30:31 +0100 Subject: IVGCVSW-6338 IMemoryOptimizerStrategy Create a wrapper validator strategy * Add validator wrapper * Add validation logic: Condition #1: All Memblocks have been assigned to a MemBin Condition #2: No Memblock is assigned to multiple MemBins Condition #3: No two Memblocks overlap in both the X and Y axis Memblocks can overlap on the X axis for SingleAxisPacking Memblocks can overlap on the Y axis or the X for MultiAxisPacking but not both * Add test strategies and tests for overlap, duplicates and unassigned blocks Signed-off-by: Francis Murtagh Change-Id: I7a779b35538ecf18a33b62b84512eba69eda1f86 --- include/armnn/Types.hpp | 4 +- .../armnn/backends/IMemoryOptimizerStrategy.hpp | 6 +- src/backends/backendsCommon/common.mk | 6 +- .../memoryOptimizationStrategies/CMakeLists.txt | 2 + .../ConstLayerMemoryOptimizerStrategy.cpp | 2 +- .../MemoryOptimizerStrategyValidator.cpp | 121 +++++++++ .../MemoryOptimizerStrategyValidator.hpp | 27 ++ .../test/CMakeLists.txt | 1 + .../ConstLayerMemoryOptimizerStrategyTests.cpp | 26 ++ .../test/MemoryOptimizerStrategyValidatorTests.cpp | 273 +++++++++++++++++++++ 10 files changed, 460 insertions(+), 8 deletions(-) create mode 100644 src/backends/backendsCommon/memoryOptimizationStrategies/MemoryOptimizerStrategyValidator.cpp create mode 100644 src/backends/backendsCommon/memoryOptimizationStrategies/MemoryOptimizerStrategyValidator.hpp create mode 100644 src/backends/backendsCommon/memoryOptimizationStrategies/test/MemoryOptimizerStrategyValidatorTests.cpp diff --git a/include/armnn/Types.hpp b/include/armnn/Types.hpp index e713b8989e..02f265c6e3 100644 --- a/include/armnn/Types.hpp +++ b/include/armnn/Types.hpp @@ -212,12 +212,12 @@ enum class MemorySource : uint32_t enum class MemBlockStrategyType { - // MemBlocks can be packed on the Y axis only. + // MemBlocks can be packed on the Y axis only, overlap allowed on X axis. // In other words MemBlocks with overlapping lifetimes cannot use the same MemBin, // equivalent to blob or pooling memory management. SingleAxisPacking = 0, - // MemBlocks can be packed on the Y and X axis. + // MemBlocks can be packed on either Y or X axis but cannot overlap on both. // In other words MemBlocks with overlapping lifetimes can use the same MemBin, // equivalent to offset or slab memory management. MultiAxisPacking = 1 diff --git a/include/armnn/backends/IMemoryOptimizerStrategy.hpp b/include/armnn/backends/IMemoryOptimizerStrategy.hpp index ec6d838aae..ad5513f8a3 100644 --- a/include/armnn/backends/IMemoryOptimizerStrategy.hpp +++ b/include/armnn/backends/IMemoryOptimizerStrategy.hpp @@ -22,8 +22,8 @@ struct MemBlock const unsigned int m_StartOfLife; // Y start const unsigned int m_EndOfLife; // Y end - const size_t m_MemSize; // X start - size_t m_Offset; // X end + const size_t m_MemSize; // Offset + Memsize = X end + size_t m_Offset; // X start const unsigned int m_Index; // Index to keep order }; @@ -40,7 +40,7 @@ struct MemBin // 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 the X dimension +// 3: No two Memblocks in a MemBin overlap in both the X and Y axis // (a strategy cannot change the y axis or length of a MemBlock) class IMemoryOptimizerStrategy { diff --git a/src/backends/backendsCommon/common.mk b/src/backends/backendsCommon/common.mk index 2795c9cc2f..910f9a4210 100644 --- a/src/backends/backendsCommon/common.mk +++ b/src/backends/backendsCommon/common.mk @@ -25,7 +25,8 @@ COMMON_SOURCES := \ WorkloadData.cpp \ WorkloadFactory.cpp \ WorkloadUtils.cpp \ - memoryOptimizationStrategies/ConstLayerMemoryOptimizerStrategy.cpp + memoryOptimizationStrategies/ConstLayerMemoryOptimizerStrategy.cpp \ + memoryOptimizationStrategies/MemoryOptimizerStrategyValidator.cpp # COMMON_TEST_SOURCES contains the list of files to be included # in the Android unit test build (armnn-tests) and it is picked @@ -101,7 +102,8 @@ COMMON_TEST_SOURCES := \ test/layerTests/SubtractionTestImpl.cpp \ test/layerTests/TransposeConvolution2dTestImpl.cpp \ test/layerTests/UnidirectionalSequenceLstmTestImpl.cpp \ - memoryOptimizationStrategies/test/ConstLayerMemoryOptimizerStrategyTests.cpp + memoryOptimizationStrategies/test/ConstLayerMemoryOptimizerStrategyTests.cpp \ + memoryOptimizationStrategies/test/MemoryOptimizerStrategyValidatorTests.cpp ifeq ($(ARMNN_REF_ENABLED),1) COMMON_TEST_SOURCES += \ diff --git a/src/backends/backendsCommon/memoryOptimizationStrategies/CMakeLists.txt b/src/backends/backendsCommon/memoryOptimizationStrategies/CMakeLists.txt index 6f3708beaa..de83505f7c 100644 --- a/src/backends/backendsCommon/memoryOptimizationStrategies/CMakeLists.txt +++ b/src/backends/backendsCommon/memoryOptimizationStrategies/CMakeLists.txt @@ -6,6 +6,8 @@ list(APPEND armnnMemoryOptimizationStrategies_sources ConstLayerMemoryOptimizerStrategy.hpp ConstLayerMemoryOptimizerStrategy.cpp + MemoryOptimizerStrategyValidator.hpp + MemoryOptimizerStrategyValidator.cpp ) if(BUILD_UNIT_TESTS) diff --git a/src/backends/backendsCommon/memoryOptimizationStrategies/ConstLayerMemoryOptimizerStrategy.cpp b/src/backends/backendsCommon/memoryOptimizationStrategies/ConstLayerMemoryOptimizerStrategy.cpp index 8abf32c096..023c6361d0 100644 --- a/src/backends/backendsCommon/memoryOptimizationStrategies/ConstLayerMemoryOptimizerStrategy.cpp +++ b/src/backends/backendsCommon/memoryOptimizationStrategies/ConstLayerMemoryOptimizerStrategy.cpp @@ -21,7 +21,7 @@ MemBlockStrategyType ConstLayerMemoryOptimizerStrategy::GetMemBlockStrategyType( // 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 the X dimension +// 3: No two Memblocks in a MemBin overlap in both the X and Y axis std::vector ConstLayerMemoryOptimizerStrategy::Optimize(std::vector& memBlocks) { std::vector memBins; diff --git a/src/backends/backendsCommon/memoryOptimizationStrategies/MemoryOptimizerStrategyValidator.cpp b/src/backends/backendsCommon/memoryOptimizationStrategies/MemoryOptimizerStrategyValidator.cpp new file mode 100644 index 0000000000..876ad90cd4 --- /dev/null +++ b/src/backends/backendsCommon/memoryOptimizationStrategies/MemoryOptimizerStrategyValidator.cpp @@ -0,0 +1,121 @@ +// +// Copyright © 2021 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include + +namespace armnn +{ + +bool MemoryOptimizerValidator::Validate(std::vector& 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 \ No newline at end of file diff --git a/src/backends/backendsCommon/memoryOptimizationStrategies/MemoryOptimizerStrategyValidator.hpp b/src/backends/backendsCommon/memoryOptimizationStrategies/MemoryOptimizerStrategyValidator.hpp new file mode 100644 index 0000000000..13e90593d8 --- /dev/null +++ b/src/backends/backendsCommon/memoryOptimizationStrategies/MemoryOptimizerStrategyValidator.hpp @@ -0,0 +1,27 @@ +// +// Copyright © 2021 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// +#pragma once + +#include +#include + +namespace armnn +{ + +class MemoryOptimizerValidator +{ +public: + explicit MemoryOptimizerValidator(std::shared_ptr strategy) + : m_Strategy(strategy) + { + }; + + bool Validate(std::vector& memBlocks); + +private: + std::shared_ptr m_Strategy; +}; + +} // namespace armnn \ No newline at end of file diff --git a/src/backends/backendsCommon/memoryOptimizationStrategies/test/CMakeLists.txt b/src/backends/backendsCommon/memoryOptimizationStrategies/test/CMakeLists.txt index 5b2489d2e9..1e16f09411 100644 --- a/src/backends/backendsCommon/memoryOptimizationStrategies/test/CMakeLists.txt +++ b/src/backends/backendsCommon/memoryOptimizationStrategies/test/CMakeLists.txt @@ -5,6 +5,7 @@ list(APPEND armnnMemoryOptimizationStrategiesUnitTests_sources ConstLayerMemoryOptimizerStrategyTests.cpp + MemoryOptimizerStrategyValidatorTests.cpp ) add_library(armnnMemoryOptimizationStrategiesUnitTests OBJECT ${armnnMemoryOptimizationStrategiesUnitTests_sources}) diff --git a/src/backends/backendsCommon/memoryOptimizationStrategies/test/ConstLayerMemoryOptimizerStrategyTests.cpp b/src/backends/backendsCommon/memoryOptimizationStrategies/test/ConstLayerMemoryOptimizerStrategyTests.cpp index 95569dcc0a..cfa2d40e7d 100644 --- a/src/backends/backendsCommon/memoryOptimizationStrategies/test/ConstLayerMemoryOptimizerStrategyTests.cpp +++ b/src/backends/backendsCommon/memoryOptimizationStrategies/test/ConstLayerMemoryOptimizerStrategyTests.cpp @@ -4,6 +4,7 @@ // #include +#include #include #include @@ -48,4 +49,29 @@ TEST_CASE("ConstLayerMemoryOptimizerStrategyTest") CHECK(memBins[4].m_MemBlocks[0].m_Index == 4); } +TEST_CASE("ConstLayerMemoryOptimizerStrategyValidatorTest") +{ + // create a few memory blocks + MemBlock memBlock0(0, 2, 20, 0, 0); + MemBlock memBlock1(2, 3, 10, 20, 1); + MemBlock memBlock2(3, 5, 15, 30, 2); + MemBlock memBlock3(5, 6, 20, 50, 3); + MemBlock memBlock4(7, 8, 5, 70, 4); + + std::vector memBlocks; + memBlocks.reserve(5); + memBlocks.push_back(memBlock0); + memBlocks.push_back(memBlock1); + memBlocks.push_back(memBlock2); + memBlocks.push_back(memBlock3); + memBlocks.push_back(memBlock4); + + // Optimize the memory blocks with ConstLayerMemoryOptimizerStrategy + ConstLayerMemoryOptimizerStrategy constLayerMemoryOptimizerStrategy; + auto ptr = std::make_shared(constLayerMemoryOptimizerStrategy); + MemoryOptimizerValidator validator(std::move(ptr)); + // Ensure ConstLayerMemoryOptimizerStrategy is valid + CHECK(validator.Validate(memBlocks)); +} + } diff --git a/src/backends/backendsCommon/memoryOptimizationStrategies/test/MemoryOptimizerStrategyValidatorTests.cpp b/src/backends/backendsCommon/memoryOptimizationStrategies/test/MemoryOptimizerStrategyValidatorTests.cpp new file mode 100644 index 0000000000..af09e4ed56 --- /dev/null +++ b/src/backends/backendsCommon/memoryOptimizationStrategies/test/MemoryOptimizerStrategyValidatorTests.cpp @@ -0,0 +1,273 @@ +// +// Copyright © 2021 Arm Ltd and Contributors. All rights reserved. +// SPDX-License-Identifier: MIT +// + +#include + +#include +#include + +using namespace armnn; + +TEST_SUITE("MemoryOptimizerStrategyValidatorTestSuite") +{ + +// TestMemoryOptimizerStrategy: Create a MemBin and put all blocks in it so the can overlap. +class TestMemoryOptimizerStrategy : public IMemoryOptimizerStrategy +{ +public: + TestMemoryOptimizerStrategy(MemBlockStrategyType type) + : m_Name(std::string("testMemoryOptimizerStrategy")) + , m_MemBlockStrategyType(type) {} + + std::string GetName() const override + { + return m_Name; + } + + MemBlockStrategyType GetMemBlockStrategyType() const override + { + return m_MemBlockStrategyType; + } + + std::vector Optimize(std::vector& memBlocks) override + { + std::vector memBins; + memBins.reserve(memBlocks.size()); + + MemBin memBin; + memBin.m_MemBlocks.reserve(memBlocks.size()); + memBin.m_MemSize = 0; + for (auto& memBlock : memBlocks) + { + + memBin.m_MemSize = memBin.m_MemSize + memBlock.m_MemSize; + memBin.m_MemBlocks.push_back(memBlock); + } + memBins.push_back(memBin); + + return memBins; + } + +private: + std::string m_Name; + MemBlockStrategyType m_MemBlockStrategyType; +}; + +TEST_CASE("MemoryOptimizerStrategyValidatorTestOverlapX") +{ + // create a few memory blocks + MemBlock memBlock0(0, 5, 20, 0, 0); + MemBlock memBlock1(5, 10, 10, 0, 1); + MemBlock memBlock2(10, 15, 15, 0, 2); + MemBlock memBlock3(15, 20, 20, 0, 3); + MemBlock memBlock4(20, 25, 5, 0, 4); + + std::vector memBlocks; + memBlocks.reserve(5); + memBlocks.push_back(memBlock0); + memBlocks.push_back(memBlock1); + memBlocks.push_back(memBlock2); + memBlocks.push_back(memBlock3); + memBlocks.push_back(memBlock4); + + // Optimize the memory blocks with TestMemoryOptimizerStrategySingle + TestMemoryOptimizerStrategy testMemoryOptimizerStrategySingle(MemBlockStrategyType::SingleAxisPacking); + auto ptr = std::make_shared(testMemoryOptimizerStrategySingle); + MemoryOptimizerValidator validator(std::move(ptr)); + // SingleAxisPacking can overlap on X axis. + CHECK(validator.Validate(memBlocks)); + + // Optimize the memory blocks with TestMemoryOptimizerStrategyMulti + TestMemoryOptimizerStrategy testMemoryOptimizerStrategyMulti(MemBlockStrategyType::MultiAxisPacking); + auto ptrMulti = std::make_shared(testMemoryOptimizerStrategyMulti); + MemoryOptimizerValidator validatorMulti(std::move(ptrMulti)); + // MultiAxisPacking can overlap on X axis. + CHECK(validatorMulti.Validate(memBlocks)); +} + +TEST_CASE("MemoryOptimizerStrategyValidatorTestOverlapXAndY") +{ + // create a few memory blocks + MemBlock memBlock0(0, 5, 20, 0, 0); + MemBlock memBlock1(0, 10, 10, 0, 1); + MemBlock memBlock2(0, 15, 15, 0, 2); + MemBlock memBlock3(0, 20, 20, 0, 3); + MemBlock memBlock4(0, 25, 5, 0, 4); + + std::vector memBlocks; + memBlocks.reserve(5); + memBlocks.push_back(memBlock0); + memBlocks.push_back(memBlock1); + memBlocks.push_back(memBlock2); + memBlocks.push_back(memBlock3); + memBlocks.push_back(memBlock4); + + // Optimize the memory blocks with TestMemoryOptimizerStrategySingle + TestMemoryOptimizerStrategy testMemoryOptimizerStrategySingle(MemBlockStrategyType::SingleAxisPacking); + auto ptr = std::make_shared(testMemoryOptimizerStrategySingle); + MemoryOptimizerValidator validator(std::move(ptr)); + // SingleAxisPacking cannot overlap on both X and Y axis. + CHECK(!validator.Validate(memBlocks)); + + // Optimize the memory blocks with TestMemoryOptimizerStrategyMulti + TestMemoryOptimizerStrategy testMemoryOptimizerStrategyMulti(MemBlockStrategyType::MultiAxisPacking); + auto ptrMulti = std::make_shared(testMemoryOptimizerStrategyMulti); + MemoryOptimizerValidator validatorMulti(std::move(ptrMulti)); + // MultiAxisPacking cannot overlap on both X and Y axis. + CHECK(!validatorMulti.Validate(memBlocks)); +} + +TEST_CASE("MemoryOptimizerStrategyValidatorTestOverlapY") +{ + // create a few memory blocks + MemBlock memBlock0(0, 2, 20, 0, 0); + MemBlock memBlock1(0, 3, 10, 20, 1); + MemBlock memBlock2(0, 5, 15, 30, 2); + MemBlock memBlock3(0, 6, 20, 50, 3); + MemBlock memBlock4(0, 8, 5, 70, 4); + + std::vector memBlocks; + memBlocks.reserve(5); + memBlocks.push_back(memBlock0); + memBlocks.push_back(memBlock1); + memBlocks.push_back(memBlock2); + memBlocks.push_back(memBlock3); + memBlocks.push_back(memBlock4); + + // Optimize the memory blocks with TestMemoryOptimizerStrategySingle + TestMemoryOptimizerStrategy testMemoryOptimizerStrategySingle(MemBlockStrategyType::SingleAxisPacking); + auto ptr = std::make_shared(testMemoryOptimizerStrategySingle); + MemoryOptimizerValidator validator(std::move(ptr)); + // SingleAxisPacking cannot overlap on Y axis + CHECK(!validator.Validate(memBlocks)); + + // Optimize the memory blocks with TestMemoryOptimizerStrategyMulti + TestMemoryOptimizerStrategy testMemoryOptimizerStrategyMulti(MemBlockStrategyType::MultiAxisPacking); + auto ptrMulti = std::make_shared(testMemoryOptimizerStrategyMulti); + MemoryOptimizerValidator validatorMulti(std::move(ptrMulti)); + // MultiAxisPacking can overlap on Y axis + CHECK(validatorMulti.Validate(memBlocks)); +} + +// TestMemoryOptimizerStrategyDuplicate: Create a MemBin and put all blocks in it duplicating each so validator +// can check +class TestMemoryOptimizerStrategyDuplicate : public TestMemoryOptimizerStrategy +{ +public: + TestMemoryOptimizerStrategyDuplicate(MemBlockStrategyType type) + : TestMemoryOptimizerStrategy(type) + {} + + std::vector Optimize(std::vector& memBlocks) override + { + std::vector memBins; + memBins.reserve(memBlocks.size()); + + MemBin memBin; + memBin.m_MemBlocks.reserve(memBlocks.size()); + for (auto& memBlock : memBlocks) + { + memBin.m_MemSize = memBin.m_MemSize + memBlock.m_MemSize; + memBin.m_MemBlocks.push_back(memBlock); + // Put block in twice so it gets found twice + memBin.m_MemBlocks.push_back(memBlock); + } + memBins.push_back(memBin); + + return memBins; + } +}; + +TEST_CASE("MemoryOptimizerStrategyValidatorTestDuplicateBlocks") +{ + // create a few memory blocks + MemBlock memBlock0(0, 2, 20, 0, 0); + MemBlock memBlock1(2, 3, 10, 20, 1); + MemBlock memBlock2(3, 5, 15, 30, 2); + MemBlock memBlock3(5, 6, 20, 50, 3); + MemBlock memBlock4(7, 8, 5, 70, 4); + + std::vector memBlocks; + memBlocks.reserve(5); + memBlocks.push_back(memBlock0); + memBlocks.push_back(memBlock1); + memBlocks.push_back(memBlock2); + memBlocks.push_back(memBlock3); + memBlocks.push_back(memBlock4); + + // Optimize the memory blocks with TestMemoryOptimizerStrategySingle + // Duplicate strategy is invalid as same block is found twice + TestMemoryOptimizerStrategyDuplicate testMemoryOptimizerStrategySingle(MemBlockStrategyType::SingleAxisPacking); + auto ptr = std::make_shared(testMemoryOptimizerStrategySingle); + MemoryOptimizerValidator validator(std::move(ptr)); + CHECK(!validator.Validate(memBlocks)); + + // Optimize the memory blocks with TestMemoryOptimizerStrategyMulti + TestMemoryOptimizerStrategyDuplicate testMemoryOptimizerStrategyMulti(MemBlockStrategyType::MultiAxisPacking); + auto ptrMulti = std::make_shared(testMemoryOptimizerStrategyMulti); + MemoryOptimizerValidator validatorMulti(std::move(ptrMulti)); + CHECK(!validatorMulti.Validate(memBlocks)); +} + +// TestMemoryOptimizerStrategySkip: Create a MemBin and put all blocks in it skipping every other block so validator +// can check +class TestMemoryOptimizerStrategySkip : public TestMemoryOptimizerStrategy +{ +public: + TestMemoryOptimizerStrategySkip(MemBlockStrategyType type) + : TestMemoryOptimizerStrategy(type) + {} + + std::vector Optimize(std::vector& memBlocks) override + { + std::vector memBins; + memBins.reserve(memBlocks.size()); + + MemBin memBin; + memBin.m_MemBlocks.reserve(memBlocks.size()); + for (unsigned int i = 0; i < memBlocks.size()-1; i+=2) + { + auto memBlock = memBlocks[i]; + memBin.m_MemSize = memBin.m_MemSize + memBlock.m_MemSize; + memBin.m_MemBlocks.push_back(memBlock); + } + memBins.push_back(memBin); + + return memBins; + } +}; + +TEST_CASE("MemoryOptimizerStrategyValidatorTestSkipBlocks") +{ + // create a few memory blocks + MemBlock memBlock0(0, 2, 20, 0, 0); + MemBlock memBlock1(2, 3, 10, 20, 1); + MemBlock memBlock2(3, 5, 15, 30, 2); + MemBlock memBlock3(5, 6, 20, 50, 3); + MemBlock memBlock4(7, 8, 5, 70, 4); + + std::vector memBlocks; + memBlocks.reserve(5); + memBlocks.push_back(memBlock0); + memBlocks.push_back(memBlock1); + memBlocks.push_back(memBlock2); + memBlocks.push_back(memBlock3); + memBlocks.push_back(memBlock4); + + // Optimize the memory blocks with TestMemoryOptimizerStrategySingle + // Skip strategy is invalid as every second block is not found + TestMemoryOptimizerStrategySkip testMemoryOptimizerStrategySingle(MemBlockStrategyType::SingleAxisPacking); + auto ptr = std::make_shared(testMemoryOptimizerStrategySingle); + MemoryOptimizerValidator validator(std::move(ptr)); + CHECK(!validator.Validate(memBlocks)); + + // Optimize the memory blocks with TestMemoryOptimizerStrategyMulti + TestMemoryOptimizerStrategySkip testMemoryOptimizerStrategyMulti(MemBlockStrategyType::MultiAxisPacking); + auto ptrMulti = std::make_shared(testMemoryOptimizerStrategyMulti); + MemoryOptimizerValidator validatorMulti(std::move(ptrMulti)); + CHECK(!validatorMulti.Validate(memBlocks)); +} + +} -- cgit v1.2.1