fix: limit max size for allocation reuse

Limit max size for allocation reuse mechanism to 256MB.

Related-To: NEO-6893

Signed-off-by: Dominik Dabek <dominik.dabek@intel.com>
This commit is contained in:
Dominik Dabek 2024-10-08 10:56:02 +00:00 committed by Compute-Runtime-Automation
parent 69a1afb8b1
commit 9159e2acd4
3 changed files with 76 additions and 2 deletions

View File

@ -44,6 +44,9 @@ void SVMAllocsManager::MapBasedAllocationTracker::remove(const SvmAllocationData
}
bool SVMAllocsManager::SvmAllocationCache::insert(size_t size, void *ptr) {
if (false == sizeAllowed(size)) {
return false;
}
std::lock_guard<std::mutex> lock(this->mtx);
if (size + this->totalSize > this->maxSize) {
return false;
@ -62,6 +65,9 @@ bool SVMAllocsManager::SvmAllocationCache::allocUtilizationAllows(size_t request
}
void *SVMAllocsManager::SvmAllocationCache::get(size_t size, const UnifiedMemoryProperties &unifiedMemoryProperties, SVMAllocsManager *svmAllocsManager) {
if (false == sizeAllowed(size)) {
return nullptr;
}
std::lock_guard<std::mutex> lock(this->mtx);
for (auto allocationIter = std::lower_bound(allocations.begin(), allocations.end(), size);
allocationIter != allocations.end();

View File

@ -157,12 +157,16 @@ class SVMAllocsManager {
};
struct SvmAllocationCache {
static constexpr size_t maxServicedSize = 256 * MemoryConstants::megaByte;
static constexpr size_t minimalSizeToCheckUtilization = 4 * MemoryConstants::pageSize64k;
static constexpr double minimalAllocUtilization = 0.5;
static bool sizeAllowed(size_t size) { return size <= SvmAllocationCache::maxServicedSize; }
bool insert(size_t size, void *);
static bool allocUtilizationAllows(size_t requestedSize, size_t reuseCandidateSize);
void *get(size_t size, const UnifiedMemoryProperties &unifiedMemoryProperties, SVMAllocsManager *svmAllocsManager);
void trim(SVMAllocsManager *svmAllocsManager);
static constexpr size_t minimalSizeToCheckUtilization = 4 * MemoryConstants::pageSize64k;
static constexpr double minimalAllocUtilization = 0.5;
std::vector<SvmCacheAllocationInfo> allocations;
std::mutex mtx;
size_t maxSize = 0;

View File

@ -99,6 +99,11 @@ TEST(SvmAllocationCacheSimpleTest, givenDifferentSizesWhenCheckingIfAllocUtiliza
EXPECT_TRUE(SVMAllocsManager::SvmAllocationCache::allocUtilizationAllows(allocationSizeBasis, allocationSizeBasis));
}
TEST(SvmAllocationCacheSimpleTest, givenDifferentSizesWhenCheckingIfSizeAllowsThenReturnCorrectValue) {
EXPECT_TRUE(SVMAllocsManager::SvmAllocationCache::sizeAllowed(256 * MemoryConstants::megaByte));
EXPECT_FALSE(SVMAllocsManager::SvmAllocationCache::sizeAllowed(256 * MemoryConstants::megaByte + 1));
}
struct SvmAllocationCacheTestFixture {
SvmAllocationCacheTestFixture() : executionEnvironment(defaultHwInfo.get()) {}
void setUp() {
@ -376,6 +381,36 @@ TEST_F(SvmDeviceAllocationCacheTest, givenAllocationsWithDifferentSizesWhenAlloc
EXPECT_EQ(svmManager->usmDeviceAllocationsCache.allocations.size(), 0u);
}
TEST_F(SvmDeviceAllocationCacheTest, givenAllocationOverSizeLimitWhenAllocatingAfterFreeThenDontSaveForReuse) {
std::unique_ptr<UltDeviceFactory> deviceFactory(new UltDeviceFactory(1, 1));
RootDeviceIndicesContainer rootDeviceIndices = {mockRootDeviceIndex};
std::map<uint32_t, DeviceBitfield> deviceBitfields{{mockRootDeviceIndex, mockDeviceBitfield}};
DebugManagerStateRestore restore;
debugManager.flags.ExperimentalEnableDeviceAllocationCache.set(1);
auto device = deviceFactory->rootDevices[0];
auto svmManager = std::make_unique<MockSVMAllocsManager>(device->getMemoryManager(), false);
svmManager->initUsmAllocationsCaches(*device);
ASSERT_TRUE(svmManager->usmDeviceAllocationsCacheEnabled);
svmManager->usmDeviceAllocationsCache.maxSize = 1 * MemoryConstants::gigaByte;
const auto notAcceptedAllocSize = SVMAllocsManager::SvmAllocationCache::maxServicedSize + 1;
SVMAllocsManager::UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::deviceUnifiedMemory, 1, rootDeviceIndices, deviceBitfields);
unifiedMemoryProperties.device = device;
auto mockMemoryManager = reinterpret_cast<MockMemoryManager *>(device->getMemoryManager());
auto mockGa = std::make_unique<MockGraphicsAllocation>(mockRootDeviceIndex, nullptr, notAcceptedAllocSize);
mockGa->gpuAddress = 0xbadf00;
mockGa->cpuPtr = reinterpret_cast<void *>(0xbadf00);
mockGa->setAllocationType(AllocationType::svmGpu);
mockMemoryManager->mockGa = mockGa.release();
mockMemoryManager->returnMockGAFromDevicePool = true;
auto allocation = svmManager->createUnifiedMemoryAllocation(notAcceptedAllocSize, unifiedMemoryProperties);
EXPECT_EQ(reinterpret_cast<void *>(0xbadf00), allocation);
svmManager->freeSVMAlloc(allocation);
EXPECT_EQ(0u, svmManager->usmDeviceAllocationsCache.allocations.size());
}
TEST_F(SvmDeviceAllocationCacheTest, givenMultipleAllocationsWhenAllocatingAfterFreeThenReturnAllocationsInCacheStartingFromSmallest) {
std::unique_ptr<UltDeviceFactory> deviceFactory(new UltDeviceFactory(1, 1));
RootDeviceIndicesContainer rootDeviceIndices = {mockRootDeviceIndex};
@ -872,6 +907,35 @@ TEST_F(SvmHostAllocationCacheTest, givenAllocationsWithDifferentSizesWhenAllocat
EXPECT_EQ(svmManager->usmHostAllocationsCache.allocations.size(), 0u);
}
TEST_F(SvmHostAllocationCacheTest, givenAllocationOverSizeLimitWhenAllocatingAfterFreeThenDontSaveForReuse) {
std::unique_ptr<UltDeviceFactory> deviceFactory(new UltDeviceFactory(1, 1));
RootDeviceIndicesContainer rootDeviceIndices = {mockRootDeviceIndex};
std::map<uint32_t, DeviceBitfield> deviceBitfields{{mockRootDeviceIndex, mockDeviceBitfield}};
DebugManagerStateRestore restore;
debugManager.flags.ExperimentalEnableHostAllocationCache.set(1);
auto device = deviceFactory->rootDevices[0];
auto svmManager = std::make_unique<MockSVMAllocsManager>(device->getMemoryManager(), false);
svmManager->initUsmAllocationsCaches(*device);
ASSERT_TRUE(svmManager->usmHostAllocationsCacheEnabled);
svmManager->usmHostAllocationsCache.maxSize = 1 * MemoryConstants::gigaByte;
const auto notAcceptedAllocSize = SVMAllocsManager::SvmAllocationCache::maxServicedSize + 1;
SVMAllocsManager::UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::hostUnifiedMemory, 1, rootDeviceIndices, deviceBitfields);
auto mockMemoryManager = reinterpret_cast<MockMemoryManager *>(device->getMemoryManager());
auto mockGa = std::make_unique<MockGraphicsAllocation>(mockRootDeviceIndex, nullptr, notAcceptedAllocSize);
mockGa->gpuAddress = 0xbadf00;
mockGa->cpuPtr = reinterpret_cast<void *>(0xbadf00);
mockGa->setAllocationType(AllocationType::svmCpu);
mockMemoryManager->mockGa = mockGa.release();
mockMemoryManager->returnMockGAFromHostPool = true;
auto allocation = svmManager->createHostUnifiedMemoryAllocation(notAcceptedAllocSize, unifiedMemoryProperties);
EXPECT_EQ(reinterpret_cast<void *>(0xbadf00), allocation);
svmManager->freeSVMAlloc(allocation);
EXPECT_EQ(0u, svmManager->usmHostAllocationsCache.allocations.size());
}
TEST_F(SvmHostAllocationCacheTest, givenMultipleAllocationsWhenAllocatingAfterFreeThenReturnAllocationsInCacheStartingFromSmallest) {
std::unique_ptr<UltDeviceFactory> deviceFactory(new UltDeviceFactory(1, 1));
RootDeviceIndicesContainer rootDeviceIndices = {mockRootDeviceIndex};