在Agner Fog的手册" C++中的优化软件 "第9.10节"大数据结构中的Cahce争论"中,他描述了当矩阵宽度等于称为临界步幅的情况时转置矩阵的问题.在他的测试中,当宽度等于临界步幅时,L1中矩阵的成本增加40%. 如果矩阵更大并且仅适用于L2,则成本为600%! 这在表9.1中的文字中得到了很好的总结.这与在为什么将512x512的矩阵转置比转置513x513的矩阵要慢得多一样是必不可少的 ?
后来他写道:
这种效果对于二级高速缓存争用而言比一级高速缓存争用强得多的原因是二级高速缓存不能一次预取多行.
所以我的问题与预取数据有关.
根据他的评论,我推断L1可以一次预取多个缓存行. 预取了多少?
据我所知,尝试编写代码来预取数据(例如使用_mm_prefetch)很少有用.我读过的唯一例子是Prefetching Examples?它只有O(10%)的改进(在某些机器上).Agner后来解释了这个:
原因是现代处理器由于无序执行和高级预测机制而自动预取数据.现代微处理器能够自动预取包含具有不同步幅的多个流的常规访问模式的数据.因此,如果可以使用固定步幅以常规模式排列数据访问,则不必显式预取数据.
那么CPU如何决定预取哪些数据,以及有哪些方法可以帮助CPU为预取做出更好的选择(例如"具有固定步幅的常规模式")?
编辑:根据Leeor的评论,让我添加我的问题并使其更有趣. 与L1相比,为什么关键步幅对L2的影响要大得多?
编辑:我试图使用代码重现Agner Fog的表格为什么转换512x512的矩阵要比转置513x513的矩阵慢得多? 我在Xeon E5 1620(Ivy Bridge)上以MSVC2013 64位版本模式运行它,它具有L1 32KB 8路,L2 256 KB 8路和L3 10MB 20路.L1的最大矩阵大小约为90x90,L3为256x256,L3为1619.
Matrix Size Average Time
64x64 0.004251 0.004472 0.004412 (three times)
65x65 0.004422 0.004442 0.004632 (three times)
128x128 0.0409
129x129 0.0169
256x256 0.219 //max L2 matrix size
257x257 0.0692
512x512 2.701
513x513 0.649
1024x1024 12.8
1025x1025 10.1
Run Code Online (Sandbox Code Playgroud)
我没有看到L1中的任何性能损失,但是L2明显具有关键的步幅问题,可能是L3.我不确定为什么L1没有出现问题.有可能还有一些其他的背景源(开销)占据了L1时代的主导地位.
在现代x86 CPU上,硬件预取是一种重要的技术,可以在用户代码明确请求之前将缓存行放入缓存层次结构的各个级别.
基本思想是,当处理器检测到对顺序或跨步连续1个位置的一系列访问时,即使在执行(可能)实际访问这些位置的指令之前,它也将继续并获取序列中的其他存储器位置.
我的问题是,预取序列的检测是基于完整地址(用户代码请求的实际地址)还是高速缓存行地址,这几乎是不包括底部6位2剥离的地址.
例如,在具有64位高速缓存行的系统上,对完整地址的1, 2, 3, 65, 150访问将访问高速缓存行0, 0, 0, 1, 2.
当一系列访问在高速缓存行寻址中比在完全寻址中更常规时,差异可能是相关的.例如,一系列完整地址,如:
32, 24, 8, 0, 64 + 32, 64 + 24, 64 + 8, 64 + 0, ..., N*64 + 32, N*64 + 24, N*64 + 8, N*64 + 0
Run Code Online (Sandbox Code Playgroud)
可能看起来不像是完整地址级别的跨步序列(实际上它可能会错误地触发向后预取器,因为4次访问的每个子序列看起来像一个8字节跨步反向序列),但是在高速缓存行级别看起来它向前发展缓存行一次(就像简单的序列一样0, 8, 16, 24, ...).
在现代硬件上采用哪种系统?
注意:也可以想象答案不会基于每次访问,而只是在预取程序正在观察的某个级别的缓存中丢失的访问,但是同样的问题仍然适用于"未命中"的过滤流访问".
1 Strided-sequential意味着访问它们之间具有相同的步幅(delta),即使该delta不是1.例如,对位置的一系列访问100, 200, 300, ...可以被检测为跨步为100的跨步访问,并且原则上,CPU将根据此模式进行提取(这意味着在预取模式中可能会"跳过"某些高速缓存行).
2这里假设一个64位高速缓存行.
我问这个关于 Haswell 微架构(英特尔至强 E5-2640-v3 CPU)的问题。从CPU和其他资源的规格我发现有10个LFB,超级队列的大小是16。我有两个关于LFB和SuperQueue的问题:
1) 系统可以提供的最大内存级并行度是多少,10 还是 16(LFB 或 SQ)?
2)根据某些来源,每个 L1D 未命中都记录在 SQ 中,然后 SQ 分配行填充缓冲区,而在其他某些来源中,他们写道 SQ 和 LFB 可以独立工作。你能简单解释一下 SQ 的工作吗?
这是 SQ 和 LFB 的示例图(不适用于 Haswell)。
参考资料:https :
//www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf
x86 ×4
architecture ×1
c ×1
caching ×1
cpu ×1
cpu-cache ×1
intel ×1
memory ×1
optimization ×1
performance ×1