Skip to content

Commit d0a32b1

Browse files
Fix: svm pointer caching
Given a following sequence of setting kernel arg svm pointers: A, nullptr, A the kernel arg was not being set to A Related-To: NEO-6895 Signed-off-by: Dominik Dabek <dominik.dabek@intel.com>
1 parent 87a016a commit d0a32b1

File tree

7 files changed

+66
-3
lines changed

7 files changed

+66
-3
lines changed

level_zero/core/source/kernel/kernel_imp.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,9 +557,9 @@ ze_result_t KernelImp::setArgBuffer(uint32_t argIndex, size_t argSize, const voi
557557
const auto driverHandle = static_cast<DriverHandleImp *>(device->getDriverHandle());
558558
const auto svmAllocsManager = driverHandle->getSvmAllocsManager();
559559
const auto allocationsCounter = svmAllocsManager->allocationsCounter.load();
560+
const auto &argInfo = this->kernelArgInfos[argIndex];
560561
NEO::SvmAllocationData *allocData = nullptr;
561562
if (argVal != nullptr) {
562-
const auto &argInfo = this->kernelArgInfos[argIndex];
563563
const auto requestedAddress = *reinterpret_cast<void *const *>(argVal);
564564
if (argInfo.allocId > 0 && requestedAddress == argInfo.value) {
565565
bool reuseFromCache = false;
@@ -578,12 +578,17 @@ ze_result_t KernelImp::setArgBuffer(uint32_t argIndex, size_t argSize, const voi
578578
}
579579
}
580580
}
581+
} else {
582+
if (argInfo.isSetToNullptr) {
583+
return ZE_RESULT_SUCCESS;
584+
}
581585
}
582586

583587
const auto &allArgs = kernelImmData->getDescriptor().payloadMappings.explicitArgs;
584588
const auto &currArg = allArgs[argIndex];
585589
if (currArg.getTraits().getAddressQualifier() == NEO::KernelArgMetadata::AddrLocal) {
586590
slmArgSizes[argIndex] = static_cast<uint32_t>(argSize);
591+
kernelArgInfos[argIndex] = KernelArgInfo{nullptr, 0, 0, false};
587592
UNRECOVERABLE_IF(NEO::isUndefinedOffset(currArg.as<NEO::ArgDescPointer>().slmOffset));
588593
auto slmOffset = *reinterpret_cast<uint32_t *>(crossThreadData.get() + currArg.as<NEO::ArgDescPointer>().slmOffset);
589594
slmOffset += static_cast<uint32_t>(argSize);
@@ -610,6 +615,7 @@ ze_result_t KernelImp::setArgBuffer(uint32_t argIndex, size_t argSize, const voi
610615
const auto &arg = kernelImmData->getDescriptor().payloadMappings.explicitArgs[argIndex].as<NEO::ArgDescPointer>();
611616
uintptr_t nullBufferValue = 0;
612617
NEO::patchPointer(ArrayRef<uint8_t>(crossThreadData.get(), crossThreadDataSize), arg, nullBufferValue);
618+
kernelArgInfos[argIndex] = KernelArgInfo{nullptr, 0, 0, true};
613619
return ZE_RESULT_SUCCESS;
614620
}
615621
const auto requestedAddress = *reinterpret_cast<void *const *>(argVal);
@@ -637,7 +643,7 @@ ze_result_t KernelImp::setArgBuffer(uint32_t argIndex, size_t argSize, const voi
637643
}
638644

639645
const uint32_t allocId = allocData ? allocData->getAllocId() : 0u;
640-
kernelArgInfos[argIndex] = KernelArgInfo{requestedAddress, allocId, allocationsCounter};
646+
kernelArgInfos[argIndex] = KernelArgInfo{requestedAddress, allocId, allocationsCounter, false};
641647

642648
return setArgBufferWithAlloc(argIndex, gpuAddress, alloc);
643649
}

level_zero/core/source/kernel/kernel_imp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ struct KernelArgInfo {
2121
const void *value;
2222
uint32_t allocId;
2323
uint32_t allocIdMemoryManagerCounter;
24+
bool isSetToNullptr = false;
2425
};
2526

2627
struct KernelImp : Kernel {

level_zero/core/test/unit_tests/sources/kernel/test_kernel.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,23 @@ TEST_F(SetKernelArgCacheTest, givenValidBufferArgumentWhenSetMultipleTimesThenSe
147147
EXPECT_EQ(ZE_RESULT_SUCCESS, mockKernel.setArgBuffer(0, sizeof(secondSvmAllocation), &secondSvmAllocation));
148148
EXPECT_EQ(++callCounter, mockKernel.setArgBufferWithAllocCalled);
149149

150-
//same value but no svmData - ZE_RESULT_ERROR_INVALID_ARGUMENT
150+
//nullptr - not called, argInfo is updated
151+
EXPECT_FALSE(mockKernel.kernelArgInfos[0].isSetToNullptr);
152+
EXPECT_EQ(ZE_RESULT_SUCCESS, mockKernel.setArgBuffer(0, sizeof(nullptr), nullptr));
153+
EXPECT_EQ(callCounter, mockKernel.setArgBufferWithAllocCalled);
154+
EXPECT_TRUE(mockKernel.kernelArgInfos[0].isSetToNullptr);
155+
156+
//nullptr again - not called
157+
EXPECT_EQ(ZE_RESULT_SUCCESS, mockKernel.setArgBuffer(0, sizeof(nullptr), nullptr));
158+
EXPECT_EQ(callCounter, mockKernel.setArgBufferWithAllocCalled);
159+
EXPECT_TRUE(mockKernel.kernelArgInfos[0].isSetToNullptr);
160+
161+
//same value as before nullptr - called, argInfo is updated
162+
EXPECT_EQ(ZE_RESULT_SUCCESS, mockKernel.setArgBuffer(0, sizeof(secondSvmAllocation), &secondSvmAllocation));
163+
EXPECT_EQ(++callCounter, mockKernel.setArgBufferWithAllocCalled);
164+
EXPECT_FALSE(mockKernel.kernelArgInfos[0].isSetToNullptr);
165+
166+
// same value but no svmData - ZE_RESULT_ERROR_INVALID_ARGUMENT
151167
svmAllocsManager->freeSVMAlloc(secondSvmAllocation);
152168
++svmAllocsManager->allocationsCounter;
153169
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, mockKernel.setArgBuffer(0, sizeof(secondSvmAllocation), &secondSvmAllocation));

opencl/source/api/api.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4900,6 +4900,11 @@ cl_int CL_API_CALL clSetKernelArgSVMPointer(cl_kernel kernel,
49004900
}
49014901
}
49024902
}
4903+
} else {
4904+
if (pMultiDeviceKernel->getKernelArguments()[argIndex].isSetToNullptr) {
4905+
TRACING_EXIT(clSetKernelArgSVMPointer, &retVal);
4906+
return CL_SUCCESS;
4907+
}
49034908
}
49044909

49054910
DBG_LOG_INPUTS("kernel", kernel, "argIndex", argIndex, "argValue", argValue);

opencl/source/kernel/kernel.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,7 @@ cl_int Kernel::setArgSvmAlloc(uint32_t argIndex, void *svmPtr, GraphicsAllocatio
931931
storeKernelArg(argIndex, SVM_ALLOC_OBJ, svmAlloc, svmPtr, sizeof(uintptr_t));
932932
kernelArguments[argIndex].allocId = allocId;
933933
kernelArguments[argIndex].allocIdMemoryManagerCounter = allocId ? this->getContext().getSVMAllocsManager()->allocationsCounter.load() : 0u;
934+
kernelArguments[argIndex].isSetToNullptr = nullptr == svmPtr;
934935
if (!kernelArguments[argIndex].isPatched) {
935936
patchedArgumentsNum++;
936937
kernelArguments[argIndex].isPatched = true;

opencl/source/kernel/kernel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ class Kernel : public ReferenceTrackedObject<Kernel> {
6969
bool isStatelessUncacheable = false;
7070
uint32_t allocId;
7171
uint32_t allocIdMemoryManagerCounter;
72+
bool isSetToNullptr = false;
7273
};
7374

7475
enum class TunningStatus {

opencl/test/unit_test/api/cl_set_kernel_arg_svm_pointer_tests.inl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,39 @@ TEST_F(clSetKernelArgSVMPointerTests, GivenSvmAndValidArgValueWhenSettingSameKer
298298
EXPECT_EQ(callCounter, pMockKernel->setArgSvmAllocCalls);
299299
++mockSvmManager->allocationsCounter;
300300

301+
// nullptr - called
302+
EXPECT_FALSE(pMockKernel->getKernelArguments()[0].isSetToNullptr);
303+
retVal = clSetKernelArgSVMPointer(
304+
pMockMultiDeviceKernel, // cl_kernel kernel
305+
0, // cl_uint arg_index
306+
nullptr // const void *arg_value
307+
);
308+
EXPECT_EQ(CL_SUCCESS, retVal);
309+
EXPECT_EQ(++callCounter, pMockKernel->setArgSvmAllocCalls);
310+
EXPECT_TRUE(pMockKernel->getKernelArguments()[0].isSetToNullptr);
311+
++mockSvmManager->allocationsCounter;
312+
313+
// nullptr again - not called
314+
retVal = clSetKernelArgSVMPointer(
315+
pMockMultiDeviceKernel, // cl_kernel kernel
316+
0, // cl_uint arg_index
317+
nullptr // const void *arg_value
318+
);
319+
EXPECT_EQ(CL_SUCCESS, retVal);
320+
EXPECT_EQ(callCounter, pMockKernel->setArgSvmAllocCalls);
321+
EXPECT_TRUE(pMockKernel->getKernelArguments()[0].isSetToNullptr);
322+
++mockSvmManager->allocationsCounter;
323+
324+
// same value as before nullptr - called
325+
retVal = clSetKernelArgSVMPointer(
326+
pMockMultiDeviceKernel, // cl_kernel kernel
327+
0, // cl_uint arg_index
328+
nextPtrSvm // const void *arg_value
329+
);
330+
EXPECT_EQ(CL_SUCCESS, retVal);
331+
EXPECT_EQ(++callCounter, pMockKernel->setArgSvmAllocCalls);
332+
++mockSvmManager->allocationsCounter;
333+
301334
DebugManagerStateRestore stateRestorer;
302335
DebugManager.flags.EnableSharedSystemUsmSupport.set(1);
303336
mockSvmManager->freeSVMAlloc(nextPtrSvm);

0 commit comments

Comments
 (0)