OpenCL编程步骤(五):创建缓冲对象

   
   
   
   
cl_mem clCreateBuffer(
cl_context context,
cl_mem_flags flags,
size_t size,
void *host_ptr,
cl_int *errcode_ret)
这个函数是用来创建缓存对象。
context是OpenCL上下文,用来创建缓存对象。
flags是位域,用来表明如何分配以及怎样使用所分配的缓存对象。如果flags的值为零,则使用缺省值CL_MEM_READ_WRITE。

cl_mem_flags
CL_MEM_READ_WRITE
表明此内存对象可读可写。这是缺省值。
CL_MEM_WRITE_ONLY
只能写不能读,对这种内存对象的读操作是未定义的。CL_MEM_READ_WRITE和CL_MEM_READ_ONLY是互斥的。
CL_MEM_READ_ONLY
只能读不能写, 对这种内存对象的写操作是未定义的。CL_MEM_READ_WRITE和CL_MEM_WRITE_ONLY是互斥的。
CL_MEM_USE_HOST_PTR
仅当host_ptr不是NULL时才有效。它表明应用想让OpenCL操作使用host_ptr所引用的内存来存储内存对象的内容。
OpenCL操作可以在设备内存中保存一根host_ptr所引用的内存用作缓存。内核在设备上执行时可以使用这份拷贝。
如果多个缓存对象由同一host_ptr创建,或者有重叠区域,那么OpenCL命令操作这些缓存对象是,其结果是未定义的。
用CL_MEM_USE_HOST_PTR创建内存对象时,host_ptr要有对齐规则。
CL_MEM_ALLOC_HOST_PTR
表明应用想让OpenCL操作在主机可以访问的内存中分配内存。
与CL_MEM_USE_HOST_PTR互斥。
CL_MEM_COPY_HOST_PTR
仅当host_ptr不是NULL时才有效。它表明应用想让OpenCL操作使用host_ptr所引用的内存来为内存对象分配内存并拷贝数据。
它与CL_MEM_USE_HOST_PTR互斥。
它与CL_MEM_ALLOC_HOST_PTR一起使用时,可以对 由主机可访问内存 分配的cl_mem对象进行初始化。
CL_MEM_HOST_WRITE_ONLY
表明主机指挥对此内存映象进行写入。可用来对主机的写操作进行优化。
CL_MEM_HOST_READ_ONLY
表明主机指挥对此内存对象进行读取。
他与CL_MEM_HOST_WRITE_ONLY互斥。
CL_MEM_HOST_NO_ACCESS
表明主机不会对此内存对象进行读写。
CL_MEM_HOST_WRITE_ONLY与CL_MEM_HOST_READ_ONLY都与CL_MEM_HOST_NO_ACCESS互斥。

size即所要分配缓存对象的大小,单位:字节。
host_ptr指向可能已经有应用分配好了的缓存数据。其大小必须大于或等于size。
errcode_ret用来返回错误码。如果为NULL,则忽略。
如果clCreateBuffer成功创建了缓存对象,则返回相应的地址,并将errcode_ret置为CL_SUCCESS。否则返回NULL,并将errcode_ret置为下列错误码之一:
  • CL_INVALID_CONTEXT,无效的上下文context。
  • CL__INVALID_VALUE,falgs的值不是所支持的值。
  • CL_INVALID_BUFFER_SIZE, size的大小为0。
  • CL_INVALID_HOST_PTR,如果host_ptr是NULL,但是flags中设置了CL_MEM_USE_HSOT_PTR或CL_MEM_COPY_HSOT_PTR;或者host_ptr不是NULL,但是flags中没有设置CL_MEM_USE_HOST_PTR或CL_MEM_COPY_HOST_PTR。
  • CL_MEM_OBJECT_ALLOCATION_FAILURE,为缓存对象分配内存失败。
  • CL_OUT_OF_RESOURCES,为设备上的OpenCL操作分配内存失败。
  • CL_OUT_OF_HOST_MEMORY,为主机上的OpenCL操作分配内存失败。

2、创建子缓冲区
    
    
    
    
cl_mem clCreateSubBuffer(
cl_mem buffer,
cl_mem_flags flags,
cl_buffer_create_type buffer_create_type,
const void *buffer_create_info,
cl_int *errcode_ret)
此函数可以由一个现有的缓存对象创建一个新的缓存对象,叫做子缓冲对象。
buffer必须是一个有效的缓冲对象,且不能是子缓冲对象。
flags是位域,用来表明如果分配和使用内存对象。同上clCreateBuffer。
buffer_create_type和buffer_create_info表明了所要创建的缓冲对象的类型。
errcode_ret返回错误码。如果为NULL,则忽略。
cl_buffer_create_type
CL_BUFFER_CREATE_TYPE_REGION
用buffer中的特定区域创建缓冲对象。
buffer_create_info指向如下的数据结构:
struct  _cl_buffer_region {
                 size_t  origin;
                 size_t  size;
}cl_buffer_region;

(origin, size)就是buffer中的偏移量和字节数。
如果buffer是用CL_MEM_USE_HOST_PTR创建的,所返回缓冲对象的host_ptr就是host_ptr + origin。
所返回的缓冲对象引用了为buffer分配的数据存储空间,并指向其中的特定区域(origin, size)。
如果在buffer中,区域(origin, size)越界了,则会在errcode_ret中返回CL_INVALID_VALUE。
如果size为0,则返回CL_INVALID_BUFFER_SIZE。
如果与buffer相关联的上下文中没有一个设备的CL_DEVICE_MEM_BASE_ADDR_ALIGN与origin对齐,则会返回CL_MISALIGNED_SUB_BUFFER_OFFSET。
    
3、查询内存对象的相关信息
    
    
    
    
cl_int clGetMemObjectInfo(cl_mem memobj,
cl_mem_info param_name,
size_t param_value_size,
void *param_value,
size_t param_value_size_ret)
memobj指定所要查询的内存对象。
param_name指定所要查询的信息。
param_value指向的内存用来存放查询结果。如果为NULL,则忽略。
param_value_size即param_value所指内存块的大小,单位字节。其值必须大于等于param_name的类型的大小。如果为NULL,则忽略。
param_value_size_ret返回查询结果的实际大小。如果为NULL,则忽略。
cl_mem_info    返回类型    描述   
CL_MEM_TYPE    cl_mem_object_type   
返回下列值中的一个:
CL_MEM_OBJECT_BUFFER,memobj使用clCreate{Buffer | SubBuffer}创建的。
cl_image_desc.image_type,用clCreateImage创建
CL_MEM_FLAGS cl_mem_flags 返回用 clCreate{Buffer | SubBuffer}创建的memobj时所制定的参数flags。
如果memobj是子缓冲对象,则同时会返回父对象所继承的内存访问限定符。
CL_MEM_SIZE size_t 返回memobj中用于数据存储的内存的实际大小,单位:字节。
CL_MEM_HOST_PTR void * 如果memobj是由   clCreate{Buffer | Image}创建,且mem_flags中设置了CL_MEM_USE_HOST_PTR则返回参数host_ptr的值,否则返回NULL。
如果memobj是由clCreateSubBuffer创建,则返回host_ptr+origin。否则返回NULL。
CL_MEM_MAP_COUT cl_uint 映射当前缓冲的次数。
CL_MEM_REFERENCE_COUNT cl_uint 返回memobj的引用技术。
CL_MEM_CONTEXT cl_context 返回创建内存对象时所指定的上下文。
CL_MEM_ASSOCIATED_MEMOBJECT cl_mem 返回memobj的父对象。即clCreateSubBuffer的参数buffer。否则返回NULL。
CL_MEM_OFFSET size_t 如果memobj是由 clCreateSubBuffer创建的自缓冲对象,则返回其偏移量,否则返回0。


4、读、写及拷贝缓冲对象
    
    
    
    
cl_int clEnqueueReadBuffer( cl_command_queue command_queue,
cl_mem buffer,
cl_bool blocking_read,
size_t offset,
size_t cb,
void *ptr,
cl_uint mem_events_in_wait_list,
const cl_event *event_wait_list,
cl_event *event)
     
     
     
     
cl_int clEnqueueWriteBuffer( cl_command_queue command_queue,
cl_mem buffer,
cl_bool blocking_write,
size_t offset,
size_t cb,
void *ptr,
cl_uint mem_events_in_wait_list,
const cl_event *event_wait_list,
cl_event *event)
这两个函数会将一个用于读写缓冲对象的命令入队,此命令可以将缓冲对象的内容读到主机内存中( clEnqueueReadBuffer), 或者由主机内存写入到缓冲对象中( clEnqueueWriteBuffer)。
  • command_queue就是命令要入的队列。command_queue和buffer必须是由同一个OpenCL上下文创建的。
  • buffer是一个缓冲对象。
  • blocking_read和blocking_write表明读写操作是阻塞的还是非阻塞的。
    • 如果blocking_read是CL_TRUE,即读命令是阻塞的,知道buffer中的数据完全拷贝到ptr所指向的内存中后,clEnqueueReadBuffer才会返回
    •  如果blocking_read是CL_FALSE,即读命令是非阻塞的,clEnqueueReadBuffer将此命令入队后就会返回。只有等到读命令执行完毕,才能继续使用ptr所指向的内容。参数event会返回一个事件对象,可以用来查询读命令的执行情况。读命令完成后,应用就可以继续使用ptr所指向的内容了。
    • 如果blocking_write是CL_TRUE,OpenCL操作会拷贝ptr所指向的数据,并将一个写命令入队。当clEnqueueWriteBuffer返回后,应用就可以继续使用ptr所指向的内存了。
    • 如果blocking_write是CL_FALSE,OpenCL操作会用ptr实施非阻塞的写操作。既然非阻塞,操作就可以立即返回。返回后,应用还不能立刻使用prt所指向的内存。参数event会返回一个事件对象,可以用来查询写命令的执行情况。写命令完成后,应用就可以重新使用prt所指向的内存了。    
  • offset是读写区域在缓冲对象中的偏移量,单位:字节。
  • cb是要读写的数据的大小,单位:字节。
  • ptr指向主机中的一块内存,用作读命令的数据源,以及写命令的目的地。
  • event_wait_list和num_events_in_wait_list中列出了执行此命令前要等待的事件。如果event_wait_list是NULL,则无须等待任何事件,并且num_events_in_wait_list必须是0。如果event_wait_list不是NULL,则其中的事件充当同步点,并且必须与command_queue位于同一个上下文中。此函数返回后,就可以回收和重新使用event_wait_list所关联的设备。
  • event会返回一个事件对象,用来标志此读写命令,可以用来查询或等待此命令完成。如果event是NULL,就没有办法查询此命令的状态或等待其完成了。如果event_wait_list和event都不是NULL,event不能属于event_wait_list。

5、拷贝内存
      
      
      
      
cl_int clEnqueueCopyBuffer(
cl_command_queue command_queue,
cl_mem src_buffer,
cl_mem dst_buffer,
size_t src_offset
size_t src_offset,
size_t size,
cl_uint num_events_in_wait_list,
const cl_event *event_wait_list,
cl_event *event)

这个函数讲一个拷贝命令入队,此命令会讲缓冲对象src_buffer的内容拷贝到dst_buffer中。
    command_queue即拷贝命令所要插入的命令队列。command_queue、src_buffer和dst_buffer必须位于同一OpenCL上下文中。
    src_offset即在src_buffer中的什么位置开始读取数据。
    dst_offset即在dst_buffer中的什么位置开始写入数据。
    size即所要拷贝数据的字节数。
    event_wait_list和num_events_in_wait_list中列出了执行此命令前要等待的时间。如果event_wait_list是NULL,则无须等待任何事件,并且num_events_in_wait_list必须是0.如果event_wait_list不是NULL,则其中所有事件都必须是有效的,并且num_events_in_wait_list必须大于0。event_wait_list中事件充当同步点,并且必须在同一个上下文中。此函数返回后,就可以回收并重新使用event_wait_list所关联的内存了。
    event会返回一个事件对象,用来标志此拷贝命令,可用来查询或等待此命令完成。

6、填充缓冲对象
      
      
      
      
cl_int clEnqueueFillBuffer (
cl_command_queue command_queue,
cl_mem buffer,
const void *pattern,
size_t pattern_size,
size_t offset,
size_t size,
cl_uint num_events_in_wait_list,
cosnt cl_event *event_wait_list,
cl_event *event)
此函数所入队的命令可以按给定的方式填充缓冲对象。
    command_queue是这个填充命令所要插入的队列。commad_queue和buffer必须位于同一个OpenCL上下文中。
    buffer是一个缓冲对象。
    pattern指向数据的方式(data pattern),其大小为pattern_size。用pattern填充的区域在buffer中的偏移量为offset,大小是size。数据方式必须是OpenCL所支持的标量或矢量的整数或浮点数类别。
    offset填充区域在buffer中的偏移量,单位:字节。它必须是patter_size的整数倍。
    event_wait_list和num_events_in_wait_list中列出了执行此命令前要等待的时间。如果event_wait_list是NULL,则无须等待任何事件,并且num_events_in_wait_list必须是0.如果event_wait_list不是NULL,则其中所有事件都必须是有效的,并且num_events_in_wait_list必须大于0。event_wait_list中事件充当同步点,并且必须在同一个上下文中。此函数返回后,就可以回收并重新使用event_wait_list所关联的内存了。
    event会返回一个事件对象,用来标志此拷贝命令,可用来查询或等待此命令完成。

7、映射缓冲对象
      
      
      
      
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,
cosnt cl_event *event_wait_list,
cl_event *event,
cl_int *errcode_ret)
此函数所入队的命令会将buffer的某个区域映射到主机的地址空间中,并返回新的地址。
  • command_queue必须是一个有效的命令。
  • blocking_map表明此映射操作是阻塞的还是非阻塞的。
    • blocking_map是CL_TRUE,即映射命令是阻塞的,直到映射完成,clEnqueueMapBuffer才会返回,应用可以返回的指针访问所映射区域的内容。
    • blocking_map是CL_FALSE,即映射命令是非阻塞的,知道映射命令完成后,才能使用返回的指针。参数event会返回一个事件对象,可用来查询映射命令的执行情况。映射命令完成后,应用就可以使用返回的指针访问映射区域的内容了。
  • map_flag是位域。
  • buffer是一个缓冲对象,必须与command_queue位于统一OpenCL上下文中。
  • offset和size是所要映射的区域在缓冲对象中的偏移量和大小,单位都是字节。
  • event_wait_list和num_events_in_wait_list中列出了执行此命令前要等待的时间。如果event_wait_list是NULL,则无须等待任何事件,并且num_events_in_wait_list必须是0.如果event_wait_list不是NULL,则其中所有事件都必须是有效的,并且num_events_in_wait_list必须大于0。event_wait_list中事件充当同步点,并且必须在同一个上下文中。此函数返回后,就可以回收并重新使用event_wait_list所关联的内存了。   
  • event会返回一个事件对象,用来标志此拷贝命令,可用来查询或等待此命令完成。   
  • errcode_ret返回错误码。如果是NULL,则不会返回错误码。

所支持的cl_map_flags
cl_map_flags
CL_MAP_READ
表明所映射区域是用来读的。当clEnqueueMap{Buffer | Image}所入队的命令完成时,保证所返回的指针中所映射区域的内容是最新的。
CL_MAP_WRITE
表明所映射的区域是用来写的。 当clEnqueueMap{Buffer | Image}所入队的命令完成时,保证所返回的指针中所映射区域的内容是最新的。
CL_MAP_WRITE_INVALIDATE_REGION
表明所映射区域是用来写的。所映射区域中的原有内容会被丢弃。一种典型的情况就是主机会复写(overwrite)其内容。此标志告诉操作可以不用保证clEnqueueMap{Buffer | Image} 所返回的指针中所映射区域的内容是最新的,这回极大提升系能。
它与CL_MAP_WRITE是互斥的。

8、解除缓冲区映射
    
    
    
    
cl_int clEnqueueUnmapMemObject (cl_command_queue command_queue,
cl_mem buffer,
void *mapped_pointer,
cl_uint num_events_in_wait_list,
const cl_event *event_wait_list,
cl_event *event)
  • command_queue是一个命令队列,该命令在这个队列中排队。
  • buffer之前映射到mapped_pointer的一个合法的缓冲区对象。
  • mapped_pointer对buffer前一个clEnqueueMapBuffer调用返回的宿主机地址。
  • event_wait_list和num_events_in_wait_list中列出了执行此命令前要等待的时间。如果event_wait_list是NULL,则无须等待任何事件,并且num_events_in_wait_list必须是0.如果event_wait_list不是NULL,则其中所有事件都必须是有效的,并且num_events_in_wait_list必须大于0。event_wait_list中事件充当同步点,并且必须在同一个上下文中。此函数返回后,就可以回收并重新使用event_wait_list所关联的内存了。 
  • event会返回一个事件对象,用来标志此拷贝命令,可用来查询或等待此命令完成。   

你可能感兴趣的:(OpenCL)