Answers:
对于nvidia(以及相应的AMD)GPU,本地内存分为记忆库。每个存储库一次只能寻址一个数据集,因此,如果半弯尝试从同一存储库加载数据/将数据存储到同一存储库,则访问必须序列化(这是存储库冲突)。对于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 |...
...
因此,如果半扭曲中的每个线程都访问连续的32位值,则不会出现存储体冲突。广播此规则的一个例外(每个线程必须访问其自己的存储区):如果所有线程都访问相同的地址,则该值仅读取一次并广播到所有线程(对于GT200,它必须是半warp中的所有线程才能访问该线程)。相同的地址,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
通常,编译器通过缓冲数组或使用数组中的素数来避免此类问题。
(CUDA银行冲突)我希望这会有所帮助..这是一个很好的解释...
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 ... |
希望这会有所帮助