动态随机存取存储器访存冲突
字数 1897 2025-12-05 05:07:28
动态随机存取存储器访存冲突
我们先从一个简单的场景理解这个概念。想象一个大型仓库(代表内存),里面有许多排货架(代表存储单元)。有许多搬运工(代表内存控制器或处理器核心)需要从这个仓库里取货或存货。访存冲突,就是当两个或更多的搬运工试图同时操作同一个货架,或者操作方式相互干扰时,发生的情况。这会导致搬运工们必须等待,从而降低整体工作效率。
现在,让我们深入这个仓库的内部结构来理解冲突的具体原因。
第一步:理解DRAM的基本访问单位——Bank
- 核心结构:DRAM芯片在逻辑上被划分为多个独立的子阵列,称为Bank。你可以把每个Bank看作仓库里的一个独立“库区”。每个库区都有自己的“门”(行地址选择器)和内部的货架系统。
- 并行潜力:多个Bank的设计初衷是实现并行访问。理论上,处理器可以同时访问不同的Bank(比如从Bank 0读取,同时向Bank 1写入),而不会相互影响,从而提升数据吞吐量。
- Bank内的操作:对一个特定Bank的一次完整数据访问分为两步:
- 激活:打开库区的“门”(激活目标行),将该行所有存储单元的数据复制到该Bank专用的、高速但微小的临时存储区——行缓冲器 中。这个过程相对耗时。
- 列读写:在行缓冲器就绪后,再根据列地址,快速读取或修改行缓冲器中特定位置的数据。
第二步:识别访存冲突的主要类型
访存冲突发生在对同一个Bank或共享资源的争用上。主要类型有:
-
Bank冲突:
- 定义:当连续的访存请求需要访问同一个Bank的不同行时发生。
- 过程:假设一个请求刚激活了Bank 0的行A,数据还在其行缓冲器中。此时,另一个请求需要访问Bank 0的行B。由于一个Bank在任一时刻只能有一行数据在行缓冲器中活跃,控制器必须先执行“预充电”命令来关闭当前打开的行A,才能去激活新的行B。
- 后果:这引入了显著的延迟(预充电 + 新行激活时间),迫使后续请求等待,严重降低了带宽利用率。这是最常见也最需要避免的冲突类型。
-
行缓冲器冲突:
- 定义:当连续的访存请求需要访问同一个Bank的同一行,但不同的列时发生。
- 过程:这听起来是理想情况,因为行已激活,数据就在行缓冲器中,可以快速进行列访问。然而,如果这两个请求靠得太近,而Bank的列访问路径(数据总线)在前一个请求完成前被占用,后一个请求仍需短暂等待。
- 后果:这种冲突的延迟远小于Bank冲突,但依然存在,是微架构优化需要考虑的因素。
-
总线/命令冲突:
- 定义:当多个访存请求竞争使用连接内存控制器和DRAM芯片的共享资源时发生。
- 资源:这些资源包括:
- 地址/命令总线:用于发送激活、读、写、预充电等指令。
- 数据总线:用于传输实际读写的数据。
- 后果:即使请求访问的是不同的Bank,如果它们需要同时使用同一组总线,也必须排队。例如,数据总线在同一时刻只能为一个读或写请求服务。
第三步:理解冲突的根源和影响
- 物理根源:冲突的根本原因在于DRAM的物理结构。每个Bank只有一套行地址解码器、行缓冲器和内部数据通路。这些是共享资源,无法被同时用于多个不同的行操作。
- 性能影响:访存冲突直接导致延迟增加和带宽利用率下降。内存控制器的核心调度任务之一,就是通过巧妙的请求排序和调度,尽可能将请求引导至不同的Bank,并减少对行的频繁切换(即减少“行切换”),从而最小化冲突。
- 系统级影响:在多核处理器系统中,多个核心同时生成内存请求,使得访存冲突的概率大大增加。糟糕的内存访问模式(例如,多线程程序频繁访问相隔较远、但恰好映射到同一Bank不同行的地址)会导致严重的性能瓶颈,即所谓的“内存墙”问题之一。
第四步:了解缓解访存冲突的技术
为了降低冲突的影响,现代计算机系统采用了多种软硬件技术:
- 内存控制器调度算法:
- 先就绪先服务:优先调度那些目标行已经打开(行命中)的请求。
- 首次就绪:一种更激进的算法,会稍微打乱请求顺序,优先选择能立即服务的请求,即使它不是最早到达的。
- Bank交织:通过地址映射技术,确保连续的内存地址尽可能均匀地分布在不同的Bank上,从而提升并行性。
- 增加Bank数量:现代DDR内存芯片拥有多个Bank Group(银行组),每组内包含多个Bank。这进一步增加了并行访问的粒度,因为访问不同Bank Group的冲突更小。
- 软件优化:程序员或编译器可以通过优化数据结构和内存访问模式,使线程更多地访问连续的内存区域(提高空间局部性),并减少对同一内存区域的交叉访问,从而从源头上降低冲突概率。