OpenCL 缓冲区对象映射

除了可使用读/写函数在主机与设备间拷贝数据之外,OpenCL还提供了把设备上的存储器对象映射到主机可访问的内存区域。一旦映射确定后,可以在主机端通过指针读取或修改设备存储器对象的值。对于缓冲区对象和图像对象都可以映射。

缓冲区对象映射

可以使用如下函数来映射缓冲区对象到主机内存区域:

void *clEnqueueMapBuffer (cl_command_queue command_queue,
                              cl_mem buffer,
                              cl_bool blocking_map,
                              cl_map_flags map_flags,
                              size_t offset,
                              size_t size,
                              cl_uint num_events_in_wait_list,
                              const cl_event *event_wait_list,
                              cl_event *event,
                              cl_int *errcode_ret)
  • 参数command_queue为一个有效的主机命令队列。

  • 参数blocking_map表明此映射是阻塞的还是非阻塞的。如果blocking_map为CL_TRUE,即表示映射命令是阻塞的,直到映射完成,函数才会返回。应用可以用返回的指针访问所映射区域的内容;如果blocking_map为CL_FALSE,即映射为非阻塞的,直到映射命令完成后才能使用返回的指针。参数event会返回一个事件对象,可用来查询映射命令的执行情况。在完成映射后,应用才可以使用返回的指针访问映射区域的内容。

  • 参数map_f lags为位域,用于描述映射区域的状态。详细见下表。
    cl_map_flags支持列表

  • 参数offset和size为所要映射的区域在缓冲区对象中的偏移量和大小,单位为字节。其余参数与5.4.1节中同名参数意义一样,在此就不赘述。

函数clEnqueueMapBuffer实现把缓冲区对象映射到主机可访问的内存区域。//创建上下文和命令队列

buffer = clCreateBuffer(context,
CL_MEM_READ_WRITE | CL_MEM_ALLOC_HOST_PTR,
                            sizseof(float) * NUM_ELEMENTS, &err);
cl_float *inputData = (cl_float *)clEnqueueMapBuffer(cmdqueue,
                          buffer, CL_TRUE,
                          CL_MAP_WRTTE, 0, sizeof(float) * NUM_ELEMENTS,
                          0, NULL, NULL,
                          &err);
//对inputData写入操作
err = clEnqueueUnmapMemObject(cmdqueue, buffer, inputData, 0,
                                    NULL, NULL);
//执行内核
cl_float *outData = (cl_float *)clEnqueueMapBuffer(cmdqueue,
                        buffer, CL_TRUE,
                        CL_MAP_REA, 0, sizeof(float) * NUM_ELEMENTS, 0,
                        NULL, NULL,
                        &err);
//对outData操作
err = clEnqueueUnmapMemObject(cmdqueue, buffer, outData, 0, NULL,
                                    NULL);

在例子中,我们使用CL_MEM_READ_WRITE|CL_MEM_ALLOC_HOST_PTR属性来分配缓冲区对象。把分配好的缓冲区对象通过map()/unmap()来映射或解映射到主机,避免了数据在主机与设备间来回拷贝。分配示意图如下图所示。
利用clCreateBuffer(CL_MEM_ALLOC_HOST_PTR)创建存储器对象

OpenCL默认假设主机与GPU的内存是各自独立的,分配缓冲区将会牵涉数据拷贝问题。对于AMD APU设备或者ARM Mali设备,主机与GPU共享内存,如果采用在主机与设备上分配缓冲区,这显然是浪费时间和功耗的。我们可以使用如下代码来避免数据拷贝:

#define NUM_ELEMENTS 1000
cl_int err;
cl_context context;
cl_command_queue cmdqueue;
cl_mem buffer;

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程