工作维度的重新排序可能会带来巨大的性能提升,但为什么呢?

时间:2015-06-25 13:50:20

标签: c++ performance opencl gpu

我在GPU上使用OpenCL进行立体图像处理,在将C ++实现移植到OpenCL之后,我正在进行优化。一个非常简单的实验是围绕维度进行交换。

考虑一个简单的内核,它是沿着二维工作空间(f.e. 640x480)为每个像素执行的。就我而言,这是一次人口普查改造。

换自:

int globalU = get_global_id(0);
int globalV = get_global_id(1);

也是

int globalU = get_global_id(1);
int globalV = get_global_id(0);

以同样的方式调整NDRange,性能提升约500%。 3D空间中的其他实验实现了从72ms到2ms的执行时间,只需重新排序尺寸。

任何人都能解释一下,这是怎么回事? 它只是内存管道和缓存使用的影响吗?

编辑:图像具有标准的乳房布局。这就是为什么我想知道效果。我期望最好的速度,当迭代过程像图像存储在内存中时,情况并非如此。

在阅读了AMD APP SDK文档后,我发现了一些有关内存通道的有趣细节。这可能是一个原因。

1 个答案:

答案 0 :(得分:1)

首次加载到CPU的缓存中时访问内存中的元素。 CPU不加载单个元素(比如1个字节),而是将一行(例如64个相邻字节)加载到缓存中。这是因为通常可能会访问后续元素,因此CPU不需要再次访问RAM。

这是一个巨大的差异,因为访问高速缓冲存储器,电信号甚至不应该离开CPU芯片,而如果CPU需要从RAM加载数据,信号需要传输到一个单独的芯片,可能还有一个以上的信号来自CPU是必需的,因为它通常需要在RAM中指定行和列来访问它的一部分(阅读What every programmer should know about memory以获取更多信息)。实际上,高速缓存的访问时间可能只需0.5 ns,而RAM访问则需要100 ns。

所以计算机算法应该考虑到这一点。如果遍历矩阵中的所有元素,则应遍历它们,以便大约同时访问彼此靠近的元素。因此,如果您的矩阵在内存中具有以下布局:

m_0_0,m_0_1,m_0_2,... m_1_0,m_1_1(第一栏,第二栏等)

您应该按顺序访问元素:m_0_0,m_0_1,m_0_2(按列)

如果你要使用不同的访问顺序(在这种情况下是按行),当你访问第一列中的第一个元素时,CPU会加载缓存中第一列的一部分,当你访问第二列中的第一个元素时,CPU会加载第二列的一部分当您遍历第一行并访问第一列的第二个元素时,第一列的缓存值将不再存在于缓存中,因为它的大小有限(且非常小)。因此,这样的算法可以有效地消除缓存。