Skip to content

Commit 912af26

Browse files
Add support for async destruction of map allocations
- map allocations with CL_MEM_USE_HOST_PTR are still destroyed in place - map allocations are additionally checked for completion on all os contexts Related-To: NEO-5073 Change-Id: I6198ff76704a03412ef648503df8e70fee4bd3be Signed-off-by: Slawomir Milczarek <slawomir.milczarek@intel.com>
1 parent 83ed9d9 commit 912af26

File tree

3 files changed

+164
-6
lines changed

3 files changed

+164
-6
lines changed

opencl/source/mem_obj/mem_obj.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ MemObj::~MemObj() {
7676

7777
for (auto graphicsAllocation : multiGraphicsAllocation.getGraphicsAllocations()) {
7878
auto rootDeviceIndex = graphicsAllocation ? graphicsAllocation->getRootDeviceIndex() : 0;
79+
bool doAsyncDestructions = DebugManager.flags.EnableAsyncDestroyAllocations.get();
7980
if (graphicsAllocation && !associatedMemObject && !isHostPtrSVM && graphicsAllocation->peekReuseCount() == 0) {
8081
memoryManager->removeAllocationFromHostPtrManager(graphicsAllocation);
81-
bool doAsyncDestructions = DebugManager.flags.EnableAsyncDestroyAllocations.get();
8282
if (!doAsyncDestructions) {
8383
needWait = true;
8484
}
@@ -89,7 +89,7 @@ MemObj::~MemObj() {
8989
graphicsAllocation = nullptr;
9090
}
9191
if (!associatedMemObject) {
92-
releaseMapAllocation(rootDeviceIndex);
92+
releaseMapAllocation(rootDeviceIndex, doAsyncDestructions);
9393
}
9494
if (mcsAllocation) {
9595
destroyGraphicsAllocation(mcsAllocation, false);
@@ -319,9 +319,17 @@ void MemObj::releaseAllocatedMapPtr() {
319319
allocatedMapPtr = nullptr;
320320
}
321321

322-
void MemObj::releaseMapAllocation(uint32_t rootDeviceIndex) {
323-
if (mapAllocations.getGraphicsAllocation(rootDeviceIndex) && !isHostPtrSVM) {
324-
destroyGraphicsAllocation(mapAllocations.getGraphicsAllocation(rootDeviceIndex), false);
322+
void MemObj::releaseMapAllocation(uint32_t rootDeviceIndex, bool asyncDestroy) {
323+
auto mapAllocation = mapAllocations.getGraphicsAllocation(rootDeviceIndex);
324+
if (mapAllocation && !isHostPtrSVM) {
325+
if (asyncDestroy && !isValueSet(flags, CL_MEM_USE_HOST_PTR)) {
326+
destroyGraphicsAllocation(mapAllocation, true);
327+
} else {
328+
if (mapAllocation->isUsed()) {
329+
memoryManager->waitForEnginesCompletion(*mapAllocation);
330+
}
331+
destroyGraphicsAllocation(mapAllocation, false);
332+
}
325333
}
326334
}
327335

opencl/source/mem_obj/mem_obj.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class MemObj : public BaseObject<_cl_mem> {
7777

7878
void setHostPtrMinSize(size_t size);
7979
void releaseAllocatedMapPtr();
80-
void releaseMapAllocation(uint32_t rootDeviceIndex);
80+
void releaseMapAllocation(uint32_t rootDeviceIndex, bool asyncDestroy);
8181

8282
bool isMemObjZeroCopy() const;
8383
bool isMemObjWithHostPtrSVM() const;

opencl/test/unit_test/mem_obj/mem_obj_destruction_tests.cpp

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,156 @@ HWTEST_P(MemObjSyncDestructionTest, givenMemObjWithDestructableAllocationWhenAsy
313313
EXPECT_TRUE(allocationList.peekIsEmpty());
314314
}
315315

316+
HWTEST_P(MemObjSyncDestructionTest, givenMemObjWithMapAllocationWhenAsyncDestructionsAreDisabledThenWaitForCompletionWithTimeoutOnMapAllocation) {
317+
auto isMapAllocationUsed = GetParam();
318+
319+
auto mockCsr = new ::testing::NiceMock<MyCsr<FamilyType>>(*device->executionEnvironment);
320+
device->resetCommandStreamReceiver(mockCsr);
321+
*mockCsr->getTagAddress() = 0;
322+
323+
GraphicsAllocation *mapAllocation = nullptr;
324+
AllocationProperties properties{device->getRootDeviceIndex(),
325+
true,
326+
MemoryConstants::pageSize,
327+
GraphicsAllocation::AllocationType::MAP_ALLOCATION,
328+
false,
329+
context->getDeviceBitfieldForAllocation()};
330+
mapAllocation = memoryManager->allocateGraphicsMemoryWithProperties(properties, nullptr);
331+
memObj->setMapAllocation(mapAllocation);
332+
333+
if (isMapAllocationUsed) {
334+
memObj->getMapAllocation(device->getRootDeviceIndex())->updateTaskCount(taskCountReady, contextId);
335+
}
336+
337+
auto waitForCompletionWithTimeoutMock = [=](bool enableTimeout, int64_t timeoutMs, uint32_t taskCountToWait) -> bool { return true; };
338+
auto osContextId = mockCsr->getOsContext().getContextId();
339+
340+
ON_CALL(*mockCsr, waitForCompletionWithTimeout(::testing::_, ::testing::_, ::testing::_))
341+
.WillByDefault(::testing::Invoke(waitForCompletionWithTimeoutMock));
342+
343+
if (isMapAllocationUsed) {
344+
EXPECT_CALL(*mockCsr, waitForCompletionWithTimeout(::testing::_, TimeoutControls::maxTimeout, mapAllocation->getTaskCount(osContextId)))
345+
.Times(1);
346+
} else {
347+
EXPECT_CALL(*mockCsr, waitForCompletionWithTimeout(::testing::_, ::testing::_, ::testing::_))
348+
.Times(0);
349+
}
350+
351+
delete memObj;
352+
}
353+
354+
HWTEST_P(MemObjSyncDestructionTest, givenMemObjWithMapAllocationWhenAsyncDestructionsAreDisabledThenMapAllocationIsNotDeferred) {
355+
auto hasMapAllocation = GetParam();
356+
357+
auto mockCsr = new ::testing::NiceMock<MyCsr<FamilyType>>(*device->executionEnvironment);
358+
device->resetCommandStreamReceiver(mockCsr);
359+
*mockCsr->getTagAddress() = 0;
360+
361+
GraphicsAllocation *mapAllocation = nullptr;
362+
if (hasMapAllocation) {
363+
AllocationProperties properties{device->getRootDeviceIndex(),
364+
true,
365+
MemoryConstants::pageSize,
366+
GraphicsAllocation::AllocationType::MAP_ALLOCATION,
367+
false,
368+
context->getDeviceBitfieldForAllocation()};
369+
mapAllocation = memoryManager->allocateGraphicsMemoryWithProperties(properties, nullptr);
370+
memObj->setMapAllocation(mapAllocation);
371+
372+
memObj->getMapAllocation(device->getRootDeviceIndex())->updateTaskCount(taskCountReady, contextId);
373+
}
374+
375+
makeMemObjUsed();
376+
377+
auto &allocationList = mockCsr->getTemporaryAllocations();
378+
EXPECT_TRUE(allocationList.peekIsEmpty());
379+
380+
delete memObj;
381+
382+
EXPECT_TRUE(allocationList.peekIsEmpty());
383+
}
384+
385+
HWTEST_P(MemObjAsyncDestructionTest, givenMemObjWithMapAllocationWithoutMemUseHostPtrFlagWhenAsyncDestructionsAreEnabledThenMapAllocationIsDeferred) {
386+
auto hasMapAllocation = GetParam();
387+
388+
auto mockCsr = new ::testing::NiceMock<MyCsr<FamilyType>>(*device->executionEnvironment);
389+
device->resetCommandStreamReceiver(mockCsr);
390+
*mockCsr->getTagAddress() = 0;
391+
392+
GraphicsAllocation *mapAllocation = nullptr;
393+
if (hasMapAllocation) {
394+
AllocationProperties properties{device->getRootDeviceIndex(),
395+
true,
396+
MemoryConstants::pageSize,
397+
GraphicsAllocation::AllocationType::MAP_ALLOCATION,
398+
false,
399+
context->getDeviceBitfieldForAllocation()};
400+
mapAllocation = memoryManager->allocateGraphicsMemoryWithProperties(properties, nullptr);
401+
memObj->setMapAllocation(mapAllocation);
402+
403+
memObj->getMapAllocation(device->getRootDeviceIndex())->updateTaskCount(taskCountReady, contextId);
404+
}
405+
406+
makeMemObjUsed();
407+
408+
auto &allocationList = mockCsr->getTemporaryAllocations();
409+
EXPECT_TRUE(allocationList.peekIsEmpty());
410+
411+
delete memObj;
412+
413+
EXPECT_FALSE(allocationList.peekIsEmpty());
414+
415+
if (hasMapAllocation) {
416+
EXPECT_EQ(allocation, allocationList.peekHead());
417+
EXPECT_EQ(mapAllocation, allocationList.peekTail());
418+
} else {
419+
EXPECT_EQ(allocation, allocationList.peekHead());
420+
EXPECT_EQ(allocation, allocationList.peekTail());
421+
}
422+
}
423+
424+
HWTEST_P(MemObjAsyncDestructionTest, givenMemObjWithMapAllocationWithMemUseHostPtrFlagWhenAsyncDestructionsAreEnabledThenMapAllocationIsNotDeferred) {
425+
auto hasMapAllocation = GetParam();
426+
427+
auto mockCsr = new ::testing::NiceMock<MyCsr<FamilyType>>(*device->executionEnvironment);
428+
device->resetCommandStreamReceiver(mockCsr);
429+
*mockCsr->getTagAddress() = 0;
430+
431+
GraphicsAllocation *mapAllocation = nullptr;
432+
char *hostPtr = (char *)alignedMalloc(MemoryConstants::pageSize, MemoryConstants::pageSize64k);
433+
if (hasMapAllocation) {
434+
AllocationProperties properties{device->getRootDeviceIndex(),
435+
false,
436+
MemoryConstants::pageSize,
437+
GraphicsAllocation::AllocationType::MAP_ALLOCATION,
438+
false,
439+
context->getDeviceBitfieldForAllocation()};
440+
mapAllocation = memoryManager->allocateGraphicsMemoryWithProperties(properties, hostPtr);
441+
memObj->setMapAllocation(mapAllocation);
442+
443+
memObj->getMapAllocation(device->getRootDeviceIndex())->updateTaskCount(taskCountReady, contextId);
444+
}
445+
446+
makeMemObjUsed();
447+
448+
auto &allocationList = mockCsr->getTemporaryAllocations();
449+
EXPECT_TRUE(allocationList.peekIsEmpty());
450+
451+
delete memObj;
452+
453+
EXPECT_FALSE(allocationList.peekIsEmpty());
454+
455+
if (hasMapAllocation) {
456+
EXPECT_EQ(allocation, allocationList.peekHead());
457+
EXPECT_EQ(allocation, allocationList.peekHead());
458+
} else {
459+
EXPECT_EQ(allocation, allocationList.peekHead());
460+
EXPECT_EQ(allocation, allocationList.peekTail());
461+
}
462+
463+
alignedFree(hostPtr);
464+
}
465+
316466
INSTANTIATE_TEST_CASE_P(
317467
MemObjTests,
318468
MemObjAsyncDestructionTest,

0 commit comments

Comments
 (0)