【问题标题】:Minimizing global memory reads in OpenCL with vectors?使用向量最小化 OpenCL 中的全局内存读取?
【发布时间】:2015-02-19 19:34:34
【问题描述】:

假设我的内核采用 4(或 3,或 2)个不相关的浮点数或双参数,或者我想从全局内存中访问 4 个单独的浮点数。这会导致 4 次单独的全局内存访问吗?访问 4 个浮点数或双精度的单个向量是否比访问 4 个单独的向量快?如果是这样,我是否最好将它们打包成一个向量,然后使用#defines 来引用各个成员?

如果这确实提高了性能,我是否必须自己做,或者编译器是否足够聪明,可以自动将 4 个单独的浮点读取转换为一个向量?这就是“自动矢量化”吗?我在一些文档中看到了自动矢量化,但没有详细解释它的具体作用,只是它似乎是仅针对 CPU 而不是 GPU 的可选性能优化。

【问题讨论】:

  • “无关”是什么意思?内存引擎通常以 128 字节为单位请求内存(这个数字取决于硬件),因此如果所有 4 个浮点数都在 128 字节之内(连续),那么您只会获得一个内存事务。这称为合并内存访问,自动矢量化是完全不相关的事情。
  • “不相关”是指概念上不相关 - 将它们存储为单个向量在语义上并不直观。例如,它们不是空间中某个点的 4 个坐标,也不是像素的颜色值,也不是矢量所要处理的那种东西。
  • 是否足以让所有浮点数彼此相距 128 字节,或者它们也必须位于同一个 128 字节对齐的块中?我可以通过将它们设为单个向量而不是 4 个单独的值来保证适当的存储吗?
  • 128 字节只是一个例子。你可能想read this question
  • 我已经对合并内存读取进行了一些搜索,但没有找到任何解释它何时以及如何发生以及何时可以依赖它的信息。如果在读取一个值时,它恰好与稍后将读取的值相邻,那么编译器是否足够聪明地注意到这一点并编译第二次访问而不是第二次读取全局内存?如果第二次读取没有访问全局内存,它访问的是什么?私人记忆?

标签: performance opencl


【解决方案1】:

使用向量取决于内核本身。如果您同时需要所有四个值(例如:内核开始时,循环开始时),最好将它们打包,因为它们将在一次读取期间分配(单个向量中的值按顺序存储)。

另一方面,当您只需要一些值时,您可以通过只读取您需要的值来加快执行速度。

另一种情况是当您逐个读取它们时,每个读数除以一些计算(即给 GPU 一些时间来获取数据)。


基本上,这些数据读取段的行为类似于缓冲区。如果您有足够的实例,则读取次数相同(可选原因),真正重要的是这些读取的使用情况。

编译器经常解压这些结构,所以只有加速是,所有变量都很好地存储,所以当你读取时,你用一次读取填充它们,其余的缓冲区用于另一个实例。

例如,我将使用 128 位宽的总线和 4 个浮点数(32 位)。

 (32b * 4) / 128b = 1 instance/read

对于标量数据类型,有 N 次读取(N = 变量数),每次读取填充每个实例中的一个变量,最多可读取变量数。

 32b / 128b = 4 instance/read

因此,在我的示例中,如果您有 4 个实例,那么无论如何总会有至少 4 次读取,并且唯一的事情是,如果可能的话,您可以通过一些计算来覆盖获取时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 2022-07-06
    • 1970-01-01
    相关资源
    最近更新 更多