refactor: decrease UsmMemAllocPoolsManager pool sizes in unit tests

Related-To: NEO-16082

Might fix NEO-16307

Signed-off-by: Aleksander Czerwionka <aleksander.czerwionka@intel.com>
This commit is contained in:
Aleksander Czerwionka
2025-10-16 10:01:57 +00:00
committed by Compute-Runtime-Automation
parent a05ce05af6
commit cfbbe04e32
16 changed files with 215 additions and 158 deletions

View File

@@ -34,7 +34,6 @@ void applyWorkarounds() {
}
L0::globalDriverHandles = new std::vector<_ze_driver_handle_t *>;
L0::globalDriverHandles->reserve(1);
debugManager.flags.EnableUsmAllocationPoolManager.set(0);
}
void setupTestFiles(std::string testBinaryFiles, int32_t revId) {

View File

@@ -1983,6 +1983,15 @@ HWTEST2_P(ImageCreateUsmPool, GivenBindlessImageWhenImageCreatedWithInvalidPitch
auto ret = imageHW->initialize(device, &srcImgDesc);
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, ret);
}
if (auto usmPoolManager = neoDevice->getUsmMemAllocPoolsManager()) {
auto mockPoolManager = reinterpret_cast<MockUsmMemAllocPoolsManager *>(usmPoolManager);
auto poolInfo = PoolInfo::getPoolInfos()[0];
auto mockUsmAllocPool = reinterpret_cast<MockUsmMemAllocPool *>(mockPoolManager->pools[poolInfo][0].get());
pitchedDesc.ptr = mockUsmAllocPool->pool; // not allocated ptr within USM pool
auto imageHW = std::make_unique<WhiteBox<::L0::ImageCoreFamily<FamilyType::gfxCoreFamily>>>();
auto ret = imageHW->initialize(device, &srcImgDesc);
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, ret);
}
}
HWTEST2_P(ImageCreateUsmPool, GivenBindlessImageWhenImageCreatedWithDeviceUSMPitchedPtrThenImageIsCreated, ImageSupport) {

View File

@@ -697,22 +697,24 @@ TEST_F(AllocUsmDeviceEnabledMemoryNewVersionTest, givenContextWhenAllocatingAndF
result = context->freeMem(allocation);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
{
void *allocation2MB = nullptr;
result = context->allocDeviceMem(deviceHandle, &deviceAllocDesc, 2 * MemoryConstants::megaByte, 0u, &allocation2MB);
for (auto poolInfo : PoolInfo::getPoolInfos()) {
void *allocation = nullptr;
auto sizeToAllocate = (poolInfo.minServicedSize + poolInfo.maxServicedSize) / 2;
result = context->allocDeviceMem(deviceHandle, &deviceAllocDesc, sizeToAllocate, 0u, &allocation);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_NE(nullptr, allocation2MB);
EXPECT_EQ(allocation2MB, usmMemAllocPoolsManager->getPooledAllocationBasePtr(allocation2MB));
auto pool = usmMemAllocPoolsManager->getPoolContainingAlloc(allocation2MB);
EXPECT_NE(nullptr, allocation);
EXPECT_EQ(allocation, usmMemAllocPoolsManager->getPooledAllocationBasePtr(allocation));
auto pool = usmMemAllocPoolsManager->getPoolContainingAlloc(allocation);
EXPECT_NE(nullptr, pool);
const auto poolInfo = pool->getPoolInfo();
EXPECT_GE(2 * MemoryConstants::megaByte, poolInfo.minServicedSize);
EXPECT_LE(2 * MemoryConstants::megaByte, poolInfo.maxServicedSize);
EXPECT_EQ(2 * MemoryConstants::megaByte, usmMemAllocPoolsManager->getPooledAllocationSize(allocation2MB));
auto allocationSizeReportedByPool = usmMemAllocPoolsManager->getPooledAllocationSize(allocation);
EXPECT_GE(allocationSizeReportedByPool, poolInfo.minServicedSize);
EXPECT_LE(allocationSizeReportedByPool, poolInfo.maxServicedSize);
EXPECT_EQ(allocationSizeReportedByPool, sizeToAllocate);
}
{
auto maxPooledSize = UsmMemAllocPoolsManager::poolInfos.back().maxServicedSize;
auto maxPooledSize = PoolInfo::getPoolInfos().back().maxServicedSize;
void *allocationOverLimit = nullptr;
result = context->allocDeviceMem(deviceHandle, &deviceAllocDesc, maxPooledSize + 1, 0u, &allocationOverLimit);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);

View File

@@ -29,6 +29,7 @@ add_executable(igdrcl_${target_name}
${NEO_SHARED_DIRECTORY}/dll/direct_submission_controller_enabled.cpp
${NEO_SHARED_DIRECTORY}/dll/unified_memory_reuse_cleaner_enabled.cpp
${NEO_SHARED_DIRECTORY}/dll/usm_pool_size.cpp
${NEO_SHARED_DIRECTORY}/dll/pool_info.cpp
${NEO_SHARED_DIRECTORY}/dll/linux/drm_neo_create.cpp
${NEO_SHARED_DIRECTORY}/dll/linux${BRANCH_DIR_SUFFIX}/options_linux.cpp
${NEO_SHARED_DIRECTORY}/dll/linux/options_linux.inl

View File

@@ -649,6 +649,25 @@ TEST(UsmPoolTest, whenGetUsmPoolSizeCalledThenReturnCorrectSize) {
EXPECT_EQ(usmPoolSize, NEO::UsmPoolParams::getUsmPoolSize(gfxCoreHelper));
}
TEST(UnifiedMemoryPoolingManagerTest, whenGetPoolInfosCalledThenCorrectInfoIsReturned) {
auto poolInfo0To4Kb = PoolInfo::getPoolInfos()[0];
auto poolInfo4KbTo64Kb = PoolInfo::getPoolInfos()[1];
auto poolInfo64KbTo2Mb = PoolInfo::getPoolInfos()[2];
ASSERT_EQ(0u, poolInfo0To4Kb.minServicedSize);
ASSERT_EQ(4 * MemoryConstants::kiloByte, poolInfo0To4Kb.maxServicedSize);
ASSERT_EQ(4 * MemoryConstants::kiloByte + 1, poolInfo4KbTo64Kb.minServicedSize);
ASSERT_EQ(64 * MemoryConstants::kiloByte, poolInfo4KbTo64Kb.maxServicedSize);
ASSERT_EQ(64 * MemoryConstants::kiloByte + 1, poolInfo64KbTo2Mb.minServicedSize);
ASSERT_EQ(2 * MemoryConstants::megaByte, poolInfo0To4Kb.poolSize);
ASSERT_EQ(2 * MemoryConstants::megaByte, poolInfo4KbTo64Kb.poolSize);
ASSERT_EQ(16 * MemoryConstants::megaByte, poolInfo64KbTo2Mb.poolSize);
ASSERT_EQ(2 * MemoryConstants::megaByte, poolInfo64KbTo2Mb.maxServicedSize);
}
TEST(DrmMemoryManagerCreate, whenCallCreateMemoryManagerThenDrmMemoryManagerIsCreated) {
DebugManagerStateRestore restorer;
debugManager.flags.OverridePatIndex.set(0);

View File

@@ -40,7 +40,7 @@ struct UsmPoolTest : public ::testing::Test {
std::unique_ptr<MockContext> mockContext;
MockUsmMemAllocPool *mockDeviceUsmMemAllocPool;
MockUsmMemAllocPool *mockHostUsmMemAllocPool;
constexpr static auto poolAllocationThreshold = 1 * MemoryConstants::megaByte;
constexpr static auto poolAllocationThreshold = MemoryConstants::pageSize;
};
TEST_F(UsmPoolTest, givenCreatedContextWhenCheckingUsmPoolsThenPoolsAreNotInitialized) {

View File

@@ -37,6 +37,7 @@ if(WIN32)
${NEO_SHARED_TEST_DIRECTORY}/common/os_interface/windows/wddm_calls.cpp
${NEO_SHARED_TEST_DIRECTORY}/common/mocks/mock_get_staging_buffer_size.cpp
${NEO_SHARED_TEST_DIRECTORY}/common/mocks/mock_usm_pool_size.cpp
${NEO_SHARED_TEST_DIRECTORY}/common/mocks/mock_pool_info.cpp
${NEO_SOURCE_DIR}/opencl/test/unit_test/test_macros/test_checks_ocl.cpp
)

View File

@@ -20,6 +20,7 @@ set(NEO_SHARED_DLLS
${CMAKE_CURRENT_SOURCE_DIR}/options_dll.cpp
${CMAKE_CURRENT_SOURCE_DIR}/get_staging_buffer_size.cpp
${CMAKE_CURRENT_SOURCE_DIR}/usm_pool_size.cpp
${CMAKE_CURRENT_SOURCE_DIR}/pool_info.cpp
)
add_library(neo_shared_dlls_precompiled_objects OBJECT ${NEO_SHARED_DLLS})

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2025 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/memory_manager/pool_info.h"
#include "shared/source/helpers/constants.h"
namespace NEO {
static constexpr uint64_t KB = MemoryConstants::kiloByte; // NOLINT(readability-identifier-naming)
static constexpr uint64_t MB = MemoryConstants::megaByte; // NOLINT(readability-identifier-naming)
// clang-format off
const std::array<const PoolInfo, 3> PoolInfo::poolInfos = {
PoolInfo{ 0, 4 * KB, 2 * MB},
PoolInfo{ 4 * KB+1, 64 * KB, 2 * MB},
PoolInfo{64 * KB+1, 2 * MB, 16 * MB}};
// clang-format on
size_t PoolInfo::getMaxPoolableSize() {
return 2 * MB;
}
} // namespace NEO

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2025 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include <array>
#include <cstddef>
namespace NEO {
class PoolInfo {
public:
size_t minServicedSize;
size_t maxServicedSize;
size_t poolSize;
bool operator<(const PoolInfo &rhs) const {
return this->minServicedSize < rhs.minServicedSize;
}
static const std::array<const PoolInfo, 3> getPoolInfos() {
return poolInfos;
}
static size_t getMaxPoolableSize();
private:
static const std::array<const PoolInfo, 3> poolInfos;
};
} // namespace NEO

View File

@@ -171,7 +171,7 @@ uint64_t UsmMemAllocPool::getPoolAddress() const {
return castToUint64(this->pool);
}
UsmMemAllocPool::PoolInfo UsmMemAllocPool::getPoolInfo() const {
PoolInfo UsmMemAllocPool::getPoolInfo() const {
return poolInfo;
}
@@ -180,7 +180,7 @@ bool UsmMemAllocPoolsManager::initialize(SVMAllocsManager *svmMemoryManager) {
poolMemoryType != InternalMemoryType::hostUnifiedMemory);
DEBUG_BREAK_IF(device == nullptr && poolMemoryType == InternalMemoryType::deviceUnifiedMemory);
this->svmMemoryManager = svmMemoryManager;
for (const auto &poolInfo : this->poolInfos) {
for (const auto &poolInfo : PoolInfo::getPoolInfos()) {
this->pools[poolInfo] = std::vector<std::unique_ptr<UsmMemAllocPool>>();
auto pool = tryAddPool(poolInfo);
if (nullptr == pool) {
@@ -212,7 +212,7 @@ void *UsmMemAllocPoolsManager::createUnifiedMemoryAllocation(size_t size, const
}
std::unique_lock<std::mutex> lock(mtx);
void *ptr = nullptr;
for (const auto &poolInfo : this->poolInfos) {
for (const auto &poolInfo : PoolInfo::getPoolInfos()) {
if (size <= poolInfo.maxServicedSize) {
for (auto &pool : this->pools[poolInfo]) {
if (nullptr != (ptr = pool->createUnifiedMemoryAllocation(size, memoryProperties))) {
@@ -247,6 +247,12 @@ bool UsmMemAllocPoolsManager::canAddPool(PoolInfo poolInfo) {
return true;
}
bool UsmMemAllocPoolsManager::canBePooled(size_t size, const UnifiedMemoryProperties &memoryProperties) {
return size <= PoolInfo::getMaxPoolableSize() &&
UsmMemAllocPool::alignmentIsAllowed(memoryProperties.alignment) &&
UsmMemAllocPool::flagsAreAllowed(memoryProperties);
}
void UsmMemAllocPoolsManager::trimEmptyPools(PoolInfo poolInfo) {
std::lock_guard lock(mtx);
auto &bucket = pools[poolInfo];
@@ -297,7 +303,7 @@ size_t UsmMemAllocPoolsManager::getOffsetInPool(const void *ptr) {
UsmMemAllocPool *UsmMemAllocPoolsManager::getPoolContainingAlloc(const void *ptr) {
std::unique_lock<std::mutex> lock(mtx);
for (const auto &poolInfo : this->poolInfos) {
for (const auto &poolInfo : PoolInfo::getPoolInfos()) {
for (auto &pool : this->pools[poolInfo]) {
if (pool->isInPool(ptr)) {
return pool.get();

View File

@@ -7,24 +7,16 @@
#pragma once
#include "shared/source/helpers/constants.h"
#include "shared/source/memory_manager/pool_info.h"
#include "shared/source/memory_manager/unified_memory_manager.h"
#include "shared/source/utilities/heap_allocator.h"
#include "shared/source/utilities/sorted_vector.h"
#include <array>
#include <map>
namespace NEO {
class UsmMemAllocPool : NEO::NonCopyableAndNonMovableClass {
public:
struct PoolInfo {
size_t minServicedSize;
size_t maxServicedSize;
size_t poolSize;
bool operator<(const PoolInfo &rhs) const {
return this->minServicedSize < rhs.minServicedSize;
}
};
using UnifiedMemoryProperties = SVMAllocsManager::UnifiedMemoryProperties;
struct AllocationInfo {
uint64_t address;
@@ -75,16 +67,6 @@ class UsmMemAllocPool : NEO::NonCopyableAndNonMovableClass {
class UsmMemAllocPoolsManager : NEO::NonCopyableAndNonMovableClass {
public:
using PoolInfo = UsmMemAllocPool::PoolInfo;
static constexpr uint64_t KB = MemoryConstants::kiloByte; // NOLINT(readability-identifier-naming)
static constexpr uint64_t MB = MemoryConstants::megaByte; // NOLINT(readability-identifier-naming)
static constexpr uint64_t maxPoolableSize = 2 * MB;
// clang-format off
static constexpr std::array<const PoolInfo, 3> poolInfos = {
PoolInfo{ 0, 4 * KB, 2 * MB},
PoolInfo{ 4 * KB+1, 64 * KB, 2 * MB},
PoolInfo{64 * KB+1, 2 * MB, 16 * MB}};
// clang-format on
static constexpr size_t maxEmptyPoolsPerBucket = 1u;
using UnifiedMemoryProperties = SVMAllocsManager::UnifiedMemoryProperties;
@@ -109,12 +91,7 @@ class UsmMemAllocPoolsManager : NEO::NonCopyableAndNonMovableClass {
UsmMemAllocPool *getPoolContainingAlloc(const void *ptr);
protected:
static bool canBePooled(size_t size, const UnifiedMemoryProperties &memoryProperties) {
return size <= maxPoolableSize &&
UsmMemAllocPool::alignmentIsAllowed(memoryProperties.alignment) &&
UsmMemAllocPool::flagsAreAllowed(memoryProperties);
}
bool canBePooled(size_t size, const UnifiedMemoryProperties &memoryProperties);
SVMAllocsManager *svmMemoryManager{};
MemoryManager *memoryManager{};
Device *device{nullptr};

View File

@@ -212,6 +212,7 @@ set(neo_libult_SRCS_LINUX
${NEO_SHARED_TEST_DIRECTORY}/common/os_interface/linux/sys_calls_linux_ult.cpp
${NEO_SHARED_TEST_DIRECTORY}/common/mocks/mock_get_staging_buffer_size.cpp
${NEO_SHARED_TEST_DIRECTORY}/common/mocks/mock_usm_pool_size.cpp
${NEO_SHARED_TEST_DIRECTORY}/common/mocks/mock_pool_info.cpp
)
set_property(GLOBAL APPEND PROPERTY neo_libult_SRCS_LINUX ${neo_libult_SRCS_LINUX})
@@ -229,6 +230,7 @@ set(neo_libult_SRCS_WINDOWS
${NEO_SHARED_TEST_DIRECTORY}/common/os_interface/windows/wddm_calls.cpp
${NEO_SHARED_TEST_DIRECTORY}/common/mocks/mock_get_staging_buffer_size.cpp
${NEO_SHARED_TEST_DIRECTORY}/common/mocks/mock_usm_pool_size.cpp
${NEO_SHARED_TEST_DIRECTORY}/common/mocks/mock_pool_info.cpp
)
set_property(GLOBAL APPEND PROPERTY neo_libult_SRCS_WINDOWS ${neo_libult_SRCS_WINDOWS})

View File

@@ -0,0 +1,24 @@
/*
* Copyright (C) 2025 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/helpers/constants.h"
#include "shared/source/memory_manager/pool_info.h"
namespace NEO {
static constexpr uint64_t KB = MemoryConstants::kiloByte; // NOLINT(readability-identifier-naming)
// clang-format off
const std::array<const PoolInfo, 3> PoolInfo::poolInfos = {
PoolInfo{ 0, 256, 2 * KB},
PoolInfo{ 256 + 1, 1 * KB, 8 * KB},
PoolInfo{1 * KB + 1, MemoryConstants::pageSize, 2 * MemoryConstants::pageSize }};
// clang-format on
size_t PoolInfo::getMaxPoolableSize() {
return MemoryConstants::pageSize;
}
} // namespace NEO

View File

@@ -2664,7 +2664,7 @@ TEST(Device, givenDeviceWhenCallingUsmAllocationPoolMethodsThenCorrectValueRetur
EXPECT_EQ(nullptr, device->getUsmMemAllocPool());
device->cleanupUsmAllocationPool();
auto poolInfo = UsmMemAllocPoolsManager::poolInfos[0];
auto poolInfo = PoolInfo::getPoolInfos()[0];
void *beforePoolPtr = addrToPtr(0xBEEF - 1);
void *poolStartPtr = addrToPtr(0xBEEF);
@@ -2697,7 +2697,7 @@ TEST(Device, givenDeviceWhenCallingUsmAllocationPoolMethodsThenCorrectValueRetur
device->resetUsmAllocationPoolManager(usmAllocPoolManager);
EXPECT_EQ(usmAllocPoolManager, device->getUsmMemAllocPoolsManager());
usmAllocPoolManager->canAddPoolCallBase = true;
EXPECT_TRUE(usmAllocPoolManager->canAddPool(UsmMemAllocPoolsManager::poolInfos[0]));
EXPECT_TRUE(usmAllocPoolManager->canAddPool(PoolInfo::getPoolInfos()[0]));
auto usmAllocPool = new MockUsmMemAllocPool;
usmAllocPool->pool = poolStartPtr;

View File

@@ -6,6 +6,8 @@
*/
#include "shared/source/helpers/aligned_memory.h"
#include "shared/source/helpers/constants.h"
#include "shared/source/memory_manager/pool_info.h"
#include "shared/source/memory_manager/unified_memory_pooling.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/mocks/mock_device.h"
@@ -271,26 +273,6 @@ TEST_F(InitializationFailedUnifiedMemoryPoolingTest, givenNotInitializedPoolWhen
EXPECT_EQ(0u, usmMemAllocPool.getOffsetInPool(bogusPtr));
}
using UnifiedMemoryPoolingManagerStaticTest = ::testing::Test;
TEST_F(UnifiedMemoryPoolingManagerStaticTest, givenUsmMemAllocPoolsManagerWhenCallingCanBePooledThenCorrectValueIsReturned) {
const RootDeviceIndicesContainer rootDeviceIndices;
const std::map<uint32_t, DeviceBitfield> deviceBitfields;
SVMAllocsManager::UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::hostUnifiedMemory, MemoryConstants::pageSize2M, rootDeviceIndices, deviceBitfields);
EXPECT_TRUE(MockUsmMemAllocPoolsManager::canBePooled(UsmMemAllocPoolsManager::maxPoolableSize, unifiedMemoryProperties));
EXPECT_FALSE(MockUsmMemAllocPoolsManager::canBePooled(UsmMemAllocPoolsManager::maxPoolableSize + 1, unifiedMemoryProperties));
unifiedMemoryProperties.alignment = UsmMemAllocPool::chunkAlignment / 2;
EXPECT_FALSE(MockUsmMemAllocPoolsManager::canBePooled(UsmMemAllocPoolsManager::maxPoolableSize, unifiedMemoryProperties));
unifiedMemoryProperties.alignment = UsmMemAllocPool::chunkAlignment;
unifiedMemoryProperties.allocationFlags.allFlags = 1u;
EXPECT_FALSE(MockUsmMemAllocPoolsManager::canBePooled(UsmMemAllocPoolsManager::maxPoolableSize, unifiedMemoryProperties));
unifiedMemoryProperties.allocationFlags.allFlags = 0u;
unifiedMemoryProperties.allocationFlags.allAllocFlags = 1u;
EXPECT_FALSE(MockUsmMemAllocPoolsManager::canBePooled(UsmMemAllocPoolsManager::maxPoolableSize, unifiedMemoryProperties));
}
class UnifiedMemoryPoolingManagerTest : public SVMMemoryAllocatorFixture<true>, public ::testing::TestWithParam<std::tuple<InternalMemoryType>> {
public:
void SetUp() override {
@@ -304,19 +286,16 @@ class UnifiedMemoryPoolingManagerTest : public SVMMemoryAllocatorFixture<true>,
usmMemAllocPoolsManager.reset(new MockUsmMemAllocPoolsManager(poolMemoryType,
rootDeviceIndices,
deviceBitfields,
poolMemoryType == InternalMemoryType::deviceUnifiedMemory ? device : nullptr));
device));
ASSERT_NE(nullptr, usmMemAllocPoolsManager);
EXPECT_FALSE(usmMemAllocPoolsManager->isInitialized());
poolInfo0To4Kb = usmMemAllocPoolsManager->poolInfos[0];
poolInfo4KbTo64Kb = usmMemAllocPoolsManager->poolInfos[1];
poolInfo64KbTo2Mb = usmMemAllocPoolsManager->poolInfos[2];
svmManager = std::make_unique<MockSVMAllocsManager>(device->getMemoryManager());
mockMemoryManager = static_cast<MockMemoryManager *>(device->getMemoryManager());
if (InternalMemoryType::deviceUnifiedMemory == poolMemoryType) {
mockMemoryManager->localMemorySupported[mockRootDeviceIndex] = true;
}
poolMemoryProperties = std::make_unique<SVMAllocsManager::UnifiedMemoryProperties>(poolMemoryType, MemoryConstants::pageSize2M, rootDeviceIndices, deviceBitfields);
poolMemoryProperties = std::make_unique<SVMAllocsManager::UnifiedMemoryProperties>(poolMemoryType, MemoryConstants::preferredAlignment, rootDeviceIndices, deviceBitfields);
poolMemoryProperties->device = poolMemoryType == InternalMemoryType::deviceUnifiedMemory ? device : nullptr;
}
void TearDown() override {
@@ -355,10 +334,6 @@ class UnifiedMemoryPoolingManagerTest : public SVMMemoryAllocatorFixture<true>,
MockMemoryManager *mockMemoryManager;
InternalMemoryType poolMemoryType;
uint64_t nextMockGraphicsAddress = alignUp(std::numeric_limits<uint64_t>::max() - MemoryConstants::teraByte, MemoryConstants::pageSize2M);
UsmMemAllocPoolsManager::PoolInfo poolInfo0To4Kb;
UsmMemAllocPoolsManager::PoolInfo poolInfo4KbTo64Kb;
UsmMemAllocPoolsManager::PoolInfo poolInfo64KbTo2Mb;
};
INSTANTIATE_TEST_SUITE_P(
@@ -367,13 +342,32 @@ INSTANTIATE_TEST_SUITE_P(
::testing::Combine(
::testing::Values(InternalMemoryType::deviceUnifiedMemory, InternalMemoryType::hostUnifiedMemory)));
TEST_P(UnifiedMemoryPoolingManagerTest, givenUsmMemAllocPoolsManagerWhenCallingCanBePooledThenCorrectValueIsReturned) {
const RootDeviceIndicesContainer rootDeviceIndices;
const std::map<uint32_t, DeviceBitfield> deviceBitfields;
SVMAllocsManager::UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::hostUnifiedMemory, MemoryConstants::pageSize2M, rootDeviceIndices, deviceBitfields);
EXPECT_TRUE(usmMemAllocPoolsManager->canBePooled(PoolInfo::getMaxPoolableSize(), unifiedMemoryProperties));
EXPECT_FALSE(usmMemAllocPoolsManager->canBePooled(PoolInfo::getMaxPoolableSize() + 1, unifiedMemoryProperties));
unifiedMemoryProperties.alignment = UsmMemAllocPool::chunkAlignment / 2;
EXPECT_FALSE(usmMemAllocPoolsManager->canBePooled(PoolInfo::getMaxPoolableSize(), unifiedMemoryProperties));
unifiedMemoryProperties.alignment = UsmMemAllocPool::chunkAlignment;
unifiedMemoryProperties.allocationFlags.allFlags = 1u;
EXPECT_FALSE(usmMemAllocPoolsManager->canBePooled(PoolInfo::getMaxPoolableSize(), unifiedMemoryProperties));
unifiedMemoryProperties.allocationFlags.allFlags = 0u;
unifiedMemoryProperties.allocationFlags.allAllocFlags = 1u;
EXPECT_FALSE(usmMemAllocPoolsManager->canBePooled(PoolInfo::getMaxPoolableSize(), unifiedMemoryProperties));
}
TEST_P(UnifiedMemoryPoolingManagerTest, givenInitializationFailsForOneOfTheSmallPoolsWhenInitializingPoolsManagerThenPoolsAreCleanedUp) {
mockMemoryManager->maxSuccessAllocatedGraphicsMemoryIndex = mockMemoryManager->successAllocatedGraphicsMemoryIndex + 2;
EXPECT_FALSE(usmMemAllocPoolsManager->initialize(svmManager.get()));
EXPECT_FALSE(usmMemAllocPoolsManager->isInitialized());
EXPECT_EQ(0u, usmMemAllocPoolsManager->pools[poolInfo0To4Kb].size());
EXPECT_EQ(0u, usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb].size());
EXPECT_EQ(0u, usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb].size());
for (auto poolInfo : PoolInfo::getPoolInfos()) {
EXPECT_EQ(0u, usmMemAllocPoolsManager->pools[poolInfo].size());
}
}
TEST_P(UnifiedMemoryPoolingManagerTest, givenInitializedPoolsManagerWhenAllocatingGreaterThan2MBOrWrongAlignmentOrWrongFlagsThenDoNotPool) {
@@ -404,7 +398,7 @@ TEST_P(UnifiedMemoryPoolingManagerTest, givenInitializedPoolsManagerWhenCallingM
EXPECT_EQ(0u, usmMemAllocPoolsManager->getPooledAllocationBasePtr(ptrOutsidePools));
EXPECT_EQ(0u, usmMemAllocPoolsManager->getOffsetInPool(ptrOutsidePools));
void *notAllocatedPtrInPoolAddressSpace = addrToPtr(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->getPoolAddress());
void *notAllocatedPtrInPoolAddressSpace = addrToPtr(usmMemAllocPoolsManager->pools[PoolInfo::getPoolInfos()[0]][0]->getPoolAddress());
EXPECT_FALSE(usmMemAllocPoolsManager->freeSVMAlloc(notAllocatedPtrInPoolAddressSpace, true));
EXPECT_EQ(0u, usmMemAllocPoolsManager->getPooledAllocationSize(notAllocatedPtrInPoolAddressSpace));
EXPECT_EQ(0u, usmMemAllocPoolsManager->getPooledAllocationBasePtr(notAllocatedPtrInPoolAddressSpace));
@@ -416,87 +410,53 @@ TEST_P(UnifiedMemoryPoolingManagerTest, givenInitializedPoolsManagerWhenCallingM
TEST_P(UnifiedMemoryPoolingManagerTest, givenInitializedPoolsManagerWhenAllocatingNotGreaterThan2MBThenPoolsAreUsed) {
ASSERT_TRUE(usmMemAllocPoolsManager->initialize(svmManager.get()));
ASSERT_TRUE(usmMemAllocPoolsManager->isInitialized());
ASSERT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo0To4Kb].size());
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->isInitialized());
ASSERT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb].size());
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->isInitialized());
ASSERT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb].size());
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->isInitialized());
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
EXPECT_EQ(2 * MemoryConstants::megaByte, usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->getPoolSize());
EXPECT_EQ(2 * MemoryConstants::megaByte, usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->getPoolSize());
EXPECT_EQ(16 * MemoryConstants::megaByte, usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->getPoolSize());
size_t totalSize = 0u;
for (auto &poolInfo : PoolInfo::getPoolInfos()) {
totalSize += poolInfo.poolSize;
}
EXPECT_EQ(totalSize, usmMemAllocPoolsManager->totalSize);
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->isEmpty());
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->isEmpty());
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->isEmpty());
for (auto &poolInfo : PoolInfo::getPoolInfos()) {
auto &pool = usmMemAllocPoolsManager->pools[poolInfo][0];
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->sizeIsAllowed(1));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->sizeIsAllowed(4 * MemoryConstants::kiloByte));
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->sizeIsAllowed(4 * MemoryConstants::kiloByte + 1));
ASSERT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo].size());
ASSERT_TRUE(pool->isInitialized());
EXPECT_EQ(poolInfo.poolSize, pool->getPoolSize());
EXPECT_TRUE(pool->isEmpty());
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->sizeIsAllowed(4 * MemoryConstants::kiloByte));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->sizeIsAllowed(4 * MemoryConstants::kiloByte + 1));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->sizeIsAllowed(64 * MemoryConstants::kiloByte));
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->sizeIsAllowed(64 * MemoryConstants::kiloByte + 1));
EXPECT_FALSE(pool->sizeIsAllowed(poolInfo.minServicedSize - 1));
EXPECT_TRUE(pool->sizeIsAllowed(poolInfo.minServicedSize));
EXPECT_TRUE(pool->sizeIsAllowed(poolInfo.maxServicedSize));
EXPECT_FALSE(pool->sizeIsAllowed(poolInfo.maxServicedSize + 1));
}
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->sizeIsAllowed(64 * MemoryConstants::kiloByte));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->sizeIsAllowed(64 * MemoryConstants::kiloByte + 1));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->sizeIsAllowed(2 * MemoryConstants::megaByte));
EXPECT_FALSE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->sizeIsAllowed(2 * MemoryConstants::megaByte + 1));
for (auto &poolInfo : PoolInfo::getPoolInfos()) {
size_t minServicedSize = poolInfo.minServicedSize ? poolInfo.minServicedSize : 1;
auto firstPoolAlloc1B = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(1u, *poolMemoryProperties.get());
EXPECT_NE(nullptr, firstPoolAlloc1B);
EXPECT_EQ(firstPoolAlloc1B, usmMemAllocPoolsManager->getPooledAllocationBasePtr(firstPoolAlloc1B));
EXPECT_EQ(1u, usmMemAllocPoolsManager->getPooledAllocationSize(firstPoolAlloc1B));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->isInPool(firstPoolAlloc1B));
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(firstPoolAlloc1B, true));
auto poolAllocMinSize = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(minServicedSize, *poolMemoryProperties.get());
EXPECT_NE(nullptr, poolAllocMinSize);
EXPECT_EQ(poolAllocMinSize, usmMemAllocPoolsManager->getPooledAllocationBasePtr(poolAllocMinSize));
EXPECT_EQ(minServicedSize, usmMemAllocPoolsManager->getPooledAllocationSize(poolAllocMinSize));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo][0]->isInPool(poolAllocMinSize));
EXPECT_EQ(totalSize, usmMemAllocPoolsManager->totalSize);
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(poolAllocMinSize, true));
auto firstPoolAlloc4KB = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(4 * MemoryConstants::kiloByte, *poolMemoryProperties.get());
EXPECT_NE(nullptr, firstPoolAlloc4KB);
EXPECT_EQ(firstPoolAlloc4KB, usmMemAllocPoolsManager->getPooledAllocationBasePtr(firstPoolAlloc4KB));
EXPECT_EQ(4 * MemoryConstants::kiloByte, usmMemAllocPoolsManager->getPooledAllocationSize(firstPoolAlloc4KB));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo0To4Kb][0]->isInPool(firstPoolAlloc4KB));
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(firstPoolAlloc4KB, true));
auto secondPoolAlloc4KB1B = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(4 * MemoryConstants::kiloByte + 1, *poolMemoryProperties.get());
EXPECT_NE(nullptr, secondPoolAlloc4KB1B);
EXPECT_EQ(secondPoolAlloc4KB1B, usmMemAllocPoolsManager->getPooledAllocationBasePtr(secondPoolAlloc4KB1B));
EXPECT_EQ(4 * MemoryConstants::kiloByte + 1, usmMemAllocPoolsManager->getPooledAllocationSize(secondPoolAlloc4KB1B));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->isInPool(secondPoolAlloc4KB1B));
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(secondPoolAlloc4KB1B, true));
auto secondPoolAlloc64KB = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(64 * MemoryConstants::kiloByte, *poolMemoryProperties.get());
EXPECT_NE(nullptr, secondPoolAlloc64KB);
EXPECT_EQ(secondPoolAlloc64KB, usmMemAllocPoolsManager->getPooledAllocationBasePtr(secondPoolAlloc64KB));
EXPECT_EQ(64 * MemoryConstants::kiloByte, usmMemAllocPoolsManager->getPooledAllocationSize(secondPoolAlloc64KB));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo4KbTo64Kb][0]->isInPool(secondPoolAlloc64KB));
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(secondPoolAlloc64KB, true));
auto thirdPoolAlloc64KB1B = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(64 * MemoryConstants::kiloByte + 1, *poolMemoryProperties.get());
EXPECT_NE(nullptr, thirdPoolAlloc64KB1B);
EXPECT_EQ(thirdPoolAlloc64KB1B, usmMemAllocPoolsManager->getPooledAllocationBasePtr(thirdPoolAlloc64KB1B));
EXPECT_EQ(64 * MemoryConstants::kiloByte + 1, usmMemAllocPoolsManager->getPooledAllocationSize(thirdPoolAlloc64KB1B));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->isInPool(thirdPoolAlloc64KB1B));
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(thirdPoolAlloc64KB1B, true));
auto thirdPoolAlloc2MB = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(2 * MemoryConstants::megaByte, *poolMemoryProperties.get());
EXPECT_NE(nullptr, thirdPoolAlloc2MB);
EXPECT_EQ(thirdPoolAlloc2MB, usmMemAllocPoolsManager->getPooledAllocationBasePtr(thirdPoolAlloc2MB));
EXPECT_EQ(2 * MemoryConstants::megaByte, usmMemAllocPoolsManager->getPooledAllocationSize(thirdPoolAlloc2MB));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][0]->isInPool(thirdPoolAlloc2MB));
EXPECT_EQ(20 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
auto poolAllocMaxSize = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(poolInfo.maxServicedSize, *poolMemoryProperties.get());
EXPECT_NE(nullptr, poolAllocMaxSize);
EXPECT_EQ(poolAllocMaxSize, usmMemAllocPoolsManager->getPooledAllocationBasePtr(poolAllocMaxSize));
EXPECT_EQ(poolInfo.maxServicedSize, usmMemAllocPoolsManager->getPooledAllocationSize(poolAllocMaxSize));
EXPECT_TRUE(usmMemAllocPoolsManager->pools[poolInfo][0]->isInPool(poolAllocMaxSize));
EXPECT_EQ(totalSize, usmMemAllocPoolsManager->totalSize);
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(poolAllocMaxSize, true));
}
usmMemAllocPoolsManager->canAddPools = false;
std::vector<void *> ptrsToFree;
for (auto i = 0u; i < 9; ++i) { // use all memory in third pool
auto ptr = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(2 * MemoryConstants::megaByte, *poolMemoryProperties.get());
auto thirdPoolInfo = PoolInfo::getPoolInfos()[2];
auto allocationsToOverfillThirdPool = thirdPoolInfo.poolSize / thirdPoolInfo.maxServicedSize + 1;
for (auto i = 0u; i < allocationsToOverfillThirdPool; ++i) {
auto ptr = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(thirdPoolInfo.maxServicedSize, *poolMemoryProperties.get());
if (nullptr == ptr) {
break;
}
@@ -508,23 +468,22 @@ TEST_P(UnifiedMemoryPoolingManagerTest, givenInitializedPoolsManagerWhenAllocati
ptrsToFree.push_back(ptr);
}
EXPECT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb].size());
EXPECT_EQ(1u, usmMemAllocPoolsManager->pools[thirdPoolInfo].size());
usmMemAllocPoolsManager->canAddPools = true;
auto thirdPoolAlloc2MBOverCapacity = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(2 * MemoryConstants::megaByte, *poolMemoryProperties.get());
EXPECT_NE(nullptr, thirdPoolAlloc2MBOverCapacity);
EXPECT_EQ(36 * MemoryConstants::megaByte, usmMemAllocPoolsManager->totalSize);
ASSERT_EQ(2u, usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb].size());
auto &newPool = usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb][1];
EXPECT_NE(nullptr, newPool->getPooledAllocationBasePtr(thirdPoolAlloc2MBOverCapacity));
auto thirdPoolAllocOverCapacity = usmMemAllocPoolsManager->createUnifiedMemoryAllocation(thirdPoolInfo.maxServicedSize, *poolMemoryProperties.get());
EXPECT_NE(nullptr, thirdPoolAllocOverCapacity);
EXPECT_EQ(totalSize + thirdPoolInfo.poolSize, usmMemAllocPoolsManager->totalSize);
ASSERT_EQ(2u, usmMemAllocPoolsManager->pools[thirdPoolInfo].size());
auto &newPool = usmMemAllocPoolsManager->pools[thirdPoolInfo][1];
EXPECT_NE(nullptr, newPool->getPooledAllocationBasePtr(thirdPoolAllocOverCapacity));
ptrsToFree.push_back(thirdPoolAlloc2MB);
ptrsToFree.push_back(thirdPoolAlloc2MBOverCapacity);
ptrsToFree.push_back(thirdPoolAllocOverCapacity);
for (auto ptr : ptrsToFree) {
EXPECT_TRUE(usmMemAllocPoolsManager->freeSVMAlloc(ptr, true));
}
EXPECT_EQ(1u, usmMemAllocPoolsManager->pools[poolInfo64KbTo2Mb].size());
EXPECT_EQ(1u, usmMemAllocPoolsManager->pools[thirdPoolInfo].size());
usmMemAllocPoolsManager->cleanup();
}