【问题标题】:What is a bank conflict? (Doing Cuda/OpenCL programming)什么是银行冲突? (做 Cuda/OpenCL 编程)
【发布时间】:2011-04-20 00:06:21
【问题描述】:

我一直在阅读 CUDA 和 OpenCL 的编程指南,但我无法弄清楚银行冲突是什么。他们只是深入研究如何解决问题而没有详细说明主题本身。有人可以帮我理解吗?如果帮助是在 CUDA/OpenCL 的上下文中,或者只是计算机科学中一般的银行冲突,我没有偏好。

【问题讨论】:

    标签: cuda opencl nvidia bank-conflict


    【解决方案1】:

    对于 nvidia(和 AMD)gpus,本地内存分为内存库。每个 bank 一次只能寻址一个数据集,因此如果 halfwarp 尝试从同一 bank 加载/存储数据,则必须对访问进行序列化(这是 bank 冲突)。对于 gt200 gpus,有 16 个库(对于 fermi 有 32 个库),对于 AMD gpus 有 16 或 32 个库(57xx 或更高:32,以下所有内容:16)),它们以 32 位的粒度交错(因此字节 0-3 在银行 1、银行 2 中的 4-7、...、银行 1 中的 64-69 等等)。为了更好的可视化,它基本上看起来像这样:

    Bank    |      1      |      2      |      3      |...
    Address |  0  1  2  3 |  4  5  6  7 |  8  9 10 11 |...
    Address | 64 65 66 67 | 68 69 70 71 | 72 73 74 75 |...
    ...
    

    因此,如果 halfwarp 中的每个线程都访问连续的 32 位值,则不会发生存储库冲突。该规则的一个例外(每个线程必须访问自己的银行)是广播: 如果所有线程都访问同一个地址,则该值只读取一次并广播给所有线程(对于 GT200,它必须是 halfwarp 中的所有线程都访问同一个地址,iirc fermi 和 AMD gpus 可以对任意数量的线程访问执行此操作相同的值)。

    【讨论】:

    • 非常感谢您的视觉和解释。我不知道广播,这似乎是一个重要的信息:) 我将如何验证我的加载和存储不会导致共享内存中的银行冲突?我必须以某种方式获取汇编代码还是有其他方法?
    • 由于银行冲突的发生是一些在运行时确定的(意味着编译器不知道它,毕竟大多数地址都是在运行时生成的),所以获得编译版本不会帮助很大。我通常用老式的方式来做这件事,我拿笔和纸开始思考我的代码存储在哪里。毕竟管理银行冲突发生的规则并不复杂。否则,您可以使用 nvidia OpenCL 分析器(应与 sdk、iirc 捆绑在一起)。我认为它有一个用于 Warp 序列化的计数器。
    • 感谢您指出 warp 序列化。计算分析器附带的自述文本文件之一是这样说的,
    • Ack,请原谅上面的评论,由于某种原因我无法重新编辑它。无论如何,我在计算分析器的自述文件中发现了这一点,“warp_serialize:在地址冲突时序列化到共享内存或常量内存的线程扭曲数。”这很好,我可以通过查看分析器输出轻松查看是否存在冲突。您如何确定笔和纸上是否存在银行冲突。您是否从任何示例或教程中学习过?
    • 正如我所说,从地址到银行的映射相对简单,因此不难确定哪些访问到哪个银行以及是否存在银行冲突。这篇论文只针对更多的冲突访问模式,没有我就做不到。
    【解决方案2】:

    可以并行访问的共享内存被划分为模块(也称为银行)。如果两个内存位置(地址)出现在同一个 bank 中,则会发生 bank 冲突,在此期间访问是串行完成的,失去了并行访问的优势。

    【讨论】:

    • 那么这与half-warp何时想要存储或加载内存有关吗? 16 个线程将尝试进行内存事务,因此使用多个线程访问同一个银行会导致序列化处理?另外,如何确保您不在同一家银行存储/加载数据?
    【解决方案3】:

    简单来说,bank 冲突是指任何内存访问模式未能在内存系统中可用的 bank 之间分配 IO 的情况。下面的例子详细说明了这个概念:-

    假设我们有二维 512x512 整数数组,并且我们的 DRAM 或内存系统中有 512 个存储体。默认情况下,数组数据将以 arr[0][0] 到 bank 0、arr[0][1] 到 bank 1、arr[0][2] 到 bank 2 的方式布局。 arr[0][511] 转到银行 511。概括 arr[x][y] 占用银行编号 y。现在一些代码(如下所示)开始以列主要方式访问数据,即。在保持 y 不变的情况下改变 x,那么最终结果将是所有连续的内存访问都会命中同一个 bank——因此会发生 bank 冲突。

    int arr[512][512];
      for ( j = 0; j < 512; j++ ) // outer loop
        for ( i = 0; i < 512; i++ ) // inner loop
           arr[i][j] = 2 * arr[i][j]; // column major processing
    

    编译器通常通过缓冲数组或使用数组中的素数元素来避免此类问题。

    【讨论】:

      【解决方案4】:

      (CUDA 银行冲突) 我希望这个能帮上忙.. 这是一个很好的解释...

      http://www.youtube.com/watch?v=CZgM3DEBplE

      【讨论】:

      • 请注意 link-only answers 是不鼓励的,所以答案应该是寻找解决方案的终点(而不是另一个参考中途停留,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,并保留链接作为参考。
      • 请详细说明链接,以便更好地协助 OP。
      • 这个视频真的很有帮助!而且我不知道为什么投反对票!这是一个非常好的输入! +1
      【解决方案5】:

      http://en.wikipedia.org/wiki/Memory_bank
      http://mprc.pku.cn/mentors/training/ISCAreading/1989/p380-weiss/p380-weiss.pdf

      从这个页面,你可以找到关于内存库的详细信息。 但这与@Grizzly 所说的有点不同。 在这个页面,银行是这样的

      银行 1 2 3

      地址|0, 3, 6...| |1,4,7...| | 2, 5,8...|

      希望这会有所帮助

      【讨论】:

        猜你喜欢
        • 2011-04-20
        • 2011-03-31
        • 2015-04-07
        • 2013-02-07
        • 2014-03-15
        • 2016-09-07
        • 2011-01-18
        • 2015-10-16
        • 2015-09-23
        相关资源
        最近更新 更多