如果使用 CL_MEM_USE_HOST_PTR 将变量传递给内核,是否意味着对设备中变量的任何更改也会显示在主机内存中?
我处于使用 CPU 作为设备而不是 GPU 的场景中,因此传递给内核的所有内容都将标记为 CL_MEM_USE_HOST_PTR。
如果这是真的,那么我不再需要将所有内容都读回主机,这非常方便。
如果使用 CL_MEM_USE_HOST_PTR 将变量传递给内核,是否意味着对设备中变量的任何更改也会显示在主机内存中?
我处于使用 CPU 作为设备而不是 GPU 的场景中,因此传递给内核的所有内容都将标记为 CL_MEM_USE_HOST_PTR。
如果这是真的,那么我不再需要将所有内容都读回主机,这非常方便。
您的理解是正确的,除了一个可能的陷阱:文档指出
host_ptr
OpenCL 实现允许缓存设备内存中指向的缓冲区内容。当内核在设备上执行时,可以使用此缓存副本。
这意味着内核对数据执行的更改可能不会立即反映在host_ptr
. 事实上,host_ptr
当它用于缓冲区时,并不能保证包含有效数据。
为了获得有效和最新的数据,您必须强制同步。官方文档对这一刻有点含糊,但缓冲区映射/取消映射确实有效:
如果缓冲区对象是使用
CL_MEM_USE_HOST_PTR
set in 创建的mem_flags
,则host_ptr
指定的 in保证在命令完成clCreateBuffer
时包含正在映射的区域中的最新位 ;clEnqueueMapBuffer
并且返回的指针值clEnqueueMapBuffer
将派生自host_ptr
创建缓冲区对象时指定的值。
这是一个改编自Khronos 论坛帖子的示例:
cl_mem device_output = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, size, original_output, NULL);
// run the kernel
void* pointer = clEnqueueMapBuffer(queue, device_output, CL_TRUE, CL_MAP_READ, size, 0, 0, NULL, NULL, NULL);
// work with 'original_output'
clEnqueueUnmapMemObject(queue, device_output, pointer, 0, NULL, NULL);
clReleaseMemObject(device_output);