Caching 对于缓存的GPU,哪种内存访问模式更有效?

Caching 对于缓存的GPU,哪种内存访问模式更有效?,caching,memory,opencl,gpu,gpgpu,Caching,Memory,Opencl,Gpu,Gpgpu,假设我有一个全局内存数组: |a|b|c| |e|f|g| |i|j|k| | 有四个“线程”(OpenCL中的本地工作项)访问此内存,以及两种可能的访问模式(列为时间片,行为线程): 上面的模式将数组分成块,每个线程在每个时间片上迭代并访问块中的下一个元素。我相信这种访问对于CPU来说会很好,因为它最大化了每个线程的缓存位置。此外,编译器可以轻松地展开利用此模式的循环 第二种模式: 0 -> 1 -> 2 -> 3 t1 a -> e -> i ->

假设我有一个全局内存数组:

|a|b|c| |e|f|g| |i|j|k| |
有四个“线程”(OpenCL中的本地工作项)访问此内存,以及两种可能的访问模式(列为时间片,行为线程):

上面的模式将数组分成块,每个线程在每个时间片上迭代并访问块中的下一个元素。我相信这种访问对于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”是上面的单元),以避免未对齐的访问。这些循环似乎不太容易展开(或者使用英特尔的CPU内核构建器)。我相信这种模式在GPU上会很好地工作


我的目标是具有缓存层次结构的GPU。特别是AMD的最新架构(GCN)。第二种访问模式是“合并”的示例吗?我的思维过程中有什么地方错了吗?

我认为答案取决于访问的是全局内存还是本地内存。如果要从全局内存中提取数据,则需要担心合并读取(即连续块,第二个示例)。但是,如果要从本地内存中提取数据,则需要担心银行冲突。我有一些经验,但不是很多,所以我不是说这是绝对的事实

编辑:在阅读了GCN之后,我不认为缓存在这里有什么不同。如果反复读/写相同的元素,基本上可以认为它们只是加速了全局内存。另一方面,谢谢你提出这个问题,因为阅读新的体系结构非常有趣


编辑2:这里有一个关于本地和全局内存库的堆栈溢出讨论:

yes;第二种模式是合并,并且通常是流处理器上的首选模式,或者任何您想要调用它们的模式。我自己也没有使用过AMD的硬件,但我想同样的情况也会发生。是的,第二种方式才是正确的。据我所知,您的解释是,列与行访问仅适用于2D数组全局内存访问。第一个表单一次将使用总McCache行数的1/3。第二个将使用所有缓存线。在我的HD7870上,使用分块算法进行矩阵乘法时,第二种方法的速度更快。@huseyintugrulbuyukisik堆栈上的缓冲区应该以相同的方式存储数据,而不管维度是什么,维度不只是一种抽象吗?现在2DImages有点不同了,可以缓存在多个维度中(比如上面、下面和旁边的元素,而不是前面的元素)。谢谢。我完全忘了提到这是全球访问。本地内存和全局内存都是存储的,但是本地内存可以针对更多的访问模式进行优化(至少在Intel HD 2500->5200的情况下)。
   0 -> 1 -> 2 -> 3
t1 a -> e -> i -> .
t2 b -> f -> j -> .
t3 c -> g -> k -> .
t4 .    .    . `> .