什么是银行冲突?(正在进行Cuda/OpenCL编程)

什么是银行冲突?(正在进行Cuda/OpenCL编程),cuda,opencl,nvidia,bank-conflict,Cuda,Opencl,Nvidia,Bank Conflict,我一直在阅读CUDA和OpenCL的编程指南,我不知道什么是银行冲突。他们只是深入研究如何解决问题,而没有详细阐述问题本身。有人能帮我理解吗?如果帮助是在CUDA/OpenCL的上下文中,或者只是在计算机科学中的一般库冲突,我没有偏好。可以并行访问的共享内存被划分为模块(也称为库)。如果两个内存位置(地址)出现在同一个存储库中,则会出现存储库冲突,在此期间,访问是串行进行的,失去了并行访问的优势。对于nvidia(以及amd)GPU,本地内存分为多个存储库。每个银行一次只能处理一个数据集,因此如

我一直在阅读CUDA和OpenCL的编程指南,我不知道什么是银行冲突。他们只是深入研究如何解决问题,而没有详细阐述问题本身。有人能帮我理解吗?如果帮助是在CUDA/OpenCL的上下文中,或者只是在计算机科学中的一般库冲突,我没有偏好。

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

对于nvidia(以及amd)GPU,本地内存分为多个存储库。每个银行一次只能处理一个数据集,因此如果halfwarp试图从同一银行加载/存储数据,则必须序列化访问(这是银行冲突)。对于gt200 GPU,有16个组(费米为32个组),AMD GPU为16或32个组(57xx或更高:32,以下所有:16)),它们以32位的粒度交错(因此字节0-3位于组1中,字节4-7位于组2中,…,字节64-69位于组1中,依此类推)。为了获得更好的可视化效果,基本上如下所示:

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 |...
...
因此,如果半扭曲中的每个线程访问连续的32位值,则不存在组冲突。此规则的一个例外(每个线程都必须访问自己的库)是广播:
如果所有线程访问同一地址,该值只读取一次并广播给所有线程(对于GT200,它必须是半扭曲中访问同一地址的所有线程,iirc fermi和AMD GPU可以对访问相同值的任意数量的线程执行此操作)。

简单地说,当任何内存访问模式无法在内存系统中的可用内存组之间分配IO时,就会出现内存组冲突。以下示例阐述了该概念:-

让我们假设我们有二维512x512整数数组,我们的DRAM或内存系统中有512个存储组。默认情况下,阵列数据的布局方式为:arr[0][0]进入气缸组0,arr[0][1]进入气缸组1,arr[0][2]进入气缸组2……arr[0][511]进入气缸组511。概括起来,arr[x][y]占据了银行编号y。现在,一些代码(如下所示)开始以列主方式访问数据,即在保持y不变的同时更改x,那么最终结果将是所有连续的内存访问都将命中同一个存储库,从而导致存储库冲突

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
int-arr[512][512];
对于(j=0;j<512;j++)//外循环
对于(i=0;i<512;i++)//内部循环
arr[i][j]=2*arr[i][j];//列主处理
编译器通常通过缓冲数组或使用数组中元素的素数来避免此类问题。


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

银行1 2 3

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

希望这会有所帮助(CUDA银行冲突) 我希望这会有帮助。。 这是很好的解释


那么这与半扭曲要存储或加载内存的时间有关吗?16个线程将尝试执行一个内存事务,因此使用多个线程访问同一个银行会导致串行处理吗?另外,如何确保您不在同一银行存储/加载数据?非常感谢您的视觉和解释。我不知道广播,这似乎是一个重要的信息:)我如何验证我的加载和存储不会导致共享内存中的存储冲突?我必须以某种方式获取汇编代码,还是有其他方法?因为库冲突的发生是在运行时确定的(这意味着编译器不知道它,在运行时生成了所有大多数地址之后),获取编译版本不会有多大帮助。我通常用老式的方式来做这件事,我拿着笔和纸,开始思考我的代码存储在哪里。毕竟,控制银行冲突发生的规则并没有那么复杂。否则,您可以使用英伟达OpenCL剖析器(应该与SDK、IIVC捆绑)。我想它有一个经线系列的计数器。谢谢你指出经线系列。compute profiler附带的一个自述文本文件说,确认,请原谅上面的评论,出于某种原因,我无法重新编辑它。无论如何,我在compute profiler的自述文件“warp_serialize:将地址冲突序列化到共享内存或常量内存的线程扭曲数”中找到了这一点。这很好,我可以通过查看profiler输出轻松查看是否存在冲突。你如何判断银行是否存在纸笔冲突。您从任何示例或教程中学到了什么吗?正如我所说的,从地址到银行的映射相对简单,因此不难确定哪些访问指向哪个银行,因此也不难确定是否存在银行冲突。这篇论文只针对更多冲突访问模式,我不能没有冲突访问模式。请注意,这是不鼓励的,因此答案应该是搜索解决方案的终点(与另一个参考文献的中途停留相比,随着时间的推移,它们往往会变得过时)。请考虑在这里添加一个独立的概要,保持链接作为参考。请详细说明链接,以更好地帮助OP。这个视频真的很有用!我不知道为什么会投反对票!这是一个非常好的输入+1.