我正在尝试分配几个 SVM 缓冲区并使用以下方法将它们传递给 OpenCL 内核。内核运行在 Intel HD Graphics 530 和 NVIDIA GTX 950M 上。我在这些 GPU 上得到了不同的结果,我不确定哪种行为是正确的(也许两者都是?)
- 初始化 OpenCL。
- 通过 3 次 clSVMAlloc() 调用分配 3 个缓冲区(
data0
、data1
、pointers
)。 - 检查 NULL 的结果(这里没有失败)。
- 使用阻塞 clEnqueueSVMMap() 调用映射所有缓冲区 + 检查 CL_SUCCESS(这里没有失败)。
- 填写
data0
和data1
与数据,和pointers
指向data0
的指针和data1
,所以pointers[0] == data0
和pointers[1] == data1
. - 使用 clEnqueueSVMUnmap() 取消映射所有缓冲区 + 检查 CL_SUCCESS(这里没有失败)。
- 使用 clSetKernelArgSVMPointer(...,
data0
) 设置第一个内核参数 + 检查 CL_SUCCESS(这里没有失败)。 - 使用 clSetKernelArgSVMPointer(...,
pointers
) 设置第二个内核参数 + 检查 CL_SUCCESS(这里没有失败)。 - 运行内核并测试结果。
在 NVIDIA 卡上,数据可通过 pointers[0]
获得和 pointers[1]
.这是预期的行为。
在 Intel 芯片上,内存在后面pointers[0]
可用(因为 data0
已设置为内核参数),但内存在 pointers[1]
后面全为零。如果我设置 data1
作为内核参数,然后通过 pointers[1]
可用和背后的内存pointers[0]
变为零。
问题是:英特尔的方法是错误还是功能?我在OpenCL 3.0规范中没有找到任何相关信息。
最佳答案
英特尔工作正常并遵守规范。然而,NVIDIA 更简单。
要解决所讨论的问题,需要不要忘记将一组 SVM 缓冲区传递给内核:
ret = clSetKernelExecInfo(kernel, CL_KERNEL_EXEC_INFO_SVM_PTRS, sizeof(svm_buffers), svm_buffers);
其中 svm_buffers
是指向使用 clSVMAlloc() 调用分配的缓冲区的指针的 void*[]
数组。
OpenCL 规范为带有参数 CL_KERNEL_EXEC_INFO_SVM_PTRS
的 clSetKernelExecInfo
声明了以下内容:
SVM pointers must reference locations contained entirely within buffers that are passed to kernel as arguments, or that are passed through the execution information. Non-argument SVM buffers must be specified by passing pointers to those buffers via clSetKernelExecInfo for coarse-grain and fine- grain buffer SVM allocations but not for finegrain system SVM allocations.
关于pointers - Intel HD Graphics 是否违反了有关 SVM 的 OpenCL 规范?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72807280/