Add support for memory free policies

Add support for ZE_DRIVER_MEMORY_FREE_POLICY_EXT_FLAG_BLOCKING_FREE
added in v1.3.

Related-To: LOCI-2672

Signed-off-by: Jaime Arteaga <jaime.a.arteaga.molina@intel.com>
This commit is contained in:
Jaime Arteaga
2021-12-27 23:41:51 +00:00
committed by Compute-Runtime-Automation
parent b59b0b6b36
commit 3b497270c8
7 changed files with 161 additions and 8 deletions

View File

@ -60,6 +60,7 @@ zeGetMemProcAddrTable(
pDdiTable->pfnAllocDevice = zeMemAllocDevice;
pDdiTable->pfnAllocHost = zeMemAllocHost;
pDdiTable->pfnFree = zeMemFree;
pDdiTable->pfnFreeExt = zeMemFreeExt;
pDdiTable->pfnGetAllocProperties = zeMemGetAllocProperties;
pDdiTable->pfnGetAddressRange = zeMemGetAddressRange;
pDdiTable->pfnGetIpcHandle = zeMemGetIpcHandle;

View File

@ -48,6 +48,14 @@ zeMemFree(
return L0::Context::fromHandle(hContext)->freeMem(ptr);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zeMemFreeExt(
ze_context_handle_t hContext,
const ze_memory_free_ext_desc_t *pMemFreeDesc,
void *ptr) {
return L0::Context::fromHandle(hContext)->freeMemExt(pMemFreeDesc, ptr);
}
ZE_APIEXPORT ze_result_t ZE_APICALL
zeMemGetAllocProperties(
ze_context_handle_t hContext,

View File

@ -53,6 +53,9 @@ struct Context : _ze_context_handle_t {
size_t alignment,
void **ptr) = 0;
virtual ze_result_t freeMem(const void *ptr) = 0;
virtual ze_result_t freeMem(const void *ptr, bool blocking) = 0;
virtual ze_result_t freeMemExt(const ze_memory_free_ext_desc_t *pMemFreeDesc,
void *ptr) = 0;
virtual ze_result_t makeMemoryResident(ze_device_handle_t hDevice,
void *ptr,
size_t size) = 0;

View File

@ -269,6 +269,10 @@ ze_result_t ContextImp::allocSharedMem(ze_device_handle_t hDevice,
}
ze_result_t ContextImp::freeMem(const void *ptr) {
return this->freeMem(ptr, false);
}
ze_result_t ContextImp::freeMem(const void *ptr, bool blocking) {
auto allocation = this->driverHandle->svmAllocsManager->getSVMAlloc(ptr);
if (allocation == nullptr) {
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
@ -284,18 +288,30 @@ ze_result_t ContextImp::freeMem(const void *ptr) {
auto peerAllocData = &iter->second;
auto peerAlloc = peerAllocData->gpuAllocations.getDefaultGraphicsAllocation();
auto peerPtr = reinterpret_cast<void *>(peerAlloc->getGpuAddress());
this->driverHandle->svmAllocsManager->freeSVMAlloc(peerPtr);
this->driverHandle->svmAllocsManager->freeSVMAlloc(peerPtr, blocking);
deviceImp->peerAllocations.allocations.erase(iter);
}
}
this->driverHandle->svmAllocsManager->freeSVMAlloc(const_cast<void *>(ptr));
this->driverHandle->svmAllocsManager->freeSVMAlloc(const_cast<void *>(ptr), blocking);
if (this->driverHandle->svmAllocsManager->getSvmMapOperation(ptr)) {
this->driverHandle->svmAllocsManager->removeSvmMapOperation(ptr);
}
return ZE_RESULT_SUCCESS;
}
ze_result_t ContextImp::freeMemExt(const ze_memory_free_ext_desc_t *pMemFreeDesc,
void *ptr) {
if (pMemFreeDesc->freePolicy == ZE_DRIVER_MEMORY_FREE_POLICY_EXT_FLAG_BLOCKING_FREE) {
return this->freeMem(ptr, true);
}
if (pMemFreeDesc->freePolicy == ZE_DRIVER_MEMORY_FREE_POLICY_EXT_FLAG_DEFER_FREE) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
return this->freeMem(ptr, false);
}
ze_result_t ContextImp::makeMemoryResident(ze_device_handle_t hDevice, void *ptr, size_t size) {
Device *device = L0::Device::fromHandle(hDevice);
NEO::Device *neoDevice = device->getNEODevice();

View File

@ -34,6 +34,9 @@ struct ContextImp : Context {
size_t alignment,
void **ptr) override;
ze_result_t freeMem(const void *ptr) override;
ze_result_t freeMem(const void *ptr, bool blocking) override;
ze_result_t freeMemExt(const ze_memory_free_ext_desc_t *pMemFreeDesc,
void *ptr) override;
ze_result_t makeMemoryResident(ze_device_handle_t hDevice,
void *ptr,
size_t size) override;

View File

@ -354,6 +354,131 @@ TEST_F(MemoryTest, whenAllocatingSharedMemoryWithHostInitialPlacementBiasFlagThe
ASSERT_EQ(result, ZE_RESULT_SUCCESS);
}
struct SVMAllocsManagerFreeExtMock : public NEO::SVMAllocsManager {
SVMAllocsManagerFreeExtMock(MemoryManager *memoryManager) : NEO::SVMAllocsManager(memoryManager, false) {}
bool freeSVMAlloc(void *ptr, bool blocking) override {
if (blocking) {
blockingCallsMade++;
}
return SVMAllocsManager::freeSVMAlloc(ptr, blocking);
}
uint32_t blockingCallsMade = 0;
};
struct FreeExtTests : public ::testing::Test {
void SetUp() override {
NEO::MockCompilerEnableGuard mock(true);
neoDevice =
NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(NEO::defaultHwInfo.get());
auto mockBuiltIns = new MockBuiltins();
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->builtins.reset(mockBuiltIns);
NEO::DeviceVector devices;
devices.push_back(std::unique_ptr<NEO::Device>(neoDevice));
driverHandle = std::make_unique<DriverHandleImp>();
driverHandle->initialize(std::move(devices));
prevSvmAllocsManager = driverHandle->svmAllocsManager;
currSvmAllocsManager = new SVMAllocsManagerFreeExtMock(driverHandle->memoryManager);
driverHandle->svmAllocsManager = currSvmAllocsManager;
device = driverHandle->devices[0];
context = std::make_unique<ContextImp>(driverHandle.get());
EXPECT_NE(context, nullptr);
context->getDevices().insert(std::make_pair(device->toHandle(), device));
auto neoDevice = device->getNEODevice();
context->rootDeviceIndices.insert(neoDevice->getRootDeviceIndex());
context->deviceBitfields.insert({neoDevice->getRootDeviceIndex(), neoDevice->getDeviceBitfield()});
}
void TearDown() override {
driverHandle->svmAllocsManager = prevSvmAllocsManager;
delete currSvmAllocsManager;
}
NEO::SVMAllocsManager *prevSvmAllocsManager;
NEO::SVMAllocsManager *currSvmAllocsManager;
std::unique_ptr<DriverHandleImp> driverHandle;
NEO::MockDevice *neoDevice = nullptr;
L0::Device *device = nullptr;
std::unique_ptr<ContextImp> context;
};
TEST_F(FreeExtTests,
whenFreeMemIsCalledWithoutArgumentThenNoBlockingCallIsMade) {
size_t size = 1024;
size_t alignment = 1u;
void *ptr = nullptr;
ze_host_mem_alloc_desc_t hostDesc = {};
ze_result_t result = context->allocHostMem(&hostDesc,
size, alignment, &ptr);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_NE(nullptr, ptr);
result = context->freeMem(ptr);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
SVMAllocsManagerFreeExtMock *memManager = reinterpret_cast<SVMAllocsManagerFreeExtMock *>(currSvmAllocsManager);
EXPECT_EQ(0u, memManager->blockingCallsMade);
}
TEST_F(FreeExtTests,
whenFreeMemExtIsCalledWithBlockingFreePolicyThenBlockingCallIsMade) {
size_t size = 1024;
size_t alignment = 1u;
void *ptr = nullptr;
ze_host_mem_alloc_desc_t hostDesc = {};
ze_result_t result = context->allocHostMem(&hostDesc,
size, alignment, &ptr);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_NE(nullptr, ptr);
ze_memory_free_ext_desc_t memFreeDesc = {};
memFreeDesc.freePolicy = ZE_DRIVER_MEMORY_FREE_POLICY_EXT_FLAG_BLOCKING_FREE;
result = context->freeMemExt(&memFreeDesc, ptr);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
SVMAllocsManagerFreeExtMock *memManager = reinterpret_cast<SVMAllocsManagerFreeExtMock *>(currSvmAllocsManager);
EXPECT_EQ(1u, memManager->blockingCallsMade);
}
TEST_F(FreeExtTests,
whenFreeMemExtIsCalledWithDeferFreePolicyThenUnsuportedIsReturned) {
size_t size = 1024;
size_t alignment = 1u;
void *ptr = nullptr;
ze_host_mem_alloc_desc_t hostDesc = {};
ze_result_t result = context->allocHostMem(&hostDesc,
size, alignment, &ptr);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_NE(nullptr, ptr);
ze_memory_free_ext_desc_t memFreeDesc = {};
memFreeDesc.freePolicy = ZE_DRIVER_MEMORY_FREE_POLICY_EXT_FLAG_DEFER_FREE;
result = context->freeMemExt(&memFreeDesc, ptr);
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result);
result = context->freeMem(ptr);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
TEST_F(FreeExtTests,
whenFreeMemExtIsCalledWithDefaultFreePolicyThenNonBlockingCallIsMade) {
size_t size = 1024;
size_t alignment = 1u;
void *ptr = nullptr;
ze_host_mem_alloc_desc_t hostDesc = {};
ze_result_t result = context->allocHostMem(&hostDesc,
size, alignment, &ptr);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_NE(nullptr, ptr);
ze_memory_free_ext_desc_t memFreeDesc = {};
result = context->freeMemExt(&memFreeDesc, ptr);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
SVMAllocsManagerFreeExtMock *memManager = reinterpret_cast<SVMAllocsManagerFreeExtMock *>(currSvmAllocsManager);
EXPECT_EQ(0u, memManager->blockingCallsMade);
}
struct SVMAllocsManagerOutOFMemoryMock : public NEO::SVMAllocsManager {
SVMAllocsManagerOutOFMemoryMock(MemoryManager *memoryManager) : NEO::SVMAllocsManager(memoryManager, false) {}
void *createUnifiedMemoryAllocation(size_t size,
@ -362,9 +487,6 @@ struct SVMAllocsManagerOutOFMemoryMock : public NEO::SVMAllocsManager {
}
};
struct DriverHandleOutOfMemoryMock : public DriverHandleImp {
};
struct OutOfMemoryTests : public ::testing::Test {
void SetUp() override {
NEO::MockCompilerEnableGuard mock(true);
@ -374,7 +496,7 @@ struct OutOfMemoryTests : public ::testing::Test {
neoDevice->executionEnvironment->rootDeviceEnvironments[0]->builtins.reset(mockBuiltIns);
NEO::DeviceVector devices;
devices.push_back(std::unique_ptr<NEO::Device>(neoDevice));
driverHandle = std::make_unique<DriverHandleOutOfMemoryMock>();
driverHandle = std::make_unique<DriverHandleImp>();
driverHandle->initialize(std::move(devices));
prevSvmAllocsManager = driverHandle->svmAllocsManager;
currSvmAllocsManager = new SVMAllocsManagerOutOFMemoryMock(driverHandle->memoryManager);
@ -395,7 +517,7 @@ struct OutOfMemoryTests : public ::testing::Test {
}
NEO::SVMAllocsManager *prevSvmAllocsManager;
NEO::SVMAllocsManager *currSvmAllocsManager;
std::unique_ptr<DriverHandleOutOfMemoryMock> driverHandle;
std::unique_ptr<DriverHandleImp> driverHandle;
NEO::MockDevice *neoDevice = nullptr;
L0::Device *device = nullptr;
std::unique_ptr<ContextImp> context;

View File

@ -131,7 +131,7 @@ class SVMAllocsManager {
const UnifiedMemoryProperties &unifiedMemoryProperties);
void setUnifiedAllocationProperties(GraphicsAllocation *allocation, const SvmAllocationProperties &svmProperties);
SvmAllocationData *getSVMAlloc(const void *ptr);
bool freeSVMAlloc(void *ptr, bool blocking);
MOCKABLE_VIRTUAL bool freeSVMAlloc(void *ptr, bool blocking);
bool freeSVMAlloc(void *ptr) { return freeSVMAlloc(ptr, false); }
void insertSVMAlloc(const SvmAllocationData &svmData);
void removeSVMAlloc(const SvmAllocationData &svmData);