OpenCL中工作项和全局内存之间的内存传输?

OpenCL中工作项和全局内存之间的内存传输?,opencl,Opencl,我对工作项和全局内存之间的数据传输有一些疑问。让我们考虑下面的非常低效的内存绑定内核。 __kernel void reduceURatios(__global myreal *coef, __global myreal *row, myreal ratio) { size_t gid = get_global_id(0);//line no 1 myreal pCoef = coef[gid];//line no 2 myreal pRow = row[gid];//

我对工作项和全局内存之间的数据传输有一些疑问。让我们考虑下面的非常低效的内存绑定内核。
__kernel void reduceURatios(__global myreal *coef, __global myreal *row, myreal ratio)
{
    size_t gid = get_global_id(0);//line no 1

    myreal pCoef = coef[gid];//line no 2
    myreal pRow = row[gid];//line no 3

    pCoef = pCoef - (pRow * ratio);//line no 4
    coef[gid] = pCoef;//line no 5
}
  • 工作组中的所有工作项是否开始在 同一时间
  • 工作组中的所有工作项是否开始在 同一时间
  • 假设工作组中的不同工作项完成执行行 4号在不同的时间。早期完成的是否等待以便, 所有工作项同时将数据传输到全局内存 第五排
  • 所有工作项是否同时退出计算单元,以便 早期完成的工作项必须等待所有工作项完成 执行完毕
  • 假设每个内核必须从全局内存执行2次读取。它是 最好一个接一个地执行这些语句,或者 最好在2次读取之间执行一些计算语句 处决
  • 上面显示的内核是GPU的内存限制。有路可走吗 哪些性能可以改进
  • 是否有避免内存限制的一般准则
  • 下面是我的答案:(感谢sharpneli对AMD GPU和warps的好评)

  • 通常是的。但这取决于硬件。您不能直接期望这种行为,也不能在这种“有序执行”的基础上设计算法。这就是为什么存在
    障碍
    成员篱笆
    的原因。例如,一些GPU只按顺序执行工作组WI的一个子集。在CPU中,它们甚至可能完全无序运行
  • 与答案1相同
  • 正如答案1所示,它们不太可能在不同的时间完成,所以是的。但是,您必须记住,这是一个很好的特性,因为对内存进行一次大的写操作比进行大量小的写操作效率更高
  • 通常是(参见答案1)
  • 最好是在读操作中插入操作,但编译器将已经考虑到这一点,并重新排列操作顺序以隐藏读/写效果的延迟。当然,编译器永远不会在可能更改结果值的代码中移动。除非手动禁用编译器优化,否则这是OpenCL编译器的典型行为
  • 不,从内核的角度来看,它是无法改进的
  • 一般规则是,输入的每个存储单元由多个WI使用?
    • 否(1个全局->1个私有)(问题中的内核就是这种情况)
    • 那么,内存是全局->私有的,没有办法改进它,不要使用本地内存,因为这会浪费时间
    • 是(1个全局->X个私有)
    • 首先尝试将全局内存移动到本地内存,然后为每个WI直接从本地读取到专用。根据重用量(可能只有两个WI使用相同的全局数据),如果计算量已经很高,那么它甚至可能不值得。您必须考虑额外内存使用和全局访问增益之间的权衡。对于图像处理来说,这通常是一个好主意,而对于其他类型的处理来说则不是那么多

  • 注意:如果尝试写入全局内存,同样的过程也适用。在写入全局之前,最好在本地内存中通过多个WI进行操作。但如果每个WI都写入全局中唯一的地址,则直接写入。

    实际上,1和2的答案在很大程度上取决于。例如,256个AMD HW工作组有64个项目执行一行,可能更多,只有在该工作组内的下64个项目开始执行时。有一个很好的理由可以解释为什么必须在一个工作组中使用本地内存围栏。是的,你是对的,你实际上无法预测所有线程都将一起运行。例如,因为它们可以在小型并行工程中进一步划分(即:64 WI在4个块中组合在一起,形成256 WG)。这就是围栏和障碍存在的原因。我会更新我的答案。