订阅移动开发RSS CSDN首页> 移动开发

Qualcomm Adreno GPU 如何获得更好的OpenCL性能——内存优化篇

发表于2016-06-09 09:44| 次阅读| 来源Qualcomm| 0 条评论| 作者Jay Yun

摘要:大多数移动应用均受制于内存,而非受制于计算。因此,性能优化归根结底往往是按需管理内存访问。在这篇文章中,作者着重讲解了内存优化的技巧。

 如果您希望利用图形处理单元(GPU),如 Adreno™ 图形处理器,加速图像处理或计算机视觉应用,不妨关注一下 OpenCL™ 开放计算语言。OpenCL 本身是用无处不在的 C语言编写的,您可以很方便的利用它编写程序。作为一项开放标准,目前很多独立部件和移动环境都存在 GPU 且支持 OpenCL。

您可以针对一种 GPU 优化应用程序,但绝大多数时候,当您将应用移植到另一种 GPU 后,并不会得到之前优化所获得的性能,对于移动 GPU 来说尤其如此,因此,您需要小心谨慎地调整应用,以获得期望的性能。然而,在针对不同 GPU 优化应用时,您需要了解或预测其架构细节,但这一点很难做到。

有鉴于此,我们分析了各种应用,为 Adreno GPU 实现更佳 OpenCL 性能提供了一套指南。在这一系列文章中,我将一五一十地讲解改善应用性能所需遵循的指南及步骤。

改善 Adreno GPU 的 OpenCL 性能

在这篇文章中,我将着重讲解内存优化。从内存开始讲起,是因为大多数移动应用均受制于内存,而非受制于计算。因此,性能优化归根结底往往是按需管理内存访问。

对于Adreno GPU,我的建议是:

  • 向量化、向量化!推荐向量大小为4(例如,vload4)。
  • 对于最大带宽,尽量将每次内存访问分组为128位。
  • 对于大多数应用而言,读取图形对象优于读取缓冲对象。
  • 如果您正在处理 YUV 图像并且只处理 Y 平面,看看能不能映射Y平面为“RGBA”,这​​样可以一次读取4个像素。(当然,如果你做的 5x5 卷积,这样不是很方便,所以尽量读取 8X5 像素,每个内核函数处理4个输出像素。)
  • 如果您希望更灵活地向量化加载和存储,或按字节寻址访问,那么我建议从缓冲区对象读取。
  • 如您心中有疑问,可以尝试从读取图像对象,写入缓冲区对象。

使用本地内存(Local Memory)

开发人员经常会问我们何时以及如何使用本地内存。Adreno GPU 在每个计算单元内均拥有专门的本地内存。例如,Snapdragon™820 处理器中的 Adreno 530 图形处理器拥有四个计算单元,每个计算单元都有 32KB 本地内存。

以下为几个需要注意的地方:

  • 本地内存的延迟比全局内存低,但可能会存在隐性开销。例如,使用本地内存经常有一个本地内存屏障,这种屏障将导致同步延迟,抵销了低延迟带来的好处。
  • 在您将多级算法合并至单一内核函数中时,本地内存对于存储中间数据是有好处的,可以节省 DDR 带宽,从而降低功耗。
  • 如果您希望在本地内存缓存数据,便于多次访问,一个好的经验法则是保证缓存数据被访问3次以上才有必要这么做。

使用常量内存

有内置 RAM 是用于存储常数存储器的。您可以用它来加速常量数组和变量。

  • 您可以在内置 RAM 中最多存储 3KB 的常量内存。
  • 编译器会尝试将常量变量和数组放到这个 RAM,但由于空间所限,一些常量可能无法被放置其中。
  • 要做到这一点,编译器需要知道常量数组的大小。如果数组是在程序范围定义的,那么万事大吉。
  • 如果数组需要以内核参数的形式传递,可以使用下面的属性,由它来告诉编译器其字节大小:
  1. __kernel void foo(__const float f* __attribute__( (max_constant_size(1024))) 

这些指南适用于 Adreno 5xxx GPU。希望对您有所帮助。在之后的文章中,我将继续探讨更多方法,改善 Adreno GPU 的 OpenCL 性能,欢迎继续关注我们后续的文章。


更多Qualcomm开发内容请详见:Qualcomm开发者社区

0
0