测验:内存层次
缓存以 64 字节缓存行为单位而不是逐字节取数据,主要原因是什么?
- 由于空间局部性,相邻地址很可能很快被使用
- DRAM 无法读取少于 64 字节的数据
- 只是为了节省存储缓存标签的空间
- 64 字节是 CPU 寄存器的宽度
按行优先存储的二维数组沿列方向遍历时,为什么会变慢?
- 乘法和除法变多
- TLB 不支持列方向访问
- 每次访问都取回新缓存行,却只使用其中一小部分就丢弃
- 编译器不会优化列方向访问
工作集略大于 L3 缓存时发生的未命中称为什么,最合适的应对方法是什么?
- 容量未命中——用分块等方法切分工作集以增加复用
- 强制未命中——开启预取
- 冲突未命中——改变数组步幅
- 一致性未命中——减少线程数
对于算术强度(arithmetic intensity)较低的工作负载,哪种提升性能的方法最无效?
- 迁移到内存带宽更高的设备
- 通过量化减少需要读取的字节数
- 换用运算性能(peak FLOPS)更高的芯片
- 利用片上内存增加已读取数据的复用
每个线程只写自己的 8 字节计数器槽位,完全没有锁,但线程越多吞吐量越低。最可能的原因是什么?
- 伪共享——多个槽位位于同一缓存行,核心之间不断转移所有权
- 上下文切换成本线性增加
- 计数器未使用原子操作,数值损坏
- 内存分配器使用锁
原子操作的操作数跨越两个缓存行时,会发生什么?
- 操作失败并抛出异常
- 改用外部总线锁而非缓存一致性协议,耗费数百周期并影响其他核心
- 编译器自动拆成两个原子操作
- 性能不变,只是不再保证正确性
为什么必须区分内存层级中的“容量”和“带宽”?
- 容量越大,带宽也会按比例增大
- 带宽是硬件规格,容量是软件设置
- 两者实际上只是同一指标的不同叫法
- 容量决定模型能否装入,带宽决定处理速度有多快,它们回答的是不同问题