OpenCL 通用编程与优化(13)


8.8 通用内存地址空间和已命名内存地址空间

自OpenCL 2.0以来,已经引入了一个名为通用内存地址空间的特性。在OpenCL 2.0之前,指针必须指定其内存地址空间,如本地、私有或全局空间。此特性允许指针不在内核中设置其地址空间。GPU在内核执行过程中确定真实的地址空间。该特性使开发人员能够重用和减少代码库,这对于库开发等任务特别有用。

由于与识别内存空间相关联的硬件成本,使用通用内存地址空间可能会导致性能损失。以下是一些关于内存地址空间的提示:

  • 开发人员应该明确指定内存地址空间。这将减少编译器的模糊性,并避免GPU硬件成本来识别真实的内存空间。
  • 尽量避免使用发散的内存地址空间。对于统一的情况,编译器可能能够提取内存空间,并避免让硬件识别其内存空间。
  • 准备具有不同内存地址空间的不同版本。

8.9 子组

OpenCL 2.0中的新子组函数提供了比工作组对工作项的更细的粒度控制。一个工作组有一个或多个子组,而Adrenogpu中的子组被精确地映射到波的概念上。与1D/2D/3D工作组相比,子组只有一个维度。与工作组类似,一组函数允许工作项查询其本地ID和子组中的其他参数。

子组的强大功能在于,OpenCL引入了一组丰富的函数,允许子组中的工作项共享数据,并跨子组中的工作项执行各种操作。如果没有该特性,跨工作项的数据共享可能不得不依赖于本地或全局内存,这通常是昂贵的。

它是由硬件供应商来选择如何实现子组功能。它可以通过硬件或软件模拟来加速。在Adrenogpu中,许多子组功能都是硬件加速的。

除了核心OpenCL中的子组函数外,在OpenCL 3.0中还有子组上的KHR扩展。在使用扩展之前,必须先检查它们的可用性。

子组功能大致有两种类型:减少和洗牌。

  • 还原: Adreno对还原功能有硬件支持,比通过本地内存进行还原要快得多。
  • 洗牌:洗牌允许将数据从一个工作项传递到另一个工作项。它通常支持上洗牌、向下洗牌和通用洗牌。
    除了支持标准的子组函数外,Adrenogpu还支持通过供应商扩展进行的子组减少和洗牌。详见第9.2.2节。

8.10 联合使用

虽然联合是OpenCL内核语言中的一个标准特性,但在Adrenogpu上是低效的。编译器需要分配额外的寄存器来处理不同大小的成员;因此,性能通常比没有并集的常规内核要差。开发人员应该避免在Adrenogpu上使用联合使用。

8.11 结构的使用

结构可以使代码更容易理解和组织,这是将一组相关变量分组到一个地方的极好方式。尽管有优点,但在Adrenogpu上使用结构可能会导致一些效率,并不总是推荐。以下是一些关于结构化的提示:

  • 会尽量避免使用结构体内部的指针。
  • 显式地分配单个成员,而不是将整个结构变量分配给另一个成员。
  • 选择数组结构或结构组数组。
    • 一个关键的考虑因素是,该选择是否可以缓解内核的瓶颈。
    • 例如,如果可以安排数组,使来自内存的数据加载有更好的合并,那么数组的结构是一个更好的选择。如果结构体中的成员导致良好的缓存本地性,那么结构体的
    • 数组可能是一个更好的选择。

该决策将取决于每个用例的特征。

8.12 其他

许多其他一些看起来很小的优化技巧都可以提高内核的性能。以下是开发人员可以尝试一下的一些事情:

  • 预先计算在内核内不会更改的值。

    • 计算一个可以在内核之外预先计算的值是一种浪费。
    • 预计算值可以通过内核参数或#depal传递给内核。
    • 使用快速整数内置函数。使用mul24用于24位整数乘法,使用mad24用于24位整数乘法和累积。
    • Adrenogpu有对mul24的本机硬件支持,而32位整数乘法需要不止一条指令。
    • 如果整数在24位范围内,则使用mul24比直接的32位乘法更快。
  • 减少EFU功能。

    • 例如,代码如下:
      r = a / select(c, d, b<T)
      其中a、b和T是浮点变量,c和d是常数,可以重写为:
      r = a * select(1/c, 1/d, b<T)
      这避免了倒数的EFU函数,因为编译器可以在编译时推导出1/c和1/d。
  • 避免除法操作,特别是整数除法。

    • 整数划分在Adrenogpu中非常昂贵。
    • 与其使用分割,不如使用naten_recep进行互操作,如8.3节所述。
  • 避免整数模块操作,这是昂贵的Adrenogpu。

  • 对于常数组,如查找表、过滤器水龙头等,在内核作用域之外声明它们。

  • 使用mem_fence函数来拆分/组代码部分。

    • 编译器有复杂的算法来从全局优化的角度生成最优代码。
    • mem_fence可能会防止编译器在代码前后进行洗牌/混合代码。
    • mem_fence允许开发人员操作一些代码来进行分析和调试。
  • 使用16位的ALU计算,而不是8位的。8位可能必须转换为16位或32位的ALU操作,因为Adrenogpu没有一般的8位ALU支持。

  • 如果可能,使用位移位操作而不是乘法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值