refactor: Adjust USM cleaner to ULLS light

Related-To: NEO-13922

Signed-off-by: Lukasz Jobczyk <lukasz.jobczyk@intel.com>
This commit is contained in:
Lukasz Jobczyk
2025-04-14 15:44:58 +00:00
committed by Compute-Runtime-Automation
parent 455209aadc
commit f7939735da
9 changed files with 58 additions and 14 deletions

View File

@@ -10,7 +10,7 @@
namespace NEO {
TEST(UnifiedMemoryReuseCleanerTestsMt, givenUnifiedMemoryReuseCleanerWhenSleepExpiredThenTrimOldInCachesIsCalled) {
MockUnifiedMemoryReuseCleaner cleaner;
MockUnifiedMemoryReuseCleaner cleaner(false);
cleaner.callBaseStartThread = true;
cleaner.callBaseTrimOldInCaches = false;
EXPECT_EQ(nullptr, cleaner.unifiedMemoryReuseCleanerThread);
@@ -33,7 +33,7 @@ TEST(UnifiedMemoryReuseCleanerTestsMt, givenUnifiedMemoryReuseCleanerWhenSleepEx
}
TEST(UnifiedMemoryReuseCleanerTestsMt, givenUnifiedMemoryReuseCleanerWithNotStartedCleaningWhenShuttingDownThenNoHang) {
MockUnifiedMemoryReuseCleaner cleaner;
MockUnifiedMemoryReuseCleaner cleaner(false);
cleaner.callBaseStartThread = true;
cleaner.callBaseTrimOldInCaches = false;
cleaner.startThread();

View File

@@ -152,16 +152,16 @@ DirectSubmissionController *ExecutionEnvironment::initializeDirectSubmissionCont
return directSubmissionController.get();
}
void ExecutionEnvironment::initializeUnifiedMemoryReuseCleaner(bool enable) {
void ExecutionEnvironment::initializeUnifiedMemoryReuseCleaner(bool isAnyDirectSubmissionLightEnabled) {
std::lock_guard<std::mutex> lock(initializeUnifiedMemoryReuseCleanerMutex);
auto initializeUnifiedMemoryReuseCleaner = UnifiedMemoryReuseCleaner::isSupported() && enable;
auto initializeUnifiedMemoryReuseCleaner = UnifiedMemoryReuseCleaner::isSupported() && !isAnyDirectSubmissionLightEnabled;
if (debugManager.flags.ExperimentalUSMAllocationReuseCleaner.get() != -1) {
initializeUnifiedMemoryReuseCleaner = debugManager.flags.ExperimentalUSMAllocationReuseCleaner.get() == 1;
}
if (initializeUnifiedMemoryReuseCleaner && nullptr == this->unifiedMemoryReuseCleaner) {
this->unifiedMemoryReuseCleaner = std::make_unique<UnifiedMemoryReuseCleaner>();
this->unifiedMemoryReuseCleaner = std::make_unique<UnifiedMemoryReuseCleaner>(isAnyDirectSubmissionLightEnabled);
this->unifiedMemoryReuseCleaner->startThread();
}
}

View File

@@ -66,7 +66,7 @@ class ExecutionEnvironment : public ReferenceTrackedObject<ExecutionEnvironment>
bool isFP64EmulationEnabled() const { return fp64EmulationEnabled; }
DirectSubmissionController *initializeDirectSubmissionController();
void initializeUnifiedMemoryReuseCleaner(bool enable);
void initializeUnifiedMemoryReuseCleaner(bool isAnyDirectSubmissionLightEnabled);
std::unique_ptr<MemoryManager> memoryManager;
std::unique_ptr<UnifiedMemoryReuseCleaner> unifiedMemoryReuseCleaner;

View File

@@ -936,7 +936,7 @@ void SVMAllocsManager::initUsmAllocationsCaches(Device &device) {
usmDeviceAllocationsCacheEnabled = !!debugManager.flags.ExperimentalEnableDeviceAllocationCache.get();
}
if (usmDeviceAllocationsCacheEnabled) {
device.getExecutionEnvironment()->initializeUnifiedMemoryReuseCleaner(!device.isAnyDirectSubmissionLightEnabled());
device.getExecutionEnvironment()->initializeUnifiedMemoryReuseCleaner(device.isAnyDirectSubmissionLightEnabled());
this->initUsmDeviceAllocationsCache(device);
}
@@ -945,7 +945,7 @@ void SVMAllocsManager::initUsmAllocationsCaches(Device &device) {
usmHostAllocationsCacheEnabled = !!debugManager.flags.ExperimentalEnableHostAllocationCache.get();
}
if (usmHostAllocationsCacheEnabled) {
device.getExecutionEnvironment()->initializeUnifiedMemoryReuseCleaner(!device.isAnyDirectSubmissionLightEnabled());
device.getExecutionEnvironment()->initializeUnifiedMemoryReuseCleaner(device.isAnyDirectSubmissionLightEnabled());
this->initUsmHostAllocationsCache();
}
}

View File

@@ -15,7 +15,7 @@
#include <thread>
namespace NEO {
UnifiedMemoryReuseCleaner::UnifiedMemoryReuseCleaner() {
UnifiedMemoryReuseCleaner::UnifiedMemoryReuseCleaner(bool trimAllAllocations) : trimAllAllocations(trimAllAllocations) {
}
UnifiedMemoryReuseCleaner::~UnifiedMemoryReuseCleaner() {
@@ -75,7 +75,7 @@ void UnifiedMemoryReuseCleaner::trimOldInCaches() {
}
}
}
svmAllocCache->trimOldAllocs(trimTimePoint, shouldLimitReuse);
svmAllocCache->trimOldAllocs(trimTimePoint, shouldLimitReuse || this->trimAllAllocations);
}
}

View File

@@ -23,7 +23,7 @@ class UnifiedMemoryReuseCleaner : NEO::NonCopyableAndNonMovableClass {
static constexpr auto sleepTime = std::chrono::milliseconds(15u);
static constexpr auto maxHoldTime = std::chrono::seconds(10u);
static constexpr auto limitedHoldTime = std::chrono::seconds(2u);
UnifiedMemoryReuseCleaner();
UnifiedMemoryReuseCleaner(bool trimAllAllocations);
virtual ~UnifiedMemoryReuseCleaner();
MOCKABLE_VIRTUAL void startThread();
@@ -45,6 +45,8 @@ class UnifiedMemoryReuseCleaner : NEO::NonCopyableAndNonMovableClass {
std::atomic_bool runCleaning = false;
std::atomic_bool keepCleaning = true;
bool trimAllAllocations = false;
};
static_assert(NEO::NonCopyableAndNonMovable<UnifiedMemoryReuseCleaner>);

View File

@@ -13,6 +13,7 @@ struct MockUnifiedMemoryReuseCleaner : public UnifiedMemoryReuseCleaner {
using UnifiedMemoryReuseCleaner::keepCleaning;
using UnifiedMemoryReuseCleaner::runCleaning;
using UnifiedMemoryReuseCleaner::svmAllocationCaches;
using UnifiedMemoryReuseCleaner::UnifiedMemoryReuseCleaner;
using UnifiedMemoryReuseCleaner::unifiedMemoryReuseCleanerThread;
void trimOldInCaches() override {

View File

@@ -431,7 +431,7 @@ TEST(ExecutionEnvironment, givenExecutionEnvironmentWithVariousMembersWhenItIsDe
}
};
struct UnifiedMemoryReuseCleanerMock : public DestructorCounted<UnifiedMemoryReuseCleaner, 7> {
UnifiedMemoryReuseCleanerMock(uint32_t &destructorId) : DestructorCounted(destructorId) {}
UnifiedMemoryReuseCleanerMock(uint32_t &destructorId) : DestructorCounted(destructorId, false) {}
};
struct DirectSubmissionControllerMock : public DestructorCounted<DirectSubmissionController, 6> {
DirectSubmissionControllerMock(uint32_t &destructorId) : DestructorCounted(destructorId) {}

View File

@@ -911,7 +911,7 @@ TEST_F(SvmDeviceAllocationCacheTest, givenUsmReuseCleanerWhenTrimOldInCachesCall
debugManager.flags.ExperimentalEnableHostAllocationCache.set(0);
auto device = deviceFactory->rootDevices[0];
auto svmManager = std::make_unique<MockSVMAllocsManager>(device->getMemoryManager(), false);
device->executionEnvironment->unifiedMemoryReuseCleaner.reset(new MockUnifiedMemoryReuseCleaner);
device->executionEnvironment->unifiedMemoryReuseCleaner.reset(new MockUnifiedMemoryReuseCleaner(false));
auto mockUnifiedMemoryReuseCleaner = reinterpret_cast<MockUnifiedMemoryReuseCleaner *>(device->executionEnvironment->unifiedMemoryReuseCleaner.get());
EXPECT_EQ(0u, mockUnifiedMemoryReuseCleaner->svmAllocationCaches.size());
device->usmReuseInfo.init(1 * MemoryConstants::gigaByte, UsmReuseInfo::notLimited);
@@ -955,6 +955,47 @@ TEST_F(SvmDeviceAllocationCacheTest, givenUsmReuseCleanerWhenTrimOldInCachesCall
EXPECT_EQ(0u, mockUnifiedMemoryReuseCleaner->svmAllocationCaches.size());
}
TEST_F(SvmDeviceAllocationCacheTest, givenDirectSubmissionLightWhenTrimOldInCachesCalledThenAllOldAllocationsAreRemoved) {
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);
debugManager.flags.ExperimentalEnableHostAllocationCache.set(0);
auto device = deviceFactory->rootDevices[0];
auto svmManager = std::make_unique<MockSVMAllocsManager>(device->getMemoryManager(), false);
device->executionEnvironment->unifiedMemoryReuseCleaner.reset(new MockUnifiedMemoryReuseCleaner(true));
auto mockUnifiedMemoryReuseCleaner = reinterpret_cast<MockUnifiedMemoryReuseCleaner *>(device->executionEnvironment->unifiedMemoryReuseCleaner.get());
EXPECT_EQ(0u, mockUnifiedMemoryReuseCleaner->svmAllocationCaches.size());
device->usmReuseInfo.init(1 * MemoryConstants::gigaByte, UsmReuseInfo::notLimited);
svmManager->initUsmAllocationsCaches(*device);
EXPECT_NE(nullptr, svmManager->usmDeviceAllocationsCache);
EXPECT_EQ(1u, mockUnifiedMemoryReuseCleaner->svmAllocationCaches.size());
EXPECT_EQ(svmManager->usmDeviceAllocationsCache.get(), mockUnifiedMemoryReuseCleaner->svmAllocationCaches[0]);
SVMAllocsManager::UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::deviceUnifiedMemory, 1, rootDeviceIndices, deviceBitfields);
unifiedMemoryProperties.device = device;
auto allocation = svmManager->createUnifiedMemoryAllocation(10u, unifiedMemoryProperties);
auto allocation2 = svmManager->createUnifiedMemoryAllocation(10u, unifiedMemoryProperties);
EXPECT_NE(allocation, nullptr);
EXPECT_NE(allocation2, nullptr);
svmManager->freeSVMAlloc(allocation);
svmManager->freeSVMAlloc(allocation2);
EXPECT_EQ(svmManager->usmDeviceAllocationsCache->allocations.size(), 2u);
const auto baseTimePoint = std::chrono::high_resolution_clock::now();
const auto oldTimePoint = baseTimePoint - UnifiedMemoryReuseCleaner::maxHoldTime;
svmManager->usmDeviceAllocationsCache->allocations[0].saveTime = oldTimePoint;
svmManager->usmDeviceAllocationsCache->allocations[1].saveTime = oldTimePoint;
mockUnifiedMemoryReuseCleaner->trimOldInCaches();
EXPECT_EQ(0u, svmManager->usmDeviceAllocationsCache->allocations.size());
svmManager->cleanupUSMAllocCaches();
EXPECT_EQ(0u, mockUnifiedMemoryReuseCleaner->svmAllocationCaches.size());
}
TEST_F(SvmDeviceAllocationCacheTest, givenUsmReuseCleanerWhenTrimOldInCachesCalledAndShouldLimitUsmReuseThenAllOldAllocationsAreRemovedEvenIfDeferredDeleterHasWork) {
std::unique_ptr<UltDeviceFactory> deviceFactory(new UltDeviceFactory(1, 1));
RootDeviceIndicesContainer rootDeviceIndices = {mockRootDeviceIndex};
@@ -965,7 +1006,7 @@ TEST_F(SvmDeviceAllocationCacheTest, givenUsmReuseCleanerWhenTrimOldInCachesCall
auto device = deviceFactory->rootDevices[0];
auto memoryManager = reinterpret_cast<MockMemoryManager *>(device->getMemoryManager());
auto svmManager = std::make_unique<MockSVMAllocsManager>(memoryManager, false);
device->executionEnvironment->unifiedMemoryReuseCleaner.reset(new MockUnifiedMemoryReuseCleaner);
device->executionEnvironment->unifiedMemoryReuseCleaner.reset(new MockUnifiedMemoryReuseCleaner(false));
auto mockUnifiedMemoryReuseCleaner = reinterpret_cast<MockUnifiedMemoryReuseCleaner *>(device->executionEnvironment->unifiedMemoryReuseCleaner.get());
EXPECT_EQ(0u, mockUnifiedMemoryReuseCleaner->svmAllocationCaches.size());
device->usmReuseInfo.init(1 * MemoryConstants::gigaByte, UsmReuseInfo::notLimited);