From 37bcc99cd2179ac4ddb33b00959d8f056a3ae2cd Mon Sep 17 00:00:00 2001 From: Pawel Wilma Date: Thu, 4 Apr 2019 10:50:02 +0200 Subject: [PATCH] Class for local memory bank selection based on usage Related-To: NEO-2906 Change-Id: I8b9cae5191da6344ee8d4f0cf7125f95d0bc6b35 Signed-off-by: Pawel Wilma --- runtime/memory_manager/CMakeLists.txt | 2 + runtime/memory_manager/local_memory_usage.cpp | 38 ++++++++ runtime/memory_manager/local_memory_usage.h | 34 ++++++++ unit_tests/memory_manager/CMakeLists.txt | 1 + .../local_memory_usage_tests.cpp | 87 +++++++++++++++++++ 5 files changed, 162 insertions(+) create mode 100644 runtime/memory_manager/local_memory_usage.cpp create mode 100644 runtime/memory_manager/local_memory_usage.h create mode 100644 unit_tests/memory_manager/local_memory_usage_tests.cpp diff --git a/runtime/memory_manager/CMakeLists.txt b/runtime/memory_manager/CMakeLists.txt index 7d93d3de62..e032b91cb4 100644 --- a/runtime/memory_manager/CMakeLists.txt +++ b/runtime/memory_manager/CMakeLists.txt @@ -27,6 +27,8 @@ set(RUNTIME_SRCS_MEMORY_MANAGER ${CMAKE_CURRENT_SOURCE_DIR}/host_ptr_manager.h ${CMAKE_CURRENT_SOURCE_DIR}/internal_allocation_storage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/internal_allocation_storage.h + ${CMAKE_CURRENT_SOURCE_DIR}/local_memory_usage.h + ${CMAKE_CURRENT_SOURCE_DIR}/local_memory_usage.cpp ${CMAKE_CURRENT_SOURCE_DIR}/memory_banks.h ${CMAKE_CURRENT_SOURCE_DIR}/memory_constants.h ${CMAKE_CURRENT_SOURCE_DIR}/memory_manager.cpp diff --git a/runtime/memory_manager/local_memory_usage.cpp b/runtime/memory_manager/local_memory_usage.cpp new file mode 100644 index 0000000000..9fa6b6fda6 --- /dev/null +++ b/runtime/memory_manager/local_memory_usage.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "runtime/memory_manager/local_memory_usage.h" + +#include +#include + +namespace NEO { + +LocalMemoryUsageBankSelector::LocalMemoryUsageBankSelector(uint32_t banksCount) : banksCount(banksCount) { + UNRECOVERABLE_IF(banksCount == 0); + + memorySizes.reset(new std::atomic[banksCount]); + for (uint32_t i = 0; i < banksCount; i++) { + memorySizes[i] = 0; + } +} + +uint32_t LocalMemoryUsageBankSelector::getLeastOccupiedBank() { + auto leastOccupiedBankIterator = std::min_element(memorySizes.get(), memorySizes.get() + banksCount); + return static_cast(std::distance(memorySizes.get(), leastOccupiedBankIterator)); +} + +void LocalMemoryUsageBankSelector::freeOnBank(uint32_t bankIndex, uint64_t allocationSize) { + UNRECOVERABLE_IF(bankIndex >= banksCount); + memorySizes[bankIndex] -= allocationSize; +} +void LocalMemoryUsageBankSelector::reserveOnBank(uint32_t bankIndex, uint64_t allocationSize) { + UNRECOVERABLE_IF(bankIndex >= banksCount); + memorySizes[bankIndex] += allocationSize; +} + +} // namespace NEO diff --git a/runtime/memory_manager/local_memory_usage.h b/runtime/memory_manager/local_memory_usage.h new file mode 100644 index 0000000000..724ca6260a --- /dev/null +++ b/runtime/memory_manager/local_memory_usage.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2019 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "runtime/helpers/debug_helpers.h" +#include "runtime/helpers/properties_helper.h" + +#include +#include + +namespace NEO { +class LocalMemoryUsageBankSelector : public NonCopyableOrMovableClass { + public: + LocalMemoryUsageBankSelector() = delete; + LocalMemoryUsageBankSelector(uint32_t banksCount); + uint32_t getLeastOccupiedBank(); + void freeOnBank(uint32_t bankIndex, uint64_t allocationSize); + void reserveOnBank(uint32_t bankIndex, uint64_t allocationSize); + + MOCKABLE_VIRTUAL uint64_t getOccupiedMemorySizeForBank(uint32_t bankIndex) { + UNRECOVERABLE_IF(bankIndex >= banksCount); + return memorySizes[bankIndex].load(); + } + + protected: + uint32_t banksCount = 0; + std::unique_ptr[]> memorySizes = nullptr; +}; +} // namespace NEO diff --git a/unit_tests/memory_manager/CMakeLists.txt b/unit_tests/memory_manager/CMakeLists.txt index a599e45822..49e1f59838 100644 --- a/unit_tests/memory_manager/CMakeLists.txt +++ b/unit_tests/memory_manager/CMakeLists.txt @@ -13,6 +13,7 @@ set(IGDRCL_SRCS_tests_memory_manager ${CMAKE_CURRENT_SOURCE_DIR}/graphics_allocation_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/host_ptr_manager_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/internal_allocation_storage_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/local_memory_usage_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/memory_manager_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}/memory_manager_allocate_in_device_pool_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/memory_manager_allocate_in_device_pool_tests.inl diff --git a/unit_tests/memory_manager/local_memory_usage_tests.cpp b/unit_tests/memory_manager/local_memory_usage_tests.cpp new file mode 100644 index 0000000000..1b84d05915 --- /dev/null +++ b/unit_tests/memory_manager/local_memory_usage_tests.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2019 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "runtime/helpers/basic_math.h" +#include "runtime/memory_manager/local_memory_usage.h" + +#include "third_party/gtest/gtest/gtest.h" + +namespace NEO { + +struct MockLocalMemoryUsageBankSelector : public LocalMemoryUsageBankSelector { + using LocalMemoryUsageBankSelector::banksCount; + using LocalMemoryUsageBankSelector::LocalMemoryUsageBankSelector; + std::atomic *getMemorySizes() { return memorySizes.get(); } +}; + +TEST(localMemoryUsageTest, givenLocalMemoryUsageBankSelectorWhenItsCreatedAllValuesAreZero) { + MockLocalMemoryUsageBankSelector selector(2u); + + for (uint32_t i = 0; i < selector.banksCount; i++) { + EXPECT_EQ(0u, selector.getMemorySizes()[i].load()); + } +} + +TEST(localMemoryUsageTest, givenLocalMemoryUsageBankSelectorWhenMemoryIsReservedOnGivenBankThenValueStoredInTheArrayIsCorrect) { + LocalMemoryUsageBankSelector selector(4u); + + uint64_t allocationSize = 1024u; + auto bankIndex = selector.getLeastOccupiedBank(); + selector.reserveOnBank(bankIndex, allocationSize); + + EXPECT_EQ(allocationSize, selector.getOccupiedMemorySizeForBank(bankIndex)); +} + +TEST(localMemoryUsageTest, givenLocalMemoryUsageBankSelectorWhenMemoryIsReleasedThenValueIsCorrectlyAllocated) { + LocalMemoryUsageBankSelector selector(1u); + + uint64_t allocationSize = 1024u; + auto bankIndex = selector.getLeastOccupiedBank(); + EXPECT_EQ(0u, bankIndex); + selector.reserveOnBank(bankIndex, allocationSize); + + bankIndex = selector.getLeastOccupiedBank(); + EXPECT_EQ(0u, bankIndex); + selector.reserveOnBank(bankIndex, allocationSize); + + selector.freeOnBank(bankIndex, allocationSize); + + EXPECT_EQ(allocationSize, selector.getOccupiedMemorySizeForBank(bankIndex)); +} + +TEST(localMemoryUsageTest, givenLocalMemoryUsageBankSelectorWhenMemoryAllocatedSeveralTimesItIsStoredOnDifferentBanks) { + MockLocalMemoryUsageBankSelector selector(5u); + + uint64_t allocationSize = 1024u; + + auto bankIndex = selector.getLeastOccupiedBank(); + selector.reserveOnBank(bankIndex, allocationSize); + bankIndex = selector.getLeastOccupiedBank(); + selector.reserveOnBank(bankIndex, allocationSize); + bankIndex = selector.getLeastOccupiedBank(); + selector.reserveOnBank(bankIndex, allocationSize); + bankIndex = selector.getLeastOccupiedBank(); + selector.reserveOnBank(bankIndex, allocationSize); + bankIndex = selector.getLeastOccupiedBank(); + selector.reserveOnBank(bankIndex, allocationSize); + + for (uint32_t i = 0; i < selector.banksCount; i++) { + EXPECT_EQ(allocationSize, selector.getOccupiedMemorySizeForBank(i)); + } +} + +TEST(localMemoryUsageTest, givenLocalMemoryUsageBankSelectorWhenIndexIsInvalidThenErrorIsReturned) { + LocalMemoryUsageBankSelector selector(3u); + EXPECT_THROW(selector.reserveOnBank(8u, 1024u), std::exception); + EXPECT_THROW(selector.freeOnBank(8u, 1024u), std::exception); + EXPECT_THROW(selector.getOccupiedMemorySizeForBank(8u), std::exception); +} + +TEST(localMemoryUsageTest, givenLocalMemoryUsageBankSelectorWhenItsCreatedWithZeroBanksThenErrorIsReturned) { + EXPECT_THROW(LocalMemoryUsageBankSelector(0u), std::exception); +} +} // namespace NEO