OpenCL 通用编程与优化(8)

46 篇文章 22 订阅


7.1.4私有内存

在OpenCL中,私有内存对每个工作项都是私有的,其他工作项无法访问。在物理上,私有内存可以驻留在片上寄存器或片外系统内存中。确切的位置取决于几个因素,这里是一些典型的案例:

  • 标量变量存储在寄存器中,它比其他内存更快。
    • 如果寄存器不足,私有变量将保存在系统内存中。
  • 私有数组可以存储在:
    • 本地内存中,但不能保证这样做。
    • 芯片外系统内存,如果它们超过本地内存容量。

将私有内存存储到芯片外系统内存中是非常不可取的,原因有二:

  • 系统内存的延迟时间远高于GPR。
  • 私有内存访问模式对缓存不友好,特别是当每个工作项的私有内存数量很大时。

建议:

  • 避免在内核中定义任何私有数组。如果可能的话,尽量使用向量。
  • 用全局或本地数组替换私有数组,并设计其布局,以便对数组元素的访问可以跨多个相邻的工作项进行合并。缓存性能可以更好。
  • 使用矢量化的私有内存加载/存储,即,尝试加载/存储128位,使用vload4/vstore4每次加载4个32位元素。

7.1.5全局内存

OpenCL支持使用芯片外系统RAM的缓冲区和图像对象。与存储在系统RAM中的简单一维数据数组的缓冲区对象相比,图像对象是一个不透明的内存对象,其中开发人员不知道底层数据是如何存储的。当创建一个图像对象时,软件以特定的方式排列数据,以便GPU有效地访问。使用它们的最佳方法是不同的,并将在下面的章节中进行讨论。

7.1.5.1缓冲区对象

缓冲区对象存储元素的一维集合:标量数据类型、向量数据类型或用户定义的结构。缓冲区对象的内容由内核通过Adrenogpu中的L2缓存加载或写入。使用以下API函数创建一个缓冲区对象:

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

在这个函数中,cl_mem_flags是开发人员必须小心使用的一个重要标志,因为它可能会显著影响性能。OpenCL允许对这个功能有许多不同的标志,对于Adrenogpu,这里有几个关键点:

  • 某些标志可能会产生额外的内存副本。尝试使用第7.4节中描述的零拷贝标志。
  • 有些标志是用于具有专用GPU内存的桌面/离散GPU的。
  • 使用最准确的标志:
    • 一般的想法是,标志越严格,OpenCL软件就越有可能找到对象的最佳配置。
    • 例如,OpenCL软件可以应用缓存刷新策略(通写、回写等)。最适合内存对象,缓存刷新的开销可以忽略。
    • 第7.4.2节详细介绍了高速缓存策略及其对性能的影响。以下是以下几个例子:
      –如果内存是主机只读的,则使用CL_MEM_HOST_READ_ONLY。
      –如果内存无法访问,请使用CL_MEM_HOST_NO_ACCESS。
      –如果内存仅供主机写入,请使用CL_MEM_HOST_WRITE_ONLY。
7.1.5.2图像对象

图像对象存储1D、2D或3D纹理、帧缓冲区或图像数据,并且图像对象内部的数据布局是不透明的。在实践中,对象中的内容不必与实际的图像数据相关联。任何数据都可以存储为一个图像对象,以利用硬件纹理引擎及其在Adreno中的L1缓存。使用以下API创建了一个图像对象:

cl_mem clCreateImage(cl_context context,
 cl_mem_flags flags,
 const cl_image_format *image_format,
 const cl_image_desc *image_desc,
 void *host_ptr,
 cl_int *errcode_ret)

请注意,图像的cl_mem_flags与上一节中讨论的缓冲区对象有类似的经验法则。

Adrenogpu支持许多图像格式和数据类型。经过几代代,增加了更多的图像格式和数据类型对。开发人员可以使用clGetSupportedImageFormats函数来获得设备上可用的图像格式/数据类型的完整列表。为了充分利用内存带宽,开发人员应该使用长度为128位的内存对,例如,CL_RGBA/CL_FlOAT、CL_RGBA/CL_SIGNED_INT32等。

Adrenogpu还通过供应商扩展支持非OpenCL标准的格式,如YUV和压缩格式。除了新的格式,许多新功能还为图像对象的硬件加速,如盒子过滤、SAD和SSD。详情请参见第9章。

7.1.5.3图像对象与缓冲区对象

如第6.2节所述,Adrenogpu处理图像对象比缓冲对象更好,因为它有各种优点,包括强大的纹理引擎、专用的L1缓存和自动处理边界外访问。Adrenogpu支持许多图像格式和数据类型组合,并可以进行自动格式转换。OpenCL支持两个采样器过滤器,CLK_FILTER_NEAREST和CLK_FILTER_LINEAR。对于CLK_FILTER_LINEAR,适当的图像类型的组合允许GPU使用其内置的纹理引擎进行自动的双线性/三线性插值。例如,假设一个图像是CLK_NORMALIZED_COORDS_TRUE和CL_UNORM_INT16,即,图像数据是2字节的无符号短。要执行read_imagef,Adrenogpu需要执行以下操作:

  • 通过L1高速缓存读取图像对象中的像素。
  • 使用所有需要的像素来执行插值。
  • 将其转换并规范化到[0,1]的范围。

这对于双线性/三线性插值操作很方便。Adrenogpu还通过供应商扩展支持双立方插值。有关更多细节,请参考第9.3.4节,但有时,缓冲区对象可能是一个更好的选择:

  • 缓冲区允许更灵活的数据访问:

  • 图像对象只允许在像素大小边界处进行访问,例如,128位的RGBA和32位/通道的图像对象。

  • Adreno支持对缓冲区对象的灵活访问,其中指针为数据访问提供了极好的灵活性。

  • L1高速缓存成为瓶颈。

    • 例如,存在严重的L1缓存抖动,这使得L1缓存访问效率低下。
  • 缓冲区对象允许在内核内部进行读取和写。OpenCL 2.0支持内核中的读写图像(具有__read_write限定符的图像对象)。由于同步的要求,读写映像的性能可能比一些老式Adrenogpu上的缓冲区要差。

表7-2Adrenogpu中的缓冲区与图像

FeaturesBufferImage
L2 cacheYesYes
L1 cacheUnavailable on most GPUsYes
Support read-and-write in kernelYesNo in OpenCL 1.x Yes, in OpenCL 2.x (synchronization required)
Use of pointerYesNo
Built-in hardware interpolationNoYes
Built-in boundary handlingNoYes
Support image format/samplerNoYes
7.1.5.4同时使用图像对象和缓冲区对象

更好的方法是同时充分利用L2缓存SP和L2缓存TPL1SP路径,而不是只使用纹理或缓冲区对象。由于TPL1具有L1高速缓存,所以让L1存储最常用但相对较少的数据量是一种较好的做法。

7.1.5.5全局内存与本地内存的比较

本地内存的一个典型用例是首先将数据加载到本地内存中,同步以确保数据准备就绪,然后工作组中的工作项可以使用它进行处理。但是,由于以下原因,使用全局内存可能优于本地内存:

  • 本地内存的一个典型用例是首先将数据加载到本地内存中,
  • 同步以确保数据准备就绪,然后工作组中的工作项可以使用它进行处理。但是,由于以下原因,使用全局内存可能优于本地内存
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值