12

为了了解如何确保满足对齐要求,我多次阅读 Heterogeneous Computing with OpenCL p.no: 157 一书中的以下段落。这显示了如何为图像卷积中的问题添加填充(假设工作组大小为 16 x 16)。

内存访问对齐

NVIDIA 和 AMD GPU 的性能都受益于全局内存中的数据对齐。特别是对于 NVIDIA,对齐 128 字节边界上的访问和访问 128 字节段将理想地映射到内存硬件。但是,在此示例中,16 宽工作组将仅访问 64 字节段,因此应对齐数据到 64 字节地址。这意味着每个工作组访问的第一列应该从一个 64 字节对齐的地址开始。在此示例中,选择让边界像素不产生值决定了所有工作组的偏移量将是工作组尺寸的倍数(即,对于 16 x 16 工作组,工作组将开始访问第 N*16 列的数据) . 为确保每个工作组正确对齐,

1-任何人都可以帮助我理解在填充每个工作组访问的第一列之后如何从 64 字节对齐的地址开始(上述段落中提到的要求,对吗?)?

2-同样,该图的陈述是正确的:对于 16 x 16 工作组,工作组将开始访问 N*16 列的数据。

如果正确,如图所示的工作组 1,2 应该开始访问第 1x16 列的数据,与图中所示相反。我完全糊涂了!!:(

更新: 我现在很清楚 Q-2。 实际上图中显示的工作组是 2,1(在 opencl 约定中,第一列),所以它是完全正确的:2x16=32 而不是我想的 1x16。

但问题没有。1 仍然没有答案。

在此处输入图像描述

4

1 回答 1

8

对于卷积核,每个区域(例如区域 (0,1) 或区域 (2,1) 等)还必须包括围绕它的数据“光环”,以便当卷积核对数据元素进行操作时在该区域的边缘,它具有该数据元素的一组合适的邻居来计算该数据点处的卷积。这意味着对于左上角具有数据元素 (0,0) 的区域 (0,0),我需要元素 (-1, 0)、(-2, 0) 等来计算卷积在元素 (0,0) 处。

现在,如果我正常存储图像,因此元素 (0,0) 位于内存位置 0(或其他一些 64 字节对齐地址),那么当我访问该点之前的元素进行卷积时,我将访问我的 64 字节对齐区域之外的数据。因此,我们可以“填充”图像的最左边一列“向左”,即在地址之前的附加数据元素,以便卷积内核拾取所有在 64 字节对齐区域内的值,而我不是跨越 64 字节边界。我们不是在内存位置 0 开始图像存储,而是在内存位置 0 开始光环存储,第一个图像数据元素从位置 0 + 光环宽度开始。这种填充也可以产生对齐其他区域的晕边框的影响,

现在我们还假设图像的宽度不是 2 的幂次方(例如,对于高清图像,宽度为 1920 像素)。如果我们只是将光晕宽度包含在图像右侧的填充中(即在像素行的末尾),然后我们紧随其后开始下一个像素行的光晕区域,我们会也不太可能从下一个像素行(包括光晕)开始有一个正确对齐的区域。因此,我们在每一行的末尾添加了额外的填充(任何卷积操作都不会触及,它只是浪费空间),这样当我们开始下一个像素行的光环区域时,它会从正确对齐的地址开始。

这个讨论和方法(和问题,我相信)实际上只关注确保每个工作组数据访问的起始地址是一致的。只要第一个工作组的起始地址对齐(通过适当的填充和调整内存中的图像存储),并且工作组具有适当的尺寸(例如 16 宽,每个工人 4 个字节),那么第一个工作组的起始地址下一个工作组也将对齐。相邻工作组的数据访问之间当然会有重叠,因为相邻工作组的光环区域是重叠的。

我在这里使用的对齐有一个相当简单的定义。如果地址的最低有效 n 位全为零,则内存中的地址是 2**n 字节对齐的。因此,一个 64 字节对齐的区域具有一个起始地址,其中 6 个最低有效位全为零。这在这些架构上通常很有用,可以满足架构的内存加载和存储要求,尤其是它们包含的 DRAM 子系统。现代 DRAM 内存库访问总是返回多个字节,因此如果我们在代码中的同一位置同时使用所有这些字节,我们可以最有效地利用传输。有关对齐的更多报道以及它对数据访问的合并和改进的影响,您可能对此网络研讨会感兴趣(和幻灯片)来自nvidia 网络研讨会页面。为了快速浏览,本演示文稿的幻灯片 26-33涵盖了基本思想。

于 2012-11-01T05:09:07.183 回答