TMA
由 Intel 提出,经典论文: (PDF) A Top-Down method for performance analysis and counters architecture 作者在论文中提到,这个方式已经被 vTune 采纳了。
Top-Down性能分析方法(原理篇):揭秘代码运行瓶颈面对性能分析一筹莫展?不清楚该关注哪些性能指标或事件?借助Top - 掘金 这篇文章对论文进行了讲解,很细致。
最重要最重要的需要时刻记在心里的图,就是论文中的 Figure 2: The Top-Down Analysis Hierarchy:
iCache miss 和 iTLB miss 都归在 Frontend Bound 上,dTLB miss 和 dCache miss 归在 Backend Bound 上。
- iTLB miss:处理器根据 PC 寄存器中的虚拟内存地址进行内存中代码获取,但是 TLB 中没有对应虚拟内存地址翻译到物理内存地址的页表项,所以我们必须要从内存中的页表来拿,这就是 iTLB miss;
- iCache miss:处理器通过翻译得到了 PC 寄存器中的虚拟内存地址对应的物理内存地址后,去内存中拿数据,但是 Cache 中没有,只能从内存中去拿,这就是 iCache miss。
- dTLB miss 和 dCache miss 就是我们平时一般说的两种 miss,不需要过多解释。
为什么 Memory Bound 被归类为后端 Bound?iTLB miss/iCache miss 不还是得从内存中拿页表项/指令吗?
这是因为性能分析工具在归类时,看的不是“最终是不是访问了内存”,而是 “CPU 流水线的哪个部分被卡住了”。
另外,取指令速度过快导致频繁读取代码段打满内存带宽,几乎是不可能的。在代码段中没有办法优化访存行为,但是在数据计算的时候对内存使用方式是可以进行优化的(优化 Memory Bound 思路^)。
不同应用下不同 Bound 原因占比:
| Category | Client/Desktop Application | Server/Database/Distributed application | HPC Application |
|---|---|---|---|
| Retiring | 20-50% | 10-30% | 30-70% |
| Back-End Bound | 20-40% | 20-60% | 20-40% |
| Front-End Bound | 5-10% | 10-25% | 5-10% |
| Bad Speculation | 5-10% | 5-10% | 1-5% |
以上数据来自:Top-down Microarchitecture Analysis Method
处理器前端和后端 / Front-end and Back-end in Microarchitecture
前端和后端的分界线应该是微指令队列。前端生成的微指令会经由这里被送到后端。
CPU 设计的前端和后端是指 CPU 的两个主要部分,分别负责指令的解析和执行。
所谓的前端主要是由指令拾取(Instruction Fetch)、指令解码(Instruction Decode)、分支预测(branch predict)组成。
读取指令,解码指令,预测分支,转换指令为微操作。
后端负责执行 CPU 指令并更新寄存器状态。
优化 Memory Bound 思路
Memory Latency Bound 是因为单次小 size 的内存访问过多,从而导致内存带宽没有拉上去。
**1. **
Memory Bandwidth Bound 表示内存带宽被打满了,需要找到瓶颈并进行优化。
1. (优化缓存命中)使用数组结构体(SoA)来代替结构体数组(AoS):
// AoS:每个对象占用一个缓存行,但遍历 age 时只使用其中一小部分
struct Person { int id; int age; double salary; };
std::vector<Person> people;
// SoA:将 age 单独放在连续数组中,遍历 age 时缓存行全部有效
struct People { std::vector<int> id; std::vector<int> age; std::vector<double> salary; };
如果只需要访问对象的某个字段,使用 SoA 布局可大幅减少缓存污染。
2. (优化缓存命中)数组代替链表
3. (减少访存次数,从而降低访存总大小)