Golang中Mechanical Sympathy的Critical Stride概念及计算逻辑咨询
Critical Stride 核心问题解答
1. 缓存组映射的基本逻辑
现代CPU的L1/L2缓存多采用组相联结构:
- 缓存被划分为若干个「组(Set)」,每个组包含固定数量的缓存行(由相联度决定,比如8路相联就是每组8行)
- 内存中的每个缓存行,会通过地址计算映射到唯一的缓存组,计算规则为:
(内存地址 / 缓存行大小) % 缓存组数 = 目标组索引
Critical Stride的本质是:当按某个步长访问数组时,所有被加载的缓存行都映射到同一个缓存组,导致该组内的缓存行被持续替换,缓存命中率直接暴跌。
2. 公式推导与512元素触发的原因
以演讲幻灯片对应的典型x86架构L1数据缓存为例(32KB总大小、8路相联、64字节缓存行):
- 第一步:计算缓存组数
缓存组数 = 缓存总大小 / (相联度 * 缓存行大小) = 32768B / (8 * 64B) = 64 - 第二步:计算Critical Stride对应的内存地址步长
要让新缓存行都落到同一组,地址步长需等于「组数 * 缓存行大小」,即64 * 64B = 4096B = 4KB - 第三步:转换为元素数量
若数组元素是8字节(比如long类型),则元素步长为:4096B / 8B = 512
这就是为什么512个元素会触发Critical Stride——每次跳过512个8字节元素,内存地址正好跳4KB,刚好让每个新缓存行都映射到同一组,组内的8个缓存行很快被占满,后续访问只能不断替换旧行,完全失去缓存优势。
3. 通用计算方法
要确定触发Critical Stride的元素数量,只需明确4个参数:目标缓存总大小、缓存相联度、缓存行大小、数组元素字节大小,按以下步骤计算:
- 计算缓存组数:
组数 = 缓存总大小 / (相联度 * 缓存行大小) - 计算Critical Stride的内存步长:
内存步长 = 组数 * 缓存行大小 - 转换为元素数量:
元素步长 = 内存步长 / 元素字节大小
比如换用4字节的int元素,同规格缓存下,元素步长就是4096B /4B=1024,即跳过1024个int元素会触发Critical Stride。
内容的提问来源于stack exchange,提问作者Tarun
相关产品推荐
相关产品推荐

