将不连续的内存发送到 OpenCL 中的缓冲区

问题描述

假设我有一个数组 A[200][200]。

如果我想将 A[0:100][0:200] 发送到 GPU 缓冲区, 我只是打电话

clEnqueueWriteBuffer(queue,buffer,CL_TRUE,100 * 200 * sizeof(float),A,NULL,NULL);

但是如果我想将 A[0:200][0:100] 发送到 GPU 缓冲区,我无法调用上述函数,因为 A[0:200][0:100] 是不连续的。

有没有什么明智的方法可以发送上述数据?

解决方法

您可以使用 clEnqueueWriteBufferRect

cl_int clEnqueueWriteBufferRect(    
    cl_command_queue command_queue,cl_mem buffer,cl_bool blocking_write,const size_t buffer_origin[3],const size_t host_origin[3],const size_t region[3],size_t buffer_row_pitch,size_t buffer_slice_pitch,size_t host_row_pitch,size_t host_slice_pitch,void *ptr,cl_uint num_events_in_wait_list,const cl_event *event_wait_list,cl_event *event
)

就您而言,最相关的参数是 host_originregionhost_row_pitch

host_row_pitch:内存中每一行的字节大小。 数组 float A[200][200] 描述了一个行距为 200 * sizeof(float) 的主要二维数组。

host_origin:您希望发送到设备的主机数据的起始位置。假设 ND 阵列。您的原点只是 size_t[3] {0,0}

host_region:您希望从阵列中复制的 ND 区域。 您所在的区域是 size_t[3] {100,200,1}。

我建议您仔细阅读文档。很容易犯小错误。

另请注意,在发送之前首先将主机数据排列到连续数组中可能更有效。 clEnqueueWriteBuffer 可能会启动 DMA 传输,这对于大型连续内存块会更有效。