清单 8. 489.Xalancbmk 基准的 'opreport -' 输出(计数器 PM_DATA_FROM_L2_GRP91 和 PM_DATA_FROM_L3_GRP91)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| CPU: ppc64 POWER7, speed 3550 MHz (estimated)
Counted PM_DATA_FROM_L2_GRP91 events ((Group 91 pm_dsource1) The processor's Data Cache
was reloaded from the local L2 due to a demand load.) with a unit mask of 0x00 (No unit
mask) count 1000
Counted PM_DATA_FROM_L3_GRP91 events ((Group 91 pm_dsource1) The processor's Data Cache
was reloaded from the local L3 due to a demand load.) with a unit mask of 0x00 (No unit
mask) count 1000
samples % samples % image name app name symbol name
767827 25.5750 7581 0.2525 gcc_base.none gcc_base.none bitmap_element_allocate
377138 12.5618 8341 0.2778 gcc_base.none gcc_base.none bitmap_operation
93334 3.1088 3160 0.1052 gcc_base.none gcc_base.none bitmap_bit_p
70278 2.3408 5913 0.1969 libc-2.13.so libc-2.13.so _int_free
56851 1.8936 22874 0.7618 oprofile oprofile /oprofile
47570 1.5845 2881 0.0959 gcc_base.none gcc_base.none rehash_using_reg
41441 1.3803 8532 0.2841 libc-2.13.so libc-2.13.so _int_malloc
|
清单 9. 489.Xalancbmk 基准的 'opreport -' 输出(计数器 PM_DATA_FROM_LMEM_GRP91 和 PM_DATA_FROM_RMEM_GRP91)1
2
3
4
5
6
7
8
9
10
11
12
13
14
| Counted PM_DATA_FROM_LMEM_GRP91 events ((Group 91 pm_dsource1) The processor's Data Cache
was reloaded from memory attached to the same module this proccessor is located on.) with
a unit mask of 0x00 (No unit mask) count 1000
Counted PM_DATA_FROM_RMEM_GRP91 events ((Group 91 pm_dsource1) The processor's Data Cache
was reloaded from memory attached to a different module than this proccessor is located
on.) with a unit mask of 0x00 (No unit mask) count 1000
samples % samples % image name app name symbol name
1605 0.3344 0 0 gcc_base.none gcc_base.none bitmap_element_allocate
1778 0.3704 0 0 gcc_base.none gcc_base.none bitmap_operation
1231 0.2564 0 0 gcc_base.none gcc_base.none bitmap_bit_p
205 0.0427 0 0 libc-2.13.so libc-2.13.so _int_free
583 0.1215 327 100.000 oprofile oprofile /oprofile
0 0 0 0 gcc_base.none gcc_base.none rehash_using_reg
225 0.0469 0 0 libc-2.13.so libc-2.13.so _int_malloc
|
解释概要文件输出显示,大多数缓存压力来自 L2 访问,几乎不需求从 L3 重载,因为 L2 访问 (PM_DATA_FROM_L2) 的计数器采样值的总数和相对值都比 L3 需求重载 (PM_DATA_FROM_L3) 要高一些。通过进行更全面的分析(通过监视更多计数器),您只能获得进一步的信息,像 L2 访问是否由于缓存未命中而造成 CPU 停滞。从该示例概要文件可以得出的结论是,与缓存访问相比,主内存访问(PM_DATA_FROM_LMEM 事件)相当低,并且没有远程访问(事件 PM_DATA_FROM_RMEM),这意味着没有远程 NUMA 节点内存访问。热点和内存访问模式的分析可以提供优化工作的方向;在本例中,需要进一步进行分析,确定究竟是什么造成 CPU 停顿,因为对于正确识别 CPU 停顿而言,只是简单识别工作负载热点和内存访问模式是远远不够的。
为了制定更好的性能优化策略,需要使用 perf 工具而不是 OProfile 来做进一步的分析,因为需要同时监视很多 POWER7 CMB 计数器,所以中显示了 22 个计数器,以便为性能优化提供更好的策略。许多事件都位于不同的组中,这意味着使用 OProfile 需要多次运行相同的工作负载。若指定的计数器位于多个组中,那么 perf 工具将会复用硬件计数器的监视。虽然这会产生一个准确度稍低的结果,但整体结果往往与预期非常近似,并且具有可以在更短时间内完成分析的优势。
下面的示例使用 perf 分析同一个 SPECcpu2006 483.xalancbmk 组件。要分析这个组件,可以发出 的命令:
清单 10. 对生成的 POWER7 CBM 发出的 perf 命令1
2
3
| $ /usr/bin/perf stat -C 0 -e r100f2,r4001a,r100f8,r4001c,r2001a,r200f4,r2004a,r4004a,
r4004e,r4004c,r20016,r40018,r20012,r40016,r40012,r20018,r4000a,r2001c,r1001c,r20014,
r40014,r30004 taskset -c 0 ./Xalan_base.none -v t5.xml xalanc.xsl > power7_cbm.dat
|
此命令会导致 perf 监视通过 -c 指定的 CPU 上的 -e 参数所定义的原始事件。任务集调用确保该组件将只在 CPU 0 上运行。工作负载 ./Xalan_base.none -v t5.xml xalanc.xsl 可以被另一个应用程序替代为概要文件。完成概要文件的处理之后,perf 命令会输出一个简单的表,显示每个原始事件的总数,以及所花费的总秒数:
清单 11. 489.Xalancbmk 基准的 'perf stat' 输出1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| Performance counter stats for 'taskset -c 0 ./Xalan_base.none -v t5.xml xalanc.xsl':
366,860,486,404 r100f2 [18.15%]
8,090,500,758 r4001a [13.65%]
50,655,176,004 r100f8 [ 9.13%]
11,358,043,420 r4001c [ 9.11%]
10,318,533,758 r2001a [13.68%]
1,301,183,175,870 r200f4 [18.22%]
2,150,935,303 r2004a [ 9.10%]
0 r4004a [13.65%]
211,224,577,427 r4004e [ 4.54%]
212,033,138,844 r4004c [ 4.54%]
264,721,636,705 r20016 [ 9.09%]
22,176,093,590 r40018 [ 9.11%]
510,728,741,936 r20012 [ 9.10%]
39,823,575,049 r40016 [ 9.07%]
7,219,335,816 r40012 [ 4.54%]
1,585,358 r20018 [ 9.08%]
882,639,601,431 r4000a [ 9.08%]
1,219,039,175 r2001c [ 9.08%]
3,107,304 r1001c [13.62%]
120,319,547,023 r20014 [ 9.09%]
50,684,413,751 r40014 [13.62%]
366,940,826,307 r30004 [18.16%]
461.057870036 seconds time elapsed
|
为了分析针对 POWER7 CBM 的 perf 输出,我们提供了一个 Python 脚本(在 中检查 power7_cbm.zip),该脚本由收集到的虚拟和硬件计数器的计数器指标组成。要创建一个报告,可以发出 中的命令:
清单 12. POWER7 CBM python 脚本调用1
| $ power7_cbm.py power7_cbm.dat
|
类似于 的输出将被打印出来:
清单 13. 489.Xalancbmk 基准的 'power7_cbm.py' 输出1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| CPI Breakdown Model (Complete)
Metric : Value : Percent
PM_CMPLU_STALL_DIV : 49802421337.0 : 0.0
PM_CMPLU_STALL_FXU_OTHER : 67578558649.0 : 5.2
PM_CMPLU_STALL_SCALAR_LONG : 2011413.0 : 0.0
PM_CMPLU_STALL_SCALAR_OTHER : 7195240404.0 : 0.6
PM_CMPLU_STALL_VECTOR_LONG : 0.0 : 0.0
PM_CMPLU_STALL_VECTOR_OTHER : 1209603592.0 : 0.1
PM_CMPLU_STALL_ERAT_MISS : 22193968056.0 : 1.7
PM_CMPLU_STALL_REJECT_OTHER : 18190293594.0 : 1.4
PM_CMPLU_STALL_DCACHE_MISS : 261865838255.0 : 20.3
PM_CMPLU_STALL_STORE : 2001544985.0 : 0.2
PM_CMPLU_STALL_LSU_OTHER : 202313206181.0 : 15.7
PM_CMPLU_STALL_THRD : 2025705.0 : 0.0
PM_CMPLU_STALL_BRU : 208356542821.0 : 16.2
PM_CMPLU_STALL_IFU_OTHER : 2171796336.0 : 0.2
PM_CMPLU_STALL_OTHER : 30895294057.0 : 2.4
PM_GCT_NOSLOT_IC_MISS : 9805421042.0 : 0.8
PM_GCT_NOSLOT_BR_MPRED : 7823508357.0 : 0.6
PM_GCT_NOSLOT_BR_MPRED_IC_MISS : 11059314150.0 : 0.9
PM_GCT_EMPTY_OTHER : 20292049774.0 : 1.6
PM_1PLUS_PPC_CMPL : 365158978504.0 : 28.3
OVERHEAD_EXPANSION : 590057044.0 : 0.0
Total : 96.1
|
这份报告以误差范围内的统计值为基础,所以最终的比例并不完全准确。即使误差范围较大,CPU 总停滞中仍然只有大约 20% 是由于数据缓存未命中 (PM_CMPLU_STALL_DCACHE_MISS) 引起的。最后的指令完成百分比 (PM_1PLUS_PPC_CMPL) 也有 28% 左右。
未来的优化应尝试通过降低 CPU 停滞和/或 GCT (Global Completion Table) 百分比将该数字最大化。根据这份报告,另一个分析途径是识别发生停滞的代码。要做到这一点,可以使用 perf record 命令。该命令将追踪原始计数器的性能,并利用进程回溯来创建一个映射,从而识别哪个符号生成最多的硬件事件。这类似于 OProfile 的工作方式。在本例中,要跟踪 PM_CMPLU_STALL_DCACHE_MISS 事件,可以发出 中的命令:
清单 14. PM_CMPLU_STALL_DCACHE_MISS 事件的 perf record1
| $ /usr/bin/perf record -C 0 -e r20016 taskset -c 0 ./Xalan_base.none -v t5.xml xalanc.xsl
|
perf 命令将利用结果创建一个数据文件(通常是 "perf.dat")。使用 perf record 命令能够以交互方式读取它,如 所示: |