多缓存组(Multi-Banking):让缓存像多车道高速一样并行

CPU的缓存越来越大,但单端口SRAM的访问速度跟不上处理器的发射宽度。多缓存组(Multi-Banking)技术把一个大缓存拆成多个独立的小块,让它们并行工作。


1. 单端口缓存的瓶颈

现代超标量处理器每周期可以发射多条内存指令。比如Intel Core i7每周期能发射2个load和1个store。但如果缓存是单端口的,这些请求必须排队串行处理,处理器只能干等。

更糟的是功耗。单端口缓存每次访问都要激活整个存储阵列,哪怕只读4字节。这就像为了开一盏灯,把整个楼的电闸都合上。


2. Bank化怎么破局

把缓存切成多个独立的Bank,每个Bank有自己的端口和控制逻辑。只要访问的是不同Bank,就能并行处理。

2.1 地址映射策略

最简单的映射是取模:

Bank\_ID = (Address / Block\_Size) \% Num\_Banks

假设64字节块、4个Bank:

  • 地址0x0000 → Bank 0
  • 地址0x0040 → Bank 1
  • 地址0x0080 → Bank 2
  • 地址0x00C0 → Bank 3
  • 地址0x0100 → Bank 0(循环)

这种交错(Interleaving)让连续地址分散到不同Bank,最大化并行性。

2.2 实际芯片的Bank配置

处理器 缓存层级 Bank数 设计特点
ARM Cortex-A8[1] L2 1-4可配置 根据负载动态启用,平衡带宽与功耗
Intel Core i7[2] L1D 4 支持每周期2次访问
Intel Core i7[2] L2 8 多核共享,更高并行度
AMD Opteron[3] L1D 8 每Bank 64位宽,总线512位
NVIDIA GPU L2 16+ 高并行,支持warp级访问

ARM Cortex-A8的L2缓存特别有意思——它支持1到4个Bank的软件可配置[1]。低负载时只开1个Bank省电,高负载时全开4个Bank提速。


3. Bank冲突:并行化的天敌

Bank化的前提是访问落在不同Bank。如果两个请求命中同一个Bank,就会冲突,必须串行处理。

3.1 冲突的性能代价

ISCA 2015的一项研究[4][5]测量了Bank冲突的影响:

  • 测试配置:4周期发射到执行延迟的乱序处理器,双发射load能力
  • Bank配置:4-Bank L1D缓存(类似Intel Core i7)
  • 结果:Bank冲突导致平均4.7%性能损失(相比理想双端口缓存)
  • 微指令重放:因冲突重放的微指令占总发射的5.1%

4.7%听起来不多,但在高性能计算中,每1%都很珍贵。

3.2 什么代码容易冲突

Stride = Block_Size × N

// 假设64字节块,4个Bank
// Stride = 256字节(0x100)
for (int i = 0; i < N; i += 64) {
    sum += array[i];  // 每次访问Bank 0
}

这种代码所有访问都落在Bank 0,其他Bank闲置,性能退化为单Bank。

矩阵转置

// 行优先存储,按列访问
for (int j = 0; j < cols; j++) {
    for (int i = 0; i < rows; i++) {
        dst[j][i] = src[i][j];  // Stride = 行大小
    }
}

如果行大小恰好是Bank数的倍数,就会产生严重冲突。

3.3 缓解冲突的方法

增加Bank数

从4 Bank增加到8 Bank,冲突概率理论上减半。但面积和功耗也增加。

非线性映射

用哈希函数替代简单取模:

Bank\_ID = (Address \gg 6) \oplus (Address \gg 10) \& 0x3

这种XOR哈希能打乱规律性访问模式,减少冲突。

软件层面的Loop Interchange

编译器优化可以把:

// 原始代码 - 可能冲突
for (j) for (i) dst[j][i] = src[i][j];

变成:

// 优化后 - 连续访问
for (i) for (j) dst[j][i] = src[i][j];

4. 硬件实现细节

4.1 Bank选择逻辑

地址的低位直接选择Bank,高位用于Tag比较和行内偏移。

以Intel Core i7的L1D为例(4 Bank,64字节行):

地址位 用途
[5:0] 块内偏移(64字节)
[7:6] Bank选择(4 Bank)
[31:8] Tag比较

这样Bank选择可以在1个周期内完成,不增加关键路径延迟。

4.2 多端口的假象

多Bank不是真正的多端口。每个Bank仍然是单端口,只是多个Bank可以并行。

如果两个请求命中同一Bank,必须仲裁。常用策略:

  • 轮询(Round-Robin):公平但可能延迟关键路径
  • 优先级:老请求优先,或load优先于store
  • 年龄:最老的请求优先,保证前进

4.3 面积与功耗权衡

Bank数 控制逻辑面积 动态功耗 峰值带宽
1 1x 1x 1x
4 ~1.3x 0.6x(相同访问模式) 4x
8 ~1.6x 0.4x 8x

注意动态功耗列。多Bank能降低功耗,因为每次只激活一个Bank的小阵列,而不是整个大阵列。

ARM Cortex-A8的实测数据[1]:4 Bank配置比1 Bank节省约35%动态功耗(相同负载下)。


5. 与乱序执行的协同

多Bank缓存和乱序执行处理器是绝配。

5.1 动态调度避免冲突

乱序执行核可以重排指令,把访问不同Bank的load提前,冲突的推迟。

Intel Core i7的Memory Disambiguator会预测load-store别名,同时考虑Bank冲突,选择最优发射顺序。

5.2 Schedule Shifting优化

ISCA 2015提出的Schedule Shifting技术[5]

当双发射两个load时,让第二个load的依赖指令晚一个周期发射。这样即使第二个load遇到Bank冲突,额外的周期可以被掩盖。

效果:

  • 恢复2.8%的性能损失(从4.7%降到1.9%)
  • 减少74.8%因Bank冲突导致的微指令重放

实现成本极低——只需要在调度器中加一个周期的偏移。


6. GPU中的极致Bank化

GPU对Bank化的需求比CPU更强烈。

6.1 Warp级并行访问

一个Warp(32线程)同时执行,每个线程可能访问不同地址。如果这32个地址分散在32个Bank,可以一次完成;如果都挤在一个Bank,需要32个周期。

6.2 Shared Memory的Bank冲突

NVIDIA GPU的Shared Memory有32个Bank(计算能力3.0+)。

无冲突访问

// 每个线程访问不同Bank
int val = shared[threadIdx.x];  // Bank = threadIdx.x % 32

冲突访问

// 所有线程访问Bank 0
int val = shared[0];  // 32周期串行

部分冲突

// Stride=2,线程0,2,4...访问Bank 0,2,4...(偶数Bank)
// 线程1,3,5...访问Bank 1,3,5...(奇数Bank)
// 需要2周期完成
int val = shared[threadIdx.x * 2];

6.3 广播机制

如果32个线程都读同一个地址,GPU可以广播,只读一次分给所有线程。这不算是Bank冲突。


7. 实际调试:如何检测Bank冲突

Intel PMU(Performance Monitoring Unit)可以统计:

  • L1D_PEND_MISS.PENDING:L1D pending miss周期
  • L1D_PEND_MISS.FB_FULL:Fill Buffer满(可能由Bank冲突引起)

ARM Cortex-A8有L2CC寄存器可以监控L2 Bank使用情况[1]

8. 总结

特性 单Bank 多Bank
峰值带宽 高(随Bank数线性增长)
访问延迟 固定 可能因冲突增加
功耗效率 低(每次激活整个阵列) 高(只激活一个Bank)
面积开销 高(控制逻辑复制)
实现复杂度 简单 需要仲裁和冲突处理

多Bank缓存是带宽和功耗的权衡艺术:

  • Bank数太少:并行度不够,容易冲突
  • Bank数太多:面积功耗爆炸,收益递减

实际设计的甜点区:

  • L1缓存:4-8 Bank
  • L2缓存:8-16 Bank
  • GPU Shared Memory:32 Bank

理解Bank化,写代码时就能避免Stride陷阱,做体系结构设计时也能做出合理的权衡。


参考


================================================================================


  1. ARM Cortex-A8 Technical Reference Manual. L2 Cache Bank Structure.

  2. Computer Systems Engineering, SJTU. Multibanked Caches Lecture Notes.

  3. AMD Opteron Processor Data Sheet. Cache banking implementation with 8 banks.

  4. ISCA 2015. Cost-Effective Speculative Scheduling in High Performance Processors.

  5. Hal-01193233. Cost-Effective Speculative Scheduling in High Performance Processors (Extended Version).

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容