2010-10-01 37 views
16

有一件事我没有想出来,谷歌没有帮助我,为什么有可能银行与共享内存冲突,但不是在全球内存?银行可以与寄存器冲突吗?为什么Cuda/OpenCL在全局内存中没有银行冲突?

UPDATE 哇我真的很感谢Tibbit和灰熊的两个答案。看来,我只能给一个绿色的复选标记一个答案,但。我对堆栈溢出很陌生。我想我必须选择一个最好的答案。我可以做些什么来表达谢意,我不给绿色检查的答案吗?

+0

您可以随时给予好评的任何问题或答案你喜欢 – Grizzly 2010-10-04 18:47:31

+0

银行的冲突可以在存储器层次结构的其他级别以及寄存器文件发生。共享内存组冲突可以显着影响内核性能,并且完全由开发人员控制。其他类型的银行冲突对性能影响较小,开发人员无法解决,因此无法与开发人员沟通。 – 2012-11-28 05:42:23

回答

32

简短回答:在全局内存或寄存器中都没有银行冲突。

说明:

理解的关键原因是要把握操作的粒度。单个线程不访问全局内存。全局内存访问是“合并”的。由于全局内存太慢,块内线程的任何访问都被分组在一起,以尽可能少地向全局内存发出请求。

共享内存可以被线程同时访问。当两个线程尝试访问同一个银行内的地址时,这会导致银行冲突。

寄存器不能被任何线程访问,除了分配给它的那个线程。由于您无法读取或写入我的寄存器,因此您无法阻止我访问它们 - 因此,没有任何银行冲突。

谁能读&写信给全球内存?

Only blocks。一个线程可以访问,但事务将在块级别进行处理(实际上是warp/half warp级别,但我不会变得复杂)。如果两个模块访问相同的内存,我认为这不会花费更长的时间,并且最新设备中的L1缓存可能会加速它 - 尽管这并不明显。

谁可以阅读&写入共享内存?

Any thread within a given block.如果你只有每块1线你不能有一个银行的冲突,但你不会有合理的性能。发生银行冲突是因为一个块被分配了几个线程,比如说512个线程,并且它们都在同一个银行内寻找不同的地址(不完全相同的地址)。在CUDA C编程指南 - 图G2,第167页(实际上是pdf的第177页)结尾处,有一些这些冲突的优秀图片。 Link to version 3.2

谁可以阅读&写入寄存器?

Only the specific thread to which it is allocated.因此,一次只有一个线程正在访问它。

+0

注意,我对L1缓存的评论实际上是我自己的问题 - 确实发生在L1缓存银行冲突。由于这完全是在硬件中处理的,我不相信我们在最新的文档中被告知。 (但L1仅在最新的2. *硬件 - 所以如果你没有费米GPU,这点它静音)。 – 2010-10-02 19:54:43

22

在给定类型的内存中是否可能存在bank冲突显然取决于内存结构及其目的。

那么,为什么共享内存设计的方式允许银行冲突呢?

这相对简单,它不容易设计一个内存控制器,它可以同时处理对同一内存的独立访问(事实证明,大多数不能)。因此,为了让每个线程都能够访问一个单独的地址单词,内存就被存储起来了,每个银行都有一个独立的控制器(至少这是怎么想的,不知道实际的硬件)。这些银行交错使顺序线程快速访问顺序存储器。因此,每个银行都可以同时处理一个请求,理想情况下允许在半war中同时执行所有请求(显然,由于这些银行的独立性,这个模型在理论上可以维持更高的带宽,这也是一个优点)。

寄存器怎么样?

寄存器设计为作为ALU指令的操作数访问,这意味着它们必须以非常低的延迟进行访问。因此他们可以获得更多的晶体管/位来实现这一点。我不确定在现代处理器中访问的是完全相同的寄存器(不是那种经常需要的信息,也不容易找到)。然而,在银行中组织寄存器显然是非常不现实的(对于更简单的架构,您通常会看到所有寄存器挂在一个大的多路复用器上)。所以不会,寄存器不会有银行冲突。

全局内存

首先全局内存的工作在不同的granuality然后共享内存。内存以32,64或128byte块访问(对于GT200,至少对于Fermi来说,它始终是128B,但缓存,AMD有点不同),每次你想从块中获得某些东西时,访问/传输整个块。这就是为什么你需要合并访问的原因,因为如果每个线程从不同的块访问内存,你必须传输所有的块。

但谁说没有银行冲突?我并不完全确定这一点,因为我还没有发现任何实际的资源来支持NVIDIA硬件,但它似乎是合乎逻辑的: 全球存储器通常分配给几个RAM芯片(可以通过查看一个图形卡)。如果这些芯片中的每一个都像本地存储器银行一样,那么如果在同一个银行上有多个同时发生的请求,就会发生银行冲突。然而,对于一件事情,这种影响会少得多(因为内存访问所消耗的大部分时间是无论如何都会将数据从A传输到B的延迟),并且它不会在一个工作组内“不可见” (因为一次只有一个半warp执行,如果这个halfwarp发出的请求多于一个,那么你有一个不合并的内存访问,所以你已经受到一次冲击,很难测量这个冲突的影响。所以你只会遇到冲突几个工作组试图访问同一个银行在你典型的gpgpu情况下,你有一个大的数据集位于顺序存储器中,所以这些影响不应该是真的不可见的,因为有足够的其他工作组同时访问其他银行,但它应该可以构建数据集中仅存在于少数几家银行的情况,这会造成对带宽的冲击(因为最大带宽将来自所有银行的平均分配接入,所以每家银行都会只有该带宽的一小部分)。再次,我没有看过任何证明nvidia硬件理论的东西(大多数情况下都集中在合并,当然这更重要,因为它使得自然数据集成为非问题)。然而,根据ATI Stream计算指南,这是Radeon卡的情况(对于5xxx:银行间隔2kb,并且您希望确保您在所有银行中均匀分配您的访问(意味着来自所有模拟活动的worgroups)),所以我会想象NVidia卡的行为是相似的。

当然对于大多数scenarious全球记忆体冲突的可能性是一个非的问题,因此在实践中,你可以说:

  • 手表合并访问全局内存
  • 关注银行时发生冲突时,访问本地内存
  • 没有问题访问寄存器
+0

也注意全球记忆露营的分区! – mch 2010-10-06 22:40:29

+1

寻找在分区露营的信息,我一头栽进这个答案。你说得对,全局内存物理分区中分成,而一些访问模式甚至可能产生冲突时,访问被合并(查看关于矩阵的文档转的CUDA SDK例子)。然而,在费米架构和一般用于与计算能力2.x设备,全球存储器访问高速缓存,32字节的宽度,和地址被散列,所以理论上分区露营不应该是一个问题。 – Auron 2012-07-18 10:07:28

+0

不要在内存架构,这些改进计算能力> = 2.0还减少分区露营为全球内存的影响*写*? – 2012-12-07 15:22:44

3

多个线程访问相同的银行并不一定意味着存在银行股份有限公司nflict。如果线程想同时从同一个银行内的不同行读取,则会发生冲突。