为什么不';Cuda/OpenCL的全局内存中是否存在银行冲突?

为什么不';Cuda/OpenCL的全局内存中是否存在银行冲突?,cuda,opencl,nvidia,bank-conflict,Cuda,Opencl,Nvidia,Bank Conflict,有一件事我还没有弄明白,谷歌也帮不了我,那就是为什么共享内存中可能存在银行冲突,而全局内存中却没有?银行是否会与登记簿发生冲突 更新 哇,我真的很感激提比特和灰熊的两个答案。看来我只能给一个答案打绿色的勾。我是个新手。我想我得选一个最好的答案。我能对我没有绿色支票的答案说声谢谢吗?简短回答:全局内存或寄存器中都没有银行冲突 说明: 理解原因的关键是掌握操作的粒度。单个线程不访问全局内存。全局内存访问是“联合的”。由于全局内存非常慢,因此块中线程的任何访问都被分组在一起,以便对全局内存发出尽可能少

有一件事我还没有弄明白,谷歌也帮不了我,那就是为什么共享内存中可能存在银行冲突,而全局内存中却没有?银行是否会与登记簿发生冲突

更新
哇,我真的很感激提比特和灰熊的两个答案。看来我只能给一个答案打绿色的勾。我是个新手。我想我得选一个最好的答案。我能对我没有绿色支票的答案说声谢谢吗?

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

说明:

理解原因的关键是掌握操作的粒度。单个线程不访问全局内存。全局内存访问是“联合的”。由于全局内存非常慢,因此块中线程的任何访问都被分组在一起,以便对全局内存发出尽可能少的请求

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

寄存器不能被任何线程访问,除了分配给它的线程。因为您不能读取或写入我的寄存器,所以您不能阻止我访问它们——因此,不存在任何银行冲突

谁可以读写全局内存?

仅块
。单个线程可以进行访问,但事务将在块级别(实际上是扭曲/半扭曲级别,但我尽量不复杂)进行处理。如果两个块访问同一个内存,我不认为需要更长的时间,而且最新设备中的一级缓存可能会加速这一过程——尽管这并不明显

谁可以读写共享内存?

给定块内的任何线程。
如果每个块只有一个线程,则不会发生库冲突,但不会有合理的性能。银行冲突的发生是因为一个块分配了多个线程,比如512个线程,它们都在同一银行内争夺不同的地址(不是完全相同的地址)。在CUDAC编程指南的末尾有一些关于这些冲突的精彩图片——图G2,第167页(实际上是pdf的第177页)

谁能读写寄存器?


只有分配给它的特定线程。
因此一次只有一个线程在访问它。

给定类型的内存上是否可能存在内存组冲突显然取决于内存的结构,因此取决于它的用途

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

这是相对简单的,它不容易设计一个内存控制器,可以同时处理对同一内存的独立访问(事实证明,大多数不能)。因此,为了允许半扭曲中的每个线程访问一个单独的寻址字,内存被存储起来,每个存储库都有一个独立的控制器(至少人们可以这样认为,但不确定实际的硬件)。这些组是交错的,以使顺序线程快速访问顺序内存。因此,这些库中的每一个都可以一次处理一个请求,理想情况下允许在halfwarp中并发执行所有请求(显然,由于这些库的独立性,该模型在理论上可以维持更高的带宽,这也是一个优点)

寄存器呢?

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

全局内存

首先,全局内存工作在不同的granuality上,然后是共享内存。内存以32、64或128字节的块访问(至少对于GT200,对于费米,它总是128B,但缓存,AMD有点不同),每当您想要从块中获取某些内容时,整个块都会被访问/传输。这就是为什么需要合并访问,因为如果每个线程从不同的块访问内存,那么必须传输所有块

但谁说没有银行冲突?我不完全确定这一点,因为我还没有找到任何支持NVIDIA硬件的实际来源,但似乎符合逻辑: 全局内存通常分配给几个ram芯片(通过查看图形卡可以轻松验证)。这是有道理的,如果这些芯片中的每一个都像一个本地内存库,那么如果在同一个内存库上同时有多个请求,那么就会出现内存库冲突。然而,一方面,这种影响要小得多(因为内存访问所消耗的大部分时间都是从A到B获取数据的延迟),而且在一个工作组的“内部”不会产生明显的影响(由于一次只执行一个半扭曲,并且如果该半扭曲发出的请求多于一个,则您有一个未恢复的内存访问,因此您已经受到影响,难以衡量此冲突的影响。因此,只有当多个工作组尝试访问同一个库时,您才会遇到冲突。在gpgpu的典型情况下,您有一个大的数据集位于顺序内存中,因此其影响不应该真正被注意到,因为有足够多的其他工作组同时访问其他数据库