caching - 对于缓存 GPU 来说,哪种内存访问模式更高效?

标签 caching memory opencl gpu gpgpu

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

|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 .    .    . `> .

上面的模式将数组分割成 block ,每个线程在每个时间片迭代并访问 block 中的下一个元素。我相信这种访问对于 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)。第二种访问模式是“合并”的示例吗?我的思维过程是否在某个地方出错了?

最佳答案

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

编辑:阅读完 GCN 后,我认为缓存在这里没有什么影响。如果您重复读/写相同的元素,您基本上可以将它们视为加速全局内存。顺便说一句,感谢您提出这个问题,因为阅读新架构非常有趣。

编辑 2:这是关于本地和全局内存银行的 Stack Overflow 讨论:Why aren't there bank conflicts in global memory for Cuda/OpenCL?

关于caching - 对于缓存 GPU 来说,哪种内存访问模式更高效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21008125/

相关文章:

caching - 分布式缓存 - 基本概念

java - 实现 servlet 数据的缓存

caching - Azure Redis 缓存超时和无连接错误

linux - 当底层物理内存用完时,如何处理访问 mmap 内存的总线错误?

java - 简单的 Java 程序 - 分析显示意外行为

c - 在windows下查找程序在c中使用的总内存

c++ - OpenCL 内核计时测量为 0 秒或导致 SIGABRT

ios - 是否可以缓存 iPhone UIWebView 中加载的资源?

java - Aparapium OpenCL 无法在带有 NVidia 显卡的 Manjaro Arch 上运行

algorithm - 在 OpenCL 1.2 上实现堆栈推送的正确方法是什么?