第七章 缓冲区和子缓冲区

创建内存对象以便从宿主机内存向缓冲区内存传入传出数据。内存对象对于使用OpenCL至关重要,包含以下类型:

  • 缓冲区(buffer):1维的字节数组。
  • 子缓冲区(sub-buffer):缓冲区的1维视图。
  • 图像(image):2维或3维结构的数组,其访问操作符有限,另外可以选择不同的格式、采样和钳制恶性。

本章将详细介绍缓冲区和子缓冲区

  • 缓冲区和子缓冲区概述
  • 创建缓冲区和子缓冲区对象
  • 读、写缓冲区和子缓冲区对象
  • 映射缓冲区和子缓冲区对象
  • 查询缓冲区和子缓冲区对象

7.1 内存对象、缓冲区和子缓冲区概述

缓冲区和子缓冲区是OpenCL内存对象的实例。图像对象同样也是内存对象的实例。一般情况下,缓冲区和子缓冲区上的操作与图像操作有所不同,不过有些情况下,使用内存对象的通用操作就足够了。

由于上下文的创建而别针对一个特定的平台,所以不可能创建不同平台设备之间共享的内存对象。如果一个应用程序要使用系统中的所有OpenCL设备,那么在这种情况下,当管理数据时,需要通过宿主机内存空间向给定上下文以及在上下文之间复制数据。

7.2 创建缓冲区和子缓冲区

缓冲区对象是1维的内存资源,可以包含标量、矢量或用户定义的数据类型。缓冲区对象使用以下函数创建:

cl_mem clCreateBuffer(cl_context context,
                                  cl_mem_flags flags,
                                  size_t size,
                                  void* host_ptr,
                                  cl_int* errcode_ref)

 与其他内核参数类似,也是用函数clSetKernelArg将缓冲区作为参数传递到内核,在内核中定义为全局地址空间中一个期望数据类型的指针。一个简单的例子展示如何创建缓冲区,以及如何用它来设置内核参数:

#define NUM_BUFFER_ELEMENTS 100
cl_int errNum;
cl_context context;
cl_kernel kernel;
cl_command_queue queue;
float inputOutput[NUM_BUFFER_ELEMENTS];
cl_mem buffer;

//这里创建上下文、内核和命令队列
buffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(float) * NUM_BUFFER_ELEMENTS, &errNUM);

errNum = setKernelArg(kernel, 0, sizeof(buffer), &buffer);  

可以将内核完成的工作划分到一个特定上下文关联的所有设备,clEnqueueNDRangeKernel的偏移量参数可以用来计算缓冲区中的偏移量。

还可以采用一种更一般的方法,将缓冲区上完成的工作进一步划分,使用子缓冲区来完成。子缓冲区为一个特定缓冲区提供一个视图,例如,允许开发人员将一个缓冲区划分为可以独立处理的小块。子缓冲区纯粹是一个软件抽象,可以用子缓冲区完成的工作都可以利用缓冲区并明确指定偏移量来完成。子缓冲区增加了一层模块性,如果只使用缓冲区则很难表述这一层抽象。与前面介绍的方法相比,子缓冲区的有点在于:子缓冲区使用的接口只需要缓冲区,而无需额外了解偏移值等信息。子缓冲区不能从其他子缓冲区构建。

7.4 读、写和复制缓冲区和子缓冲区

缓冲区和子缓冲区可以由度主机应用程序读、写,将数据移入或移出宿主机内存。

7.5 映射缓冲区和子缓冲区

OpenCL支持将一个缓冲区的一个区域直接映射到宿主机内存,允许使用标准C/C++代码来回复制内存。映射缓冲区和子缓冲区有一个好处,返回的宿主机指针可以传入库和其他函数抽象,这些库和函数抽象可能并不知道所访问的内存实际上由OpenCL管理和使用。

原文地址:https://www.cnblogs.com/tcsong24/p/7651745.html