fix: do not wait on tag when releasing in-place

Related-To: GSD-11990

If user releases USM without defer policy, do not check whether
allocation is in use when trying to reuse.

Also, when context is being destroyed, use blocking policy to
make sure that tag is updated and driver will notice that
resource is no longer being used by GPU when cleaning up.

Signed-off-by: Szymon Morek <szymon.morek@intel.com>
This commit is contained in:
Szymon Morek
2025-11-25 09:40:48 +00:00
committed by Compute-Runtime-Automation
parent 5790a624e1
commit bb15deca7e
6 changed files with 79 additions and 38 deletions

View File

@@ -42,7 +42,7 @@ namespace L0 {
ze_result_t ContextImp::destroy() { ze_result_t ContextImp::destroy() {
while (driverHandle->svmAllocsManager->getNumDeferFreeAllocs() > 0) { while (driverHandle->svmAllocsManager->getNumDeferFreeAllocs() > 0) {
this->driverHandle->svmAllocsManager->freeSVMAllocDeferImpl(); this->driverHandle->svmAllocsManager->freeSVMAllocDeferImplBlocking();
} }
delete this; delete this;

View File

@@ -2826,8 +2826,8 @@ TEST_F(FreeExtTests,
size_t size = 1024; size_t size = 1024;
size_t alignment = 1u; size_t alignment = 1u;
void *ptr = nullptr; void *ptr = nullptr;
auto mockMemoryManager = static_cast<MockMemoryManager *>(driverHandle->getMemoryManager());
static_cast<MockMemoryManager *>(driverHandle->getMemoryManager())->deferAllocInUse = true; mockMemoryManager->deferAllocInUse = true;
ze_host_mem_alloc_desc_t hostDesc = {}; ze_host_mem_alloc_desc_t hostDesc = {};
ze_result_t result = context->allocHostMem(&hostDesc, ze_result_t result = context->allocHostMem(&hostDesc,
@@ -2859,10 +2859,12 @@ TEST_F(FreeExtTests,
EXPECT_EQ(ZE_RESULT_SUCCESS, result); EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(3u, memManager->numDeferFreeAllocs()); EXPECT_EQ(3u, memManager->numDeferFreeAllocs());
EXPECT_EQ(3u, memManager->deferFreeCallsMade); EXPECT_EQ(3u, memManager->deferFreeCallsMade);
static_cast<MockMemoryManager *>(driverHandle->getMemoryManager())->deferAllocInUse = false; mockMemoryManager->deferAllocInUse = false;
EXPECT_EQ(0u, mockMemoryManager->waitForEnginesCompletionCalled);
context->destroy(); context->destroy();
context = nullptr; context = nullptr;
EXPECT_EQ(0u, memManager->numDeferFreeAllocs()); EXPECT_EQ(0u, memManager->numDeferFreeAllocs());
EXPECT_EQ(3u, mockMemoryManager->waitForEnginesCompletionCalled);
} }
TEST_F(FreeExtTests, TEST_F(FreeExtTests,

View File

@@ -62,7 +62,7 @@ SVMAllocsManager::SvmAllocationCache::SvmAllocationCache() {
this->enablePerformanceLogging = NEO::debugManager.flags.LogUsmReuse.get(); this->enablePerformanceLogging = NEO::debugManager.flags.LogUsmReuse.get();
} }
bool SVMAllocsManager::SvmAllocationCache::insert(size_t size, void *ptr, SvmAllocationData *svmData, bool waitForCompletion) { bool SVMAllocsManager::SvmAllocationCache::insert(size_t size, void *ptr, SvmAllocationData *svmData, CompletionCheckPolicy completionPolicy) {
if (false == sizeAllowed(size) || if (false == sizeAllowed(size) ||
svmData->isInternalAllocation || svmData->isInternalAllocation ||
svmData->isImportedAllocation) { svmData->isImportedAllocation) {
@@ -93,14 +93,14 @@ bool SVMAllocsManager::SvmAllocationCache::insert(size_t size, void *ptr, SvmAll
} }
} }
if (isSuccess) { if (isSuccess) {
if (waitForCompletion) { if (completionPolicy == CompletionCheckPolicy::waitOnFree) {
svmAllocsManager->waitForEnginesCompletion(svmData); svmAllocsManager->waitForEnginesCompletion(svmData);
} }
if (requireUpdatingAllocsForIndirectAccess) { if (requireUpdatingAllocsForIndirectAccess) {
svmAllocsManager->removeFromAllocsForIndirectAccess(*svmData); svmAllocsManager->removeFromAllocsForIndirectAccess(*svmData);
} }
svmData->isSavedForReuse = true; svmData->isSavedForReuse = true;
allocations.emplace(std::lower_bound(allocations.begin(), allocations.end(), size), size, ptr, svmData, waitForCompletion); allocations.emplace(std::lower_bound(allocations.begin(), allocations.end(), size), size, ptr, svmData, completionPolicy == CompletionCheckPolicy::deferred);
empty = false; empty = false;
if (auto usmReuseCleaner = this->memoryManager->peekExecutionEnvironment().unifiedMemoryReuseCleaner.get()) { if (auto usmReuseCleaner = this->memoryManager->peekExecutionEnvironment().unifiedMemoryReuseCleaner.get()) {
lock.unlock(); lock.unlock();
@@ -132,7 +132,7 @@ bool SVMAllocsManager::SvmAllocationCache::alignmentAllows(void *ptr, size_t ali
} }
bool SVMAllocsManager::SvmAllocationCache::isInUse(SvmCacheAllocationInfo &cacheAllocInfo) { bool SVMAllocsManager::SvmAllocationCache::isInUse(SvmCacheAllocationInfo &cacheAllocInfo) {
if (cacheAllocInfo.completed) { if (!cacheAllocInfo.isInUseCheckRequired) {
return false; return false;
} }
if (cacheAllocInfo.svmData->cpuAllocation && memoryManager->allocInUse(*cacheAllocInfo.svmData->cpuAllocation)) { if (cacheAllocInfo.svmData->cpuAllocation && memoryManager->allocInUse(*cacheAllocInfo.svmData->cpuAllocation)) {
@@ -700,15 +700,16 @@ bool SVMAllocsManager::freeSVMAlloc(void *ptr, bool blocking) {
} }
SvmAllocationData *svmData = getSVMAlloc(ptr); SvmAllocationData *svmData = getSVMAlloc(ptr);
if (svmData) { if (svmData) {
auto completionCheckPolicy = blocking ? SvmAllocationCache::CompletionCheckPolicy::waitOnFree : SvmAllocationCache::CompletionCheckPolicy::notRequired;
if (InternalMemoryType::deviceUnifiedMemory == svmData->memoryType && if (InternalMemoryType::deviceUnifiedMemory == svmData->memoryType &&
this->usmDeviceAllocationsCache) { this->usmDeviceAllocationsCache) {
if (this->usmDeviceAllocationsCache->insert(svmData->gpuAllocations.getDefaultGraphicsAllocation()->getUnderlyingBufferSize(), ptr, svmData, blocking)) { if (this->usmDeviceAllocationsCache->insert(svmData->gpuAllocations.getDefaultGraphicsAllocation()->getUnderlyingBufferSize(), ptr, svmData, completionCheckPolicy)) {
return true; return true;
} }
} }
if (InternalMemoryType::hostUnifiedMemory == svmData->memoryType && if (InternalMemoryType::hostUnifiedMemory == svmData->memoryType &&
this->usmHostAllocationsCache) { this->usmHostAllocationsCache) {
if (this->usmHostAllocationsCache->insert(svmData->gpuAllocations.getDefaultGraphicsAllocation()->getUnderlyingBufferSize(), ptr, svmData, blocking)) { if (this->usmHostAllocationsCache->insert(svmData->gpuAllocations.getDefaultGraphicsAllocation()->getUnderlyingBufferSize(), ptr, svmData, completionCheckPolicy)) {
return true; return true;
} }
} }
@@ -730,16 +731,16 @@ bool SVMAllocsManager::freeSVMAllocDefer(void *ptr) {
SvmAllocationData *svmData = getSVMAlloc(ptr); SvmAllocationData *svmData = getSVMAlloc(ptr);
if (svmData) { if (svmData) {
constexpr bool waitForCompletion = false; constexpr auto completionCheckPolicy = SvmAllocationCache::CompletionCheckPolicy::deferred;
if (InternalMemoryType::deviceUnifiedMemory == svmData->memoryType && if (InternalMemoryType::deviceUnifiedMemory == svmData->memoryType &&
this->usmDeviceAllocationsCache) { this->usmDeviceAllocationsCache) {
if (this->usmDeviceAllocationsCache->insert(svmData->gpuAllocations.getDefaultGraphicsAllocation()->getUnderlyingBufferSize(), ptr, svmData, waitForCompletion)) { if (this->usmDeviceAllocationsCache->insert(svmData->gpuAllocations.getDefaultGraphicsAllocation()->getUnderlyingBufferSize(), ptr, svmData, completionCheckPolicy)) {
return true; return true;
} }
} }
if (InternalMemoryType::hostUnifiedMemory == svmData->memoryType && if (InternalMemoryType::hostUnifiedMemory == svmData->memoryType &&
this->usmHostAllocationsCache) { this->usmHostAllocationsCache) {
if (this->usmHostAllocationsCache->insert(svmData->gpuAllocations.getDefaultGraphicsAllocation()->getUnderlyingBufferSize(), ptr, svmData, waitForCompletion)) { if (this->usmHostAllocationsCache->insert(svmData->gpuAllocations.getDefaultGraphicsAllocation()->getUnderlyingBufferSize(), ptr, svmData, completionCheckPolicy)) {
return true; return true;
} }
} }
@@ -800,11 +801,11 @@ void SVMAllocsManager::freeSVMAllocImpl(void *ptr, FreePolicyType policy, SvmAll
} }
} }
void SVMAllocsManager::freeSVMAllocDeferImpl() { void SVMAllocsManager::freeSVMAllocDeferImpl(FreePolicyType policy) {
std::vector<void *> freedPtr; std::vector<void *> freedPtr;
for (auto iter = svmDeferFreeAllocs.allocations.begin(); iter != svmDeferFreeAllocs.allocations.end(); ++iter) { for (auto iter = svmDeferFreeAllocs.allocations.begin(); iter != svmDeferFreeAllocs.allocations.end(); ++iter) {
void *ptr = reinterpret_cast<void *>(iter->second.gpuAllocations.getDefaultGraphicsAllocation()->getGpuAddress()); void *ptr = reinterpret_cast<void *>(iter->second.gpuAllocations.getDefaultGraphicsAllocation()->getGpuAddress());
this->freeSVMAllocImpl(ptr, FreePolicyType::defer, this->getSVMAlloc(ptr)); this->freeSVMAllocImpl(ptr, policy, this->getSVMAlloc(ptr));
if (this->getSVMAlloc(ptr) == nullptr) { if (this->getSVMAlloc(ptr) == nullptr) {
freedPtr.push_back(ptr); freedPtr.push_back(ptr);

View File

@@ -158,8 +158,8 @@ class SVMAllocsManager {
void *allocation; void *allocation;
SvmAllocationData *svmData; SvmAllocationData *svmData;
std::chrono::high_resolution_clock::time_point saveTime; std::chrono::high_resolution_clock::time_point saveTime;
bool completed; bool isInUseCheckRequired;
SvmCacheAllocationInfo(size_t allocationSize, void *allocation, SvmAllocationData *svmData, bool completed) : allocationSize(allocationSize), allocation(allocation), svmData(svmData), completed(completed) { SvmCacheAllocationInfo(size_t allocationSize, void *allocation, SvmAllocationData *svmData, bool isInUseCheckRequired) : allocationSize(allocationSize), allocation(allocation), svmData(svmData), isInUseCheckRequired(isInUseCheckRequired) {
saveTime = std::chrono::high_resolution_clock::now(); saveTime = std::chrono::high_resolution_clock::now();
} }
bool operator<(SvmCacheAllocationInfo const &other) const { bool operator<(SvmCacheAllocationInfo const &other) const {
@@ -183,6 +183,11 @@ class SVMAllocsManager {
trim, trim,
trimOld trimOld
}; };
enum class CompletionCheckPolicy {
waitOnFree,
deferred,
notRequired,
};
struct SvmAllocationCachePerfInfo { struct SvmAllocationCachePerfInfo {
uint64_t allocationSize; uint64_t allocationSize;
@@ -199,7 +204,7 @@ class SVMAllocsManager {
SvmAllocationCache(); SvmAllocationCache();
static bool sizeAllowed(size_t size) { return size <= SvmAllocationCache::maxServicedSize; } static bool sizeAllowed(size_t size) { return size <= SvmAllocationCache::maxServicedSize; }
bool insert(size_t size, void *ptr, SvmAllocationData *svmData, bool waitForCompletion); bool insert(size_t size, void *ptr, SvmAllocationData *svmData, CompletionCheckPolicy completionCheckPolicy);
static bool allocUtilizationAllows(size_t requestedSize, size_t reuseCandidateSize); static bool allocUtilizationAllows(size_t requestedSize, size_t reuseCandidateSize);
static bool alignmentAllows(void *ptr, size_t alignment); static bool alignmentAllows(void *ptr, size_t alignment);
bool isInUse(SvmCacheAllocationInfo &cacheAllocInfo); bool isInUse(SvmCacheAllocationInfo &cacheAllocInfo);
@@ -259,8 +264,9 @@ class SVMAllocsManager {
MOCKABLE_VIRTUAL bool freeSVMAlloc(void *ptr, bool blocking); MOCKABLE_VIRTUAL bool freeSVMAlloc(void *ptr, bool blocking);
MOCKABLE_VIRTUAL bool freeSVMAllocDefer(void *ptr); MOCKABLE_VIRTUAL bool freeSVMAllocDefer(void *ptr);
MOCKABLE_VIRTUAL void freeSVMAllocDeferImpl();
MOCKABLE_VIRTUAL void freeSVMAllocImpl(void *ptr, FreePolicyType policy, SvmAllocationData *svmData); MOCKABLE_VIRTUAL void freeSVMAllocImpl(void *ptr, FreePolicyType policy, SvmAllocationData *svmData);
void freeSVMAllocDeferImpl() { this->freeSVMAllocDeferImpl(FreePolicyType::defer); }
void freeSVMAllocDeferImplBlocking() { this->freeSVMAllocDeferImpl(FreePolicyType::blocking); }
bool freeSVMAlloc(void *ptr) { return freeSVMAlloc(ptr, false); } bool freeSVMAlloc(void *ptr) { return freeSVMAlloc(ptr, false); }
void cleanupUSMAllocCaches(); void cleanupUSMAllocCaches();
void trimUSMDeviceAllocCache(); void trimUSMDeviceAllocCache();
@@ -306,6 +312,7 @@ class SVMAllocsManager {
void waitForEnginesCompletion(SvmAllocationData *allocationData); void waitForEnginesCompletion(SvmAllocationData *allocationData);
protected: protected:
void freeSVMAllocDeferImpl(FreePolicyType policy);
void *createZeroCopySvmAllocation(size_t size, const SvmAllocationProperties &svmProperties, void *createZeroCopySvmAllocation(size_t size, const SvmAllocationProperties &svmProperties,
const RootDeviceIndicesContainer &rootDeviceIndices, const RootDeviceIndicesContainer &rootDeviceIndices,
const std::map<uint32_t, DeviceBitfield> &subdeviceBitfields); const std::map<uint32_t, DeviceBitfield> &subdeviceBitfields);

View File

@@ -138,11 +138,11 @@ TEST(SvmAllocationCacheSimpleTest, givenAllocationsWhenCheckingIsInUseThenReturn
allocationCache.svmAllocsManager = &svmAllocsManager; allocationCache.svmAllocsManager = &svmAllocsManager;
{ {
constexpr bool completed = false; constexpr bool inUseCheckRequired = true;
memoryManager.deferAllocInUse = false; memoryManager.deferAllocInUse = false;
MockGraphicsAllocation gpuGfxAllocation; MockGraphicsAllocation gpuGfxAllocation;
SvmAllocationData svmAllocData(mockRootDeviceIndex); SvmAllocationData svmAllocData(mockRootDeviceIndex);
SvmCacheAllocationInfo svmCacheAllocInfo(1u, addrToPtr(0xFULL), &svmAllocData, completed); SvmCacheAllocationInfo svmCacheAllocInfo(1u, addrToPtr(0xFULL), &svmAllocData, inUseCheckRequired);
EXPECT_FALSE(allocationCache.isInUse(svmCacheAllocInfo)); EXPECT_FALSE(allocationCache.isInUse(svmCacheAllocInfo));
svmAllocData.gpuAllocations.addAllocation(&gpuGfxAllocation); svmAllocData.gpuAllocations.addAllocation(&gpuGfxAllocation);
EXPECT_FALSE(allocationCache.isInUse(svmCacheAllocInfo)); EXPECT_FALSE(allocationCache.isInUse(svmCacheAllocInfo));
@@ -150,23 +150,23 @@ TEST(SvmAllocationCacheSimpleTest, givenAllocationsWhenCheckingIsInUseThenReturn
EXPECT_TRUE(allocationCache.isInUse(svmCacheAllocInfo)); EXPECT_TRUE(allocationCache.isInUse(svmCacheAllocInfo));
} }
{ {
constexpr bool completed = false; constexpr bool inUseCheckRequired = true;
memoryManager.deferAllocInUse = false; memoryManager.deferAllocInUse = false;
MockGraphicsAllocation cpuGfxAllocation; MockGraphicsAllocation cpuGfxAllocation;
SvmAllocationData svmAllocData(mockRootDeviceIndex); SvmAllocationData svmAllocData(mockRootDeviceIndex);
svmAllocData.cpuAllocation = &cpuGfxAllocation; svmAllocData.cpuAllocation = &cpuGfxAllocation;
SvmCacheAllocationInfo svmCacheAllocInfo(1u, addrToPtr(0xFULL), &svmAllocData, completed); SvmCacheAllocationInfo svmCacheAllocInfo(1u, addrToPtr(0xFULL), &svmAllocData, inUseCheckRequired);
EXPECT_FALSE(allocationCache.isInUse(svmCacheAllocInfo)); EXPECT_FALSE(allocationCache.isInUse(svmCacheAllocInfo));
memoryManager.deferAllocInUse = true; memoryManager.deferAllocInUse = true;
EXPECT_TRUE(allocationCache.isInUse(svmCacheAllocInfo)); EXPECT_TRUE(allocationCache.isInUse(svmCacheAllocInfo));
} }
{ {
constexpr bool completed = true; constexpr bool inUseCheckRequired = false;
memoryManager.deferAllocInUse = false; memoryManager.deferAllocInUse = false;
MockGraphicsAllocation cpuGfxAllocation; MockGraphicsAllocation cpuGfxAllocation;
SvmAllocationData svmAllocData(mockRootDeviceIndex); SvmAllocationData svmAllocData(mockRootDeviceIndex);
svmAllocData.cpuAllocation = &cpuGfxAllocation; svmAllocData.cpuAllocation = &cpuGfxAllocation;
SvmCacheAllocationInfo svmCacheAllocInfo(1u, addrToPtr(0xFULL), &svmAllocData, completed); SvmCacheAllocationInfo svmCacheAllocInfo(1u, addrToPtr(0xFULL), &svmAllocData, inUseCheckRequired);
EXPECT_FALSE(allocationCache.isInUse(svmCacheAllocInfo)); EXPECT_FALSE(allocationCache.isInUse(svmCacheAllocInfo));
memoryManager.deferAllocInUse = true; memoryManager.deferAllocInUse = true;
EXPECT_FALSE(allocationCache.isInUse(svmCacheAllocInfo)); EXPECT_FALSE(allocationCache.isInUse(svmCacheAllocInfo));
@@ -189,19 +189,19 @@ TEST(SvmAllocationCacheSimpleTest, givenAllocationsWhenInsertingAllocationThenDo
{ {
svmAllocData.isImportedAllocation = false; svmAllocData.isImportedAllocation = false;
svmAllocData.isInternalAllocation = false; svmAllocData.isInternalAllocation = false;
EXPECT_TRUE(allocationCache.insert(1u, ptr, &svmAllocData, false)); EXPECT_TRUE(allocationCache.insert(1u, ptr, &svmAllocData, SVMAllocsManager::SvmAllocationCache::CompletionCheckPolicy::notRequired));
allocationCache.allocations.clear(); allocationCache.allocations.clear();
} }
{ {
svmAllocData.isImportedAllocation = true; svmAllocData.isImportedAllocation = true;
svmAllocData.isInternalAllocation = false; svmAllocData.isInternalAllocation = false;
EXPECT_FALSE(allocationCache.insert(1u, ptr, &svmAllocData, false)); EXPECT_FALSE(allocationCache.insert(1u, ptr, &svmAllocData, SVMAllocsManager::SvmAllocationCache::CompletionCheckPolicy::notRequired));
allocationCache.allocations.clear(); allocationCache.allocations.clear();
} }
{ {
svmAllocData.isImportedAllocation = false; svmAllocData.isImportedAllocation = false;
svmAllocData.isInternalAllocation = true; svmAllocData.isInternalAllocation = true;
EXPECT_FALSE(allocationCache.insert(1u, ptr, &svmAllocData, false)); EXPECT_FALSE(allocationCache.insert(1u, ptr, &svmAllocData, SVMAllocsManager::SvmAllocationCache::CompletionCheckPolicy::notRequired));
allocationCache.allocations.clear(); allocationCache.allocations.clear();
} }
} }
@@ -229,7 +229,7 @@ TEST(SvmAllocationCacheSimpleTest, givenAllocationsWhenGettingAllocationThenUpda
{ {
allocationCache.requireUpdatingAllocsForIndirectAccess = false; allocationCache.requireUpdatingAllocsForIndirectAccess = false;
EXPECT_EQ(1u, svmAllocsManager.internalAllocationsMap.count(1u)); EXPECT_EQ(1u, svmAllocsManager.internalAllocationsMap.count(1u));
EXPECT_TRUE(allocationCache.insert(1u, ptr, &svmAllocData, false)); EXPECT_TRUE(allocationCache.insert(1u, ptr, &svmAllocData, SVMAllocsManager::SvmAllocationCache::CompletionCheckPolicy::notRequired));
EXPECT_EQ(1u, svmAllocsManager.internalAllocationsMap.count(1u)); EXPECT_EQ(1u, svmAllocsManager.internalAllocationsMap.count(1u));
auto reusedPtr = allocationCache.get(1u, unifiedMemoryProperties); auto reusedPtr = allocationCache.get(1u, unifiedMemoryProperties);
EXPECT_EQ(ptr, reusedPtr); EXPECT_EQ(ptr, reusedPtr);
@@ -248,7 +248,7 @@ TEST(SvmAllocationCacheSimpleTest, givenAllocationsWhenGettingAllocationThenUpda
EXPECT_EQ(1u, svmAllocsManager.internalAllocationsMap.count(1u)); EXPECT_EQ(1u, svmAllocsManager.internalAllocationsMap.count(1u));
EXPECT_EQ(0u, svmAllocsManager.internalAllocationsMap.count(2u)); EXPECT_EQ(0u, svmAllocsManager.internalAllocationsMap.count(2u));
allocationCache.requireUpdatingAllocsForIndirectAccess = true; allocationCache.requireUpdatingAllocsForIndirectAccess = true;
EXPECT_TRUE(allocationCache.insert(1u, ptr, &svmAllocData, false)); EXPECT_TRUE(allocationCache.insert(1u, ptr, &svmAllocData, SVMAllocsManager::SvmAllocationCache::CompletionCheckPolicy::notRequired));
EXPECT_EQ(0u, svmAllocsManager.internalAllocationsMap.count(1u)); EXPECT_EQ(0u, svmAllocsManager.internalAllocationsMap.count(1u));
EXPECT_EQ(0u, svmAllocsManager.internalAllocationsMap.count(2u)); EXPECT_EQ(0u, svmAllocsManager.internalAllocationsMap.count(2u));
auto reusedPtr = allocationCache.get(1u, unifiedMemoryProperties); auto reusedPtr = allocationCache.get(1u, unifiedMemoryProperties);
@@ -277,7 +277,7 @@ TEST(SvmAllocationCacheSimpleTest, givenAllocationsInCacheWhenCallingTrimThenUse
SvmAllocationData svmAllocData(mockRootDeviceIndex); SvmAllocationData svmAllocData(mockRootDeviceIndex);
svmAllocData.gpuAllocations.addAllocation(&gpuGfxAllocation); svmAllocData.gpuAllocations.addAllocation(&gpuGfxAllocation);
allocationCache.insert(1u, ptr, &svmAllocData, false); allocationCache.insert(1u, ptr, &svmAllocData, SVMAllocsManager::SvmAllocationCache::CompletionCheckPolicy::waitOnFree);
EXPECT_EQ(1u, allocationCache.allocations.size()); EXPECT_EQ(1u, allocationCache.allocations.size());
svmAllocsManager.freeSVMAllocImplCallBase = false; svmAllocsManager.freeSVMAllocImplCallBase = false;
allocationCache.trim(); allocationCache.trim();
@@ -311,7 +311,7 @@ TEST(SvmAllocationCacheSimpleTest, givenReuseCleanerWhenInsertingAllocationIntoC
UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::hostUnifiedMemory, 1, rootDeviceIndices, deviceBitfields); UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::hostUnifiedMemory, 1, rootDeviceIndices, deviceBitfields);
EXPECT_FALSE(reuseCleaner->startThreadCalled); EXPECT_FALSE(reuseCleaner->startThreadCalled);
EXPECT_TRUE(allocationCache.insert(1u, ptr, &svmAllocData, false)); EXPECT_TRUE(allocationCache.insert(1u, ptr, &svmAllocData, SVMAllocsManager::SvmAllocationCache::CompletionCheckPolicy::notRequired));
EXPECT_TRUE(reuseCleaner->startThreadCalled); EXPECT_TRUE(reuseCleaner->startThreadCalled);
EXPECT_FALSE(reuseCleaner->stopThreadCalled); EXPECT_FALSE(reuseCleaner->stopThreadCalled);
@@ -1179,7 +1179,7 @@ TEST_F(SvmDeviceAllocationCacheTest, givenAllocationInUsageWhenAllocatingAfterFr
unifiedMemoryProperties.device = device; unifiedMemoryProperties.device = device;
auto allocation = svmManager->createUnifiedMemoryAllocation(10u, unifiedMemoryProperties); auto allocation = svmManager->createUnifiedMemoryAllocation(10u, unifiedMemoryProperties);
EXPECT_NE(allocation, nullptr); EXPECT_NE(allocation, nullptr);
svmManager->freeSVMAlloc(allocation); svmManager->freeSVMAllocDefer(allocation);
EXPECT_EQ(svmManager->usmDeviceAllocationsCache->allocations.size(), 1u); EXPECT_EQ(svmManager->usmDeviceAllocationsCache->allocations.size(), 1u);
MockMemoryManager *mockMemoryManager = reinterpret_cast<MockMemoryManager *>(device->getMemoryManager()); MockMemoryManager *mockMemoryManager = reinterpret_cast<MockMemoryManager *>(device->getMemoryManager());
@@ -1189,7 +1189,7 @@ TEST_F(SvmDeviceAllocationCacheTest, givenAllocationInUsageWhenAllocatingAfterFr
auto svmData = svmManager->getSVMAlloc(testedAllocation); auto svmData = svmManager->getSVMAlloc(testedAllocation);
EXPECT_NE(nullptr, svmData); EXPECT_NE(nullptr, svmData);
svmManager->freeSVMAlloc(testedAllocation); svmManager->freeSVMAllocDefer(testedAllocation);
EXPECT_EQ(svmManager->usmDeviceAllocationsCache->allocations.size(), 2u); EXPECT_EQ(svmManager->usmDeviceAllocationsCache->allocations.size(), 2u);
svmManager->cleanupUSMAllocCaches(); svmManager->cleanupUSMAllocCaches();
@@ -2093,7 +2093,7 @@ TEST_F(SvmHostAllocationCacheTest, givenAllocationInUsageWhenAllocatingAfterFree
UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::hostUnifiedMemory, 1, rootDeviceIndices, deviceBitfields); UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::hostUnifiedMemory, 1, rootDeviceIndices, deviceBitfields);
auto allocation = svmManager->createHostUnifiedMemoryAllocation(10u, unifiedMemoryProperties); auto allocation = svmManager->createHostUnifiedMemoryAllocation(10u, unifiedMemoryProperties);
EXPECT_NE(allocation, nullptr); EXPECT_NE(allocation, nullptr);
svmManager->freeSVMAlloc(allocation); svmManager->freeSVMAllocDefer(allocation);
EXPECT_EQ(svmManager->usmHostAllocationsCache->allocations.size(), 1u); EXPECT_EQ(svmManager->usmHostAllocationsCache->allocations.size(), 1u);
memoryManager->deferAllocInUse = true; memoryManager->deferAllocInUse = true;
@@ -2102,12 +2102,43 @@ TEST_F(SvmHostAllocationCacheTest, givenAllocationInUsageWhenAllocatingAfterFree
auto svmData = svmManager->getSVMAlloc(testedAllocation); auto svmData = svmManager->getSVMAlloc(testedAllocation);
EXPECT_NE(nullptr, svmData); EXPECT_NE(nullptr, svmData);
svmManager->freeSVMAlloc(testedAllocation); svmManager->freeSVMAllocDefer(testedAllocation);
EXPECT_EQ(svmManager->usmHostAllocationsCache->allocations.size(), 2u); EXPECT_EQ(svmManager->usmHostAllocationsCache->allocations.size(), 2u);
svmManager->cleanupUSMAllocCaches(); svmManager->cleanupUSMAllocCaches();
} }
TEST_F(SvmHostAllocationCacheTest, givenAllocationInUsageWhenReleaseInPlaceAndAllocatingAfterFreeThenReuseAllocation) {
auto deviceFactory = std::make_unique<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 memoryManager = reinterpret_cast<MockMemoryManager *>(device->getMemoryManager());
auto svmManager = std::make_unique<MockSVMAllocsManager>(memoryManager);
memoryManager->usmReuseInfo.init(1 * MemoryConstants::gigaByte, UsmReuseInfo::notLimited);
svmManager->initUsmAllocationsCaches(*device);
EXPECT_NE(nullptr, svmManager->usmHostAllocationsCache);
UnifiedMemoryProperties unifiedMemoryProperties(InternalMemoryType::hostUnifiedMemory, 1, rootDeviceIndices, deviceBitfields);
auto allocation = svmManager->createHostUnifiedMemoryAllocation(10u, unifiedMemoryProperties);
EXPECT_NE(allocation, nullptr);
svmManager->freeSVMAlloc(allocation);
EXPECT_EQ(svmManager->usmHostAllocationsCache->allocations.size(), 1u);
memoryManager->deferAllocInUse = true;
auto testedAllocation = svmManager->createHostUnifiedMemoryAllocation(10u, unifiedMemoryProperties);
EXPECT_EQ(svmManager->usmHostAllocationsCache->allocations.size(), 0u);
auto svmData = svmManager->getSVMAlloc(testedAllocation);
EXPECT_NE(nullptr, svmData);
svmManager->freeSVMAlloc(testedAllocation);
EXPECT_EQ(svmManager->usmHostAllocationsCache->allocations.size(), 1u);
svmManager->cleanupUSMAllocCaches();
}
TEST_F(SvmHostAllocationCacheTest, givenAllocationMarkedCompletedWhenAllocatingAfterFreeThenDoNotCallAllocInUse) { TEST_F(SvmHostAllocationCacheTest, givenAllocationMarkedCompletedWhenAllocatingAfterFreeThenDoNotCallAllocInUse) {
auto deviceFactory = std::make_unique<UltDeviceFactory>(1, 1); auto deviceFactory = std::make_unique<UltDeviceFactory>(1, 1);
RootDeviceIndicesContainer rootDeviceIndices = {mockRootDeviceIndex}; RootDeviceIndicesContainer rootDeviceIndices = {mockRootDeviceIndex};
@@ -2130,7 +2161,7 @@ TEST_F(SvmHostAllocationCacheTest, givenAllocationMarkedCompletedWhenAllocatingA
EXPECT_EQ(svmManager->usmHostAllocationsCache->allocations.size(), 1u); EXPECT_EQ(svmManager->usmHostAllocationsCache->allocations.size(), 1u);
auto &svmAllocCacheInfo = svmManager->usmHostAllocationsCache->allocations[0]; auto &svmAllocCacheInfo = svmManager->usmHostAllocationsCache->allocations[0];
EXPECT_TRUE(svmAllocCacheInfo.completed); EXPECT_FALSE(svmAllocCacheInfo.isInUseCheckRequired);
memoryManager->deferAllocInUse = true; memoryManager->deferAllocInUse = true;
auto testedAllocation = svmManager->createHostUnifiedMemoryAllocation(10u, unifiedMemoryProperties); auto testedAllocation = svmManager->createHostUnifiedMemoryAllocation(10u, unifiedMemoryProperties);

View File

@@ -51,7 +51,7 @@ TEST(UnifiedMemoryReuseCleanerTestsMt, givenUnifiedMemoryReuseCleanerWhenCachesA
cleaner.waitOnConditionVar.store(false); cleaner.waitOnConditionVar.store(false);
EXPECT_FALSE(cleaner.waitOnConditionVar.load()); EXPECT_FALSE(cleaner.waitOnConditionVar.load());
SvmAllocationData allocData{0}; SvmAllocationData allocData{0};
svmAllocCache->insert(svmAllocSize, nullptr, &allocData, false); svmAllocCache->insert(svmAllocSize, nullptr, &allocData, SVMAllocsManager::SvmAllocationCache::CompletionCheckPolicy::notRequired);
cleaner.waitTillSleep(); cleaner.waitTillSleep();
EXPECT_TRUE(cleaner.waitOnConditionVar.load()); EXPECT_TRUE(cleaner.waitOnConditionVar.load());
EXPECT_TRUE(cleaner.isEmpty()); EXPECT_TRUE(cleaner.isEmpty());