【发布时间】:2014-01-27 06:57:25
【问题描述】:
假设我有一个全局内存数组:
|a|b|c| |e|f|g| |i|j|k| |
有四个“线程”(OpenCL 中的本地工作项)访问此内存,并且此访问有两种可能的模式(列是时间片,行是线程):
0 -> 1 -> 2 -> 3
t1 a -> b -> c -> .
t2 e -> f -> g -> .
t3 i -> j -> k -> .
t4 . . . `> .
上述模式将数组拆分为块,每个线程在每个时间片中迭代并访问块中的下一个元素。我相信这种访问对于 CPU 来说会很有效,因为它可以最大化每个线程的缓存局部性。此外,使用这种模式的循环可以很容易地被编译器展开。
第二种模式:
0 -> 1 -> 2 -> 3
t1 a -> e -> i -> .
t2 b -> f -> j -> .
t3 c -> g -> k -> .
t4 . . . `> .
上述模式大步访问内存:例如,线程 1 访问 a,然后是 e,然后是 i 等。这最大化了每单位时间的缓存局部性。假设您在任何给定的时间片上都有 64 个工作项“跨步”。这意味着,对于 64 字节的缓存行大小和 sizeof(float) 的元素,工作项 1-16 的读取由工作项 1 的读取缓存。必须仔细选择每个单元格的数据宽度/计数(其中“a”是上面的一个单元格)以避免未对齐的访问。这些循环似乎不那么容易展开(或者根本不使用 Intel 的 Kernel Builder 和 CPU)。我相信这种模式适用于 GPU。
我的目标是具有缓存层次结构的 GPU。特别是 AMD 的最新架构 (GCN)。第二种访问模式是“合并”的一个例子吗?我的思维过程是否有错误?
【问题讨论】:
-
是的;第二种模式是合并,通常在流处理器或任何您想调用的处理器上首选。我自己还没有使用过 AMD 硬件,但我想同样的事情必须坚持
-
是的,第二个是正确的方法。你所有的解释都很好
-
据我所知,列与行访问仅适用于二维数组全局内存访问。第一种形式一次将使用总 mcache 行的 1/3。第二个将使用所有缓存行。在我的 HD7870 上使用阻塞算法进行矩阵乘法时,第二个工作得更快。
-
@huseyintugrulbuyukisik 堆栈上的缓冲区应该以相同的方式存储数据,无论维度如何,维度不只是抽象吗?现在 2DImages 有点不同,并且可以缓存在多个维度中(比如上面、下面和旁边的元素,而不是前面的元素)。
标签: caching memory opencl gpu gpgpu