使用 Counter Analyzer 进行 Performance Monitor Counter 数据分析

使用 Counter Analyzer 分析 POWER 和 Cell Broad Engine 平台的 PMC 数据

为了了解在执行应用程序时在处理器中发生的情况,处理器架构师设计了一组特殊的寄存器,它们对在处理器执行指令时发生的事件进行计数。这些寄存器称为 Performance Monitor Counter,它们提供关于处理器的重要信息,比如发生了多少次 I-cache 失效、完成了多少个指令等等。Counter Analyzer 是 Visual Performance Analyzer(一种基于 Eclipse 的性能分析工具)的插件。它可以分析原始事件、指标和 CPI 细分模型,帮助更好地了解这些事件。本文简要介绍 Performance Monitor Counter 及相关工具,然后以 Caesar 密码工具为例,讲解如何结合使用这些工具和 Counter Analyzer。

Qi Liang, 资深软件工程师, IBM

http://www.ibm.com/developerworks/i/p-qliang.jpgQi Liang 是 IBM 中国软件和技术中心的资深软件工程师。Qi 从事 GUI 性能分析工具 Visual Performance Analyzer 方面的研究。他在性能领域具备丰富的经验,精通 AIX、Linux 和 Java 上的各种性能工具。他还曾经从事 Eclipse 插件开发超过五年,在加入 IBM 之前是 Eclipse BIRT (Business Intelligence Reporting Tool) 的成员。



2009 年 4 月 16 日

Performance Monitor Counter 简介

现代处理器具有一种特殊的硬件设施,即 Performance Monitor Unit (PMU)。它用于收集与处理器中的操作相关的事件。如果发生 D-cache 失效(处理器无法在 D-cache 中找到数据),那么发出一个中断,让相应的寄存器可以通过增加它的值记录这一事件。Performance Monitor Counter (PMC) 寄存器有助于揭示芯片中发生的情况。

我们来看看 POWER5™ 中的 PMC。每个 POWER5 处理器核有 6 个 32 位 PMC 寄存器,PMC1 到 PMC6。PMC1、PMC2、PMC3 和 PMC4 是可编程的,可以通过设置 Monitor Mode Control Register 1 (MMCR1) 来指定要收集什么事件。PMC5 和 PMC6 是不可编程的,所以无论选择哪个事件组,都会收集它们。PMC5 统计代表已完成指令数的 PM_INST_CMPL,PMC6 统计代表周期数的 PM_RUN_CYC。在一般情况下,每个 PMC 递增在一个周期中发生的相应事件次数。所以,在任何时候,只能同时收集 6 种事件。处理器设计者把可以同时收集的 6 个事件定义为事件组。通过选择事件组,可以为前 4 个 PMC 指定事件。

下表列出不同 POWER 处理器的 PMC 数量。

表 1. Performance Monitor Counter 数量
处理器Performance Monitor Counter事件事件组
PowerPC 970823049
PowerPC 970 MP823051
POWER4824463
POWER4 II824463
POWER56474163
POWER5 II6483188
POWER66553202

如何使用 PMC 评估性能

使用 PMC 评估性能有三种方法,从低级到高级依次是:原始 PMC 事件、指标和 CPI 细分模型。

原始 PMC 事件提供关于在处理器中执行的代码的特定信息。例如,POWER5 中的 PM_TLB_MISS 表示发生了多少次 TLB (Translation Look-aside Buffer) 失效。TLB 缓存包含从虚拟地址到内存中物理页面的映射信息。如果发生了很多 TLB 失效,就说明代码读取大地址范围中的数据。可能需要改进空间位置。

判断性能是好还是坏以及特定事件的准确含义并不容易。您需要某种高级信息。第二种方法是指标,指标是根据事件或预定义变量定义的公式计算出的值。例如,如果希望知道 MIPS (Million Instructions per Second) 值是多少,可以定义一个名为 PMD_MIPS 的指标。根据定义,MIPS = 10-6 * 指令数 / 执行时间。当流水线(pipeline)中完成一个指令时,PM_INST_CMPL 递增 1,所以它可以作为指令计数器。有一个预定义的变量 total_time,它代表整个数据收集过程的时钟时间。所以,PMD_MIPS 定义为:PMD_MIPS = 1e-06 * PM_INST_CMPL / total_time。

最后一种方法是 CPI (Cycle per Instruction) 细分模型。CPI 表示一个指令平均占用多少个周期。这个度量值对于评估总体系统性能非常重要。CPI 值低就意味着指令花费的执行时间少。当然,这就意味着性能更好。周期数可以细分为几个部分,分别表示在不同的流水线阶段花费的时间。细分意味着按照流水线阶段把周期数划分为几个部分。

同样以 POWER5 为例,指令在流水线中停留的时间可以划分为三个部分:

  • 流水线正在处理指令,包括指令解码、发布和执行。
  • 流水线由于 GCT 是空的而停滞。
  • 流水线由于其他原因停滞。

Global completion table (GCT) 是一个表,它表示处理器当前处理的指令组。它存储指令、指令的逻辑程序次序和指令在组中的完成次序。空的 GCT 意味着流水线中没有要执行的指令。

总时间 (PMD_TOTAL_CPI)流水线正在执行指令 (PMD_CPI_CMPL_CYC)
流水线由于 GCT 是空的而停滞 (PMD_CPI_GCT_EMPTY)
流水线由于其他原因停滞 (PMD_CPI_STALL_CYC)

PMD_CPI_GCT_EMPTY 可能由以下原因导致:

  • I-cache 失效(处理器无法从指令缓存获取下一个指令)
  • 分支预测错误(处理器猜错了分支,所以它不得不更新流水线并从正确的分支装载指令)
  • 其他原因

PMD_CPI_STALL_CYC 可能由以下原因导致:

  • 由于 LSU 指令而停滞
  • 由于 FXU 指令而停滞
  • 由于 FPU 指令而停滞
  • 其他原因
总时间 (PMD_TOTAL_CPI)流水线正在执行指令 (PMD_CPI_CMPL_CYC)
流水线由于 GCT 是空的而停滞 (PMD_CPI_GCT_EMPTY)I-cache 失效 (PMD_CPI_GCT_EMPTY_IC_MISS)
分支预测错误 (PMD_CPI_GCT_EMPTY_BR_MPRED)
其他原因 (PMD_CPI_GCT_EMPTY_OTHER)
流水线由于其他原因停滞 (PMD_CPI_STALL_CYC)由于 LSU 指令而停滞 (PMD_CPI_STALL_LSU)
由于 FXU 指令而停滞 (PMD_CPI_STALL_FXU)
由于 FPU 指令而停滞 (PMD_CPI_STALL_FPU)
其他原因 (PMD_CPI_STALL_OTHERS)

通过这样划分,最终可以得到一个树结构,它称为 CPI 细分模型。CPI 细分模型完全由为特定处理器设计的 PMC 事件决定。

PMD_TOTAL_CPI - 总周期数 PMD_CPI_CMPL_CYC - 完成周期数
PMD_CPI_GCT_EMPTY - 完成表空(GCT 空)PMD_CPI_GCT_EMPTY_IC_MISS - I-Cache 失效损失
PMD_CPI_GCT_EMPTY_BR_MPRED - 分支预测错误损失
PMD_CPI_GCT_EMPTY_OTHER
PMD_CPI_STALL_CYCPMD_CPI_STALL_LSU - 由于 LSU 指令而停滞PMD_CPI_STALL_LSU_REJECT - 由于 LSU 拒绝而停滞PMD_CPI_STALL_LSU_ERAT_MISS - 由于 LSU 转换拒绝而停滞
PMD_CPI_STALL_LSU_REJECT_OTHERS
PMD_CPI_STALL_LSU_DCACHE_MISS -由于 LSU D-cache 失效而停滞
PMD_CPI_STALL_LSU_OTHERS
PMD_CPI_STALL_FXU - 由于 FXU 指令而停滞PMD_CPI_STALL_FXU_DIV - 由于任何形式的 DIV/MTSPR/MFSPR 指令而停滞
PMD_CPI_STALL_FXU_OTHERS
PMD_CPI_STALL_FPU - 由于 FPU 指令而停滞PMD_CPI_STALL_FPU_DIV - 由于任何形式的 FDIV/FSQRT 指令而停滞
PMD_CPI_STALL_FPU_OTHERS
PMD_CPI_STALL_OTHERS

收集 Performance Monitor Counter 数据的工具

许多分析工具都可以收集 PMC 数据。本文只讨论 AIX® 工具 hpmcount 和 hpmstat 以及 Cell SDK 工具 cpc(即 cellperfctr)。这些工具可以输出 XML 文件,可以把这些文件提供给 Counter Analyzer。

hpmcount 和 hpmstat - AIX

AIX V5.3 和 V6.1 提供的 hpmcount 和 hpmstat 可以从 PMC 收集事件。它们做的工作差不多,只是监视的范围不一样。hpmcount 从 hpmcount 启动的工作负载应用程序收集事件,而 hpmstat 收集整个系统的事件。

在讨论 hpmcount 和 hpmstat 之前,先谈谈 pmlist。这个实用工具列出 POWER 处理器的 PMC 事件、事件组和指标。

首先运行 pmlist,了解是否支持您使用的处理器。

清单 1. 列出 hpmcount/hpmstat 支持的所有处理器
bash-3.00# pmlist -l
Processors supported (specify with -p)
====================
RS64-II
POWER3
RS64-III
POWER3-II
POWER4
POWER4-II
POWER5
PowerPC970
POWER5-II
POWER6
PowerPC970MP

还可以用 pmlist 列出给定的处理器类型提供的事件和事件组。下面列出 POWER5 处理器的 “0” 事件组的相关信息。

清单 2. POWER5 的 “0” 事件组
bash-3.00# pmlist -p POWER5 -g 0
Group #0: pm_utilization
Group name: CPI and utilization data
Group description: CPI and utilization data
Group status: Verified
Group members:
Counter  1, event 190: PM_RUN_CYC  : Run cycles
Counter  2, event 71: PM_IOPS_CMPL  : Internal operations completed
Counter  3, event 56: PM_INST_DISP  : Instructions dispatched
Counter  4, event 12: PM_CYC [shared core] : Processor cycles
Counter  5, event  0: PM_INST_CMPL  : Instructions completed
Counter  6, event  0: PM_RUN_CYC  : Run cycles

它列出 “0” 事件组的 ID 号、名称、描述、状态和其中的 6 个事件。如果希望了解所有事件组,那么使用 “-g -1” 选项。关于 pmlist 命令的信息参见 参考资料

hpmcount

现在启动 hpmcount,收集 “0” 事件组并把结果输出到一个 XML 文件中。

清单 3. 使用 hpmcount 收集 0 事件组
bash-3.00# hpmcount –g 0 –o sleep –x sleep 2
  • -g 0 收集 0 事件组中定义的性能事件。
  • -o sleep 指定输出文件名为 sleep。
  • -x 指定 XML 输出。Counter Analyzer 需要 XML 格式的输出文件。
  • sleep 2 是要运行的工作负载应用程序。

输出文件名与 “sleep_0000.319628” 相似。把它重命名为 sleep.pmf。关于 hpmcount 的更多信息参见 参考资料

hpmstat

还可以通过运行 hpmstat 收集 “0” 事件组,但是 hpmstat 没有工作负载应用程序,因为它以全系统范围模式收集事件。

清单 4. 使用 hpmstat 收集 “0” 事件组
bash-3.00# hpmstat -g 0 -o hpmstat.pmf -x

输出文件名就是指定的名称 hpmstat.pmf。这是 hpmcount 和 hpmstat 之间的另一差异。关于 hpmstat 的更多信息参见 参考资料

多路模式

在使用 hpmcount 和 hpmstat 时,可以指定多个事件组,从而以多路模式收集事件。例如,可以使用 hpmstat 同时收集 0 和 1 事件组。

清单 5. 使用 hpmstat 同时收集 0 和 1 事件组
				bash-3.00# hpmstat -g 0,1 -o hpmstat2.pmf -x

请下载输出文件 hpmstat2.pmf。现在看看多路模式的工作方式。

处理器只有固定数量的 PMC。例如,POWER5 只有 6 个 PMC,只能同时收集一个事件组中定义的 6 个事件。因此,在多路模式中,hpmcount 和 hpmstat 控制 PMC,让它们在不同的时间片中轮流收集不同的事件组。例如,假设要在 6 个时间片(T1、T2、T3、T4、T5 和 T6)中收集两个事件组,G0 (E1、E2、E3、E4、E5 和 E6)和 G1(E7、E8、E9、E10、E5 和 E6)。E1 到 E10 是要收集的事件,G0 和 G1 都包含 E5 和 E6。在下表中,可以看到如何收集这些事件。

T1T2T3T4T5T6...
PMC1E1E7E1E7E1E7...
PMC2E2E8E2E8E2E8...
PMC3E3E9E3E9E3E9...
PMC4E4E10E4E10E4E10...
PMC5E5E5E5E5E5E5...
PMC6E6E6E6E6E6E6...
G0G1G0G1G0G1...

任何时候都会收集 E5 和 E6,但是轮流收集其他事件。因为它们的收集时间不同,所以它们的值没有可比性。为了对这些事件做某些计算,必须使用规范化的事件计数值。规范化的事件计数值使我们能够像是在整个数据收集过程中收集事件那样处理事件。规范化的事件计数值定义为 Enormalized = ∑E * Ttotal / Tevent

E1normalized = (E1T1 + E1T3 + E1T5) * (T1 + T2 + T3 + T4 + T5 + T6) / (T1 + T3 + T5)

E2normalized = (E2T1 + E2T3 + E2T5) * (T1 + T2 + T3 + T4 + T5 + T6) / (T1 + T3 + T5)

...

E5normalized = (E5T1 + E5T2 + E5T3 + E5T4 + E5T5 + E5T6) * (T1 + T2 + T3 + T4 + T5 + T6) / (T1 + T2 + T3 + T4 + T5 + T6)

...

CPC - Cell Broad Engine 上的 Cell SDK

Cell SDK 3.0 包含一个名为 CPC(即 cellperfctr,Cell Performance Counter)的工具,它从 Cell Broad Engine PMC 收集性能事件。

在开始运行 CPC 之前,需要在 Cell SDK 中找到一个名为 “simple” 的小 SPU 应用程序。可以在 cell-tutorial-source-*.*-*.rpm 中找到它。获取 Cell SDK 3.0 中的所有教程应用程序,并运行 “simple” 应用程序。

清单 6. 获得 SPU 应用程序 “simple”
bash-3.00# rpm -ql cell-tutorial-source
/opt/cell/sdk/src/tutorial_source.tar
bash-3.00# cp /opt/cell/sdk/src/tutorial_source.tar ~
bash-3.00# tar xvf tutorial_source.tar
tutorial/
tutorial/Makefile
tutorial/euler/
tutorial/euler/STEP3_multi_spe/
...
bash-3.00# cd tutorial/
bash-3.00# export CELL_TOP=/opt/cell/sdk/
bash-3.00# make
bash-3.00# cd simple/
bash-3.00# ./simple
Hello Cell (0x1820008)
Hello Cell (0x1820688)
Hello Cell (0x1820900)
Hello Cell (0x1820b98)
Hello Cell (0x1821578)
Hello Cell (0x1820e10)
Hello Cell (0x1821ce0)
Hello Cell (0x1821300)
Hello Cell (0x18221d0)
Hello Cell (0x1821088)
Hello Cell (0x18217f0)
Hello Cell (0x1821a68)
Hello Cell (0x1821f58)
Hello Cell (0x1822448)
Hello Cell (0x18226c0)
Hello Cell (0x1822938)

The program has successfully executed.
bash-3.00#

这个应用程序非常简单,它只创建 16 个 SPE 线程。每个线程输出 “Hello Cell” 和它的 ID。运行 CPC 的最简单方式是收集系统时钟周期,其事件名是 System_Clock_Cycles 或 C。

清单 7. 使用 CPC 收集系统时钟周期
bash-3.00# cpc -e C -X cycles.pmf ./simple
  • -e C 指定收集周期事件。
  • -X simple.pmf 指定输出文件是 XML 文件 simple.pmf。
  • ./simple 指定要运行的工作负载应用程序。

也可以指定多个事件。CPC 在一个事件集中支持最多 4 个事件,还支持多个事件集。在以下示例中,收集两个事件集,2100、2101、2102、2103 和 2106、2109、2111、2119。-i 10u 表示以 10 微秒的取样间隔执行硬件取样。CPC 有许多用于 Cell BE 处理器 PMC 数据收集的选项。详细信息参见 下载的 CPC 帮助

清单 8. 使用 CPC 收集两个事件集
bash-3.00# cpc -e 2100,2101,2102,2103 -e 2106,2109,2111,2119 -i 10u -X 2sets.pmf ./simple

示例应用程序:Caesar 密码工具

在后面的讨论中,以 Caesar 密码工具作为示例程序。Caesar 密码是一种非常古老、简单的加密算法。它把明文消息中的字母向后偏移 n 个字符,从而产生密文文本。例如,如果偏移数是 2,那么 “H” 被替换为 “J”,“z” 被替换为 “b”,以此类推。

明文文本Helloworld!
密文文本Jgnnqyqtnf!

在这个示例程序中,只能加密字母和数字字符(a-z、A-Z 和 0-9)。逗号等其他字符保持不变。如果字符偏移后超出了 'z'、'Z' 或 '9',就重新回到 'a'、'A' 或 '0' 计算偏移。可以下载 caesar_src.zip。命令的语法如下所示:

清单 9. Caesar 的命令语法
Syntax: caesar [enc|dec] shift_number input_file output_file
enc|dec: 	  Encipher (enc) or decipher (dec)
shift_number: The number of characters to shift
input_file:   The input file. 
              The plain text for encipher, or the cipher text for decipher.
output_file:  The output file. 
              The cipher text for decipher, or the plan text for encipher.

下面是 caesar.c 中函数 void cipher(char * buffer, int length, int shift) 的源代码清单。

清单 10. Caesar 加密器/解密器
7	// char * buffer - The buffer holding the bytes read from file
8	// int length 	 - How many bytes are read into buffer
9	// int shift     - The shift number for ciphering
10	// 
11	// Return the ciphered bytes  
12	int cipher(char * buffer, int length, int shift) {
13		int bytes = 0;
14		int j = 0;
15	    for (; j < length; j ++) {
16
17	         if (buffer[j] >= 'a' && buffer[j] <= 'z') {
18	             buffer[j] = (buffer[j] - 'a' + 26 + shift) % 26 + 'a';
19	             bytes ++;
20	         }
21	         if (buffer[j] >= 'A' && buffer[j] <= 'Z') {
22	             buffer[j] = (buffer[j] - 'A' + 26 + shift) % 26 + 'A';
23	             bytes ++;
24	         }
25	         if (buffer[j] >= '0' && buffer[j] <= '9') {
26	             buffer[j] = (buffer[j] - '0' + 10 + shift) % 10 + '0';
27	             bytes ++;
28	        }
29	    }
30    
31	    return bytes;
32	}

根据字符是 “a-z”、“A-Z” 还是 “0-9”,分别执行不同的代码。请注意,偏移数可以是负数,这意味着反向偏移字符。

首先准备一个输入文件 hello.txt,其中包含 “Hello world!”。

清单 11. 准备明文输入文件
bash-3.00# echo ‘Hello world!’ > hello.txt
bash-3.00# cat hello.txt
Hello world!

然后,编译这个程序并运行它来加密 hello.txt 中的消息。最后,会在 hello.enc 中得到加密的消息 “Jgnnq yqtnf!”。

清单 12. 编译并运行
bash-3.00# xlc –o caesar1 caesar1.c
bash-3.00# ./caesar1
Syntax: caesar [enc|dec] shift_number input_file output_file
bash-3.00# ./caesar1 enc 2 hello.txt hello.enc
10 bytes are processed.
1283 ticks elapsed.
bash-3.00# cat hello.enc
Jgnnq yqtnf!

这说明这个工具工作正常。现在,使用 hpmcount 启动这个密码工具,加密一个很大的输入文件(例如数百 MB),然后查看 PMC 数据并判断哪些地方可以改进。

为了获得完整的 CPI 细分数据,需要收集事件组 0、1、5、28、29、30、31、40、43、44、48、49、79、81 和 91。如果只需要总 CPI,那么可以选择任何事件组,因为 PMC5 和 PMC6 总是收集指令完成和周期事件。

清单 13. 使用 hpmcount 收集多个事件组
bash-3.00# hpmcount -g 0,1,5,28,29,30,31,40,43,44,48,49,79,81,91 
-o caesar1_cpi -x ./caesar1 enc 4 huge.txt huge.enc
147040048 bytes are processed.
13627187 ticks elapsed.

此命令输出一个名称与 caesar1_cpi_0000.311434 相似的文件。把它改名为 caesar1_cpi.pmf


使用 Counter Analyzer 查看 PMC 数据

Counter Analyzer 是一个 VPA (Visual Performance Analyzer) 插件,它帮助用户更简便更好地分析和理解 PMC 数据。它读取 hpmcount/hpmstat 和 cpc 生成的 XML 文件。除了支持上述三种分析方法之外,Counter Analyzer 还支持 PMC 数据比较,并为多种处理器提供指标定义和 CPI 细分模型。

处理器指标CPI 细分模型
PowerPC 970YN
PowerPC 970 MPYN
POWER4YY
POWER4 IIYY
POWER5YY
POWER5 IIYY
POWER6YY

安装 VPA

可以从 http://www.alphaworks.ibm.com/tech/vpa 获得 Visual Performance Analyzer。安装 VPA 非常容易。假设已经下载了 vpa-rcp-${version}-win32.zip,打算把它安装在 C:\。安装只需三步:

  • 把 vpa-rcp-${version}-win32.zip 解压到 c:\
  • 进入 c:\vpa-rcp 目录
  • 运行 vpa.exe

如果看到下面的欢迎视图,就说明 VPA 已经成功地运行了。然后选择 Tools -> Counter Analyzer 切换到 Counter Analyzer 透视图。

图 1. VPA 欢迎视图
VPA 欢迎视图

在打开 XML 输出文件之前,需要把它的扩展名改为 .pmf (Performance Monitoring File),这帮助 Visual Performance Analyzer 认识到它是 Counter Analyzer 的输入。在 Counter Analyzer 打开此文件之后,原始 PMC 事件显示在 Counter Analyzer 编辑器中。有三个编辑器页面,Details、Metrics 和 CPI Breakdown,它们分别显示原始 PMC 事件、指标和 CPI 细分。在 VPA 中打开 caesar1_cpi.pmf

查看原始 PMC 事件

打开 caesar1_cpi.pmf 之后,会在 Details 页面中看到许多事件和事件计数值,在工具提示中还可以看到说明。事件名(比如 PM_CMPLU_STALL_DIV[u])在方括号中包含计数模式。[u] 表示在以用户模式执行应用程序期间发生的事件。其他有效值是 k(内核模式)、h(系统管理程序模式)、r(runlatch 模式)和 n(非中断模式)。

在下图中,选择的事件是在用户模式下收集的 PM_CMPLU_STALL_DIV。因为 hpmcount 不支持针对每个处理器收集数据,所以来自不同处理器的事件累计为一个值。来自单处理器系统的数据看起来与来自多处理器系统的数据相同。

注意,如果指定了多个事件集,那么事件计数值是规范化值。所以,事件计数值看起来像是在整个收集周期中收集的。

图 2. 查看原始 PMC 事件
查看原始 PMC 事件

查看指标

单击 Metrics 选项卡进入 Metrics 页面。左边的面板(名为 metrics)列出所有指标。根据系统处理器的不同,这些指标可能会被分组。在这里,POWER5 的指标分组为 “cpi_breakdown” 和 “performance”。如果没有定义指标组,就会列出所有指标。右边的面板(名为 variable)列出指标计算所需的变量。例如,指标 PMD_MIPS 定义为 1e-06 * PM_INST_CMPL / total_time。因此,它的值取决于总数据收集时间和 PM_INST_CMPL。Counter Analyzer 通过 .pmf 文件了解到执行数据收集的时间长度,并把这个值显示在 variable 面板上。如果指标的公式定义中有其他变量,就需要在 variable 面板中输入适当的值。

图 3. 查看指标
查看指标

查看 CPI 细分数据

最后一个页面是 CPI breakdown 页面,它以树结构显示 CPI 细分数据。树节点称为组件。

  • fig6 表示这个组件具有用事件定义的公式。例如,PMD_CPI_GCT_EMPTY = PM_GCT_NOSLOT_CYC / PM_INST_CMPL。
  • fig7 表示这个组件没有公式,它由其父节点和同胞节点决定。例如,PMD_CPI_GCT_EMPTY_OTHER = PMD_CPI_GCT_EMPTY - PMD_CPI_EMPTY_IC_MISS - PMD_CPI_GCT_EMPTY_BR_MPRED。
图 4. 查看 CPI 细分数据
查看 CPI 细分数据

通过在上下文菜单中选择 Export as HTML ...,还可以把 CPI 细分数据导出为 HTML。这有助于生成性能分析报告。

比较 PMC 数据

可以比较两次计数器数据收集过程产生的 PMC 数据。例如,假设您正在进行应用程序性能调优。可以在运行最初的应用程序时收集 PMC 数据,以这些数据作为基线数据。在代码中做一些改进之后,可以再次收集 PMC 数据并与基线数据做比较,这样就能够看到代码改进的效果,考虑进一步改进的可能性。

对于示例程序,可以在 caesar1_cpi.pmf 中找到基线 PMC 数据。现在,研究源代码文件,看看什么地方可以改进。

清单 14. Caesar 加密器/解密器
7	// char * buffer - The buffer holding the bytes read from file
8	// int length 	 - How many bytes are read into buffer
9	// int shift     - The shift number for ciphering
10	// 
11	// Return the ciphered bytes  
12	int cipher(char * buffer, int length, int shift) {
13		int bytes = 0;
14		int j = 0;
15	    for (; j < length; j ++) {
16
17	         if (buffer[j] >= 'a' && buffer[j] <= 'z') {
18	             buffer[j] = (buffer[j] - 'a' + 26 + shift) % 26 + 'a';    (1)
19	             bytes ++;
20	         }
21	         if (buffer[j] >= 'A' && buffer[j] <= 'Z') {                   (2)
22	             buffer[j] = (buffer[j] - 'A' + 26 + shift) % 26 + 'A';    (1)
23	             bytes ++;
24	         }
25	         if (buffer[j] >= '0' && buffer[j] <= '9') {                   (2)
26	             buffer[j] = (buffer[j] - '0' + 10 + shift) % 10 + '0';    (1)
27	             bytes ++;
28	        }
29	    }
30    
31	    return bytes;
32	}

仔细查看 PMC 数据和源代码文件之后,会发现可以改进的两个地方。

  • 在原始 PMC 事件中,出现了许多 PM_CMPLU_STALL_DIV 事件,这意味着流水线花费很多时间等待除法函数单元可用。阅读整个源代码文件之后,发现 (1) 使用了除法。因此,应该修改偏移字母的方式。
    清单 15. 新的加密器代码
    buffer[j] += shift;
    if (buffer[j] > 'z')
      buffer[j] -= 26;
    else (buffer[j] < ‘a’)
      buffer[j] += 26;
  • 对 a-z、A-Z 或 0-9 的检查应该是排他的。在后两个 if 之前添加 else,即可避免不必要的字符比较。

现在再次运行 hpmcount 收集 PMC 数据,产生 caesar2_cpi_0000.311458 这样的输出文件。把它改名为 caesar2_cpi.pmf。单击工具栏上的 fig8。在 Select To Compare 对话框中,选择 caesar1_cpi.pmf 并单击 Add 按钮。然后,选择 caesar2_cpi.pmf 并添加它。第一个文件作为比较的基线。还可以选择指标或 CPI 细分模型。在这里,选择预定义的 POWER5 指标和 CPI 细分模型。

图 5. 选择要比较的 .pmf 文件
选择要比较的 .pmf 文件

单击 OK 之后,Counter Analyzer 开始装载这两个文件并显示下面的比较结果。(A) 列和 (B) 列分别代表比较的两个文件。后两列是它们的差值 (B - A) 和百分比差值 ((B - A) * 100 / A)。红色值表示比较大的值,蓝色值表示比较小的值。

图 6. 比较原始 PMC 事件
比较原始 PMC 事件

通过原始 PMC 事件比较,可以发现:

  • 总周期数降低了 21.88%。所以总体时间性能得到了改进。
  • PM_CMPLU_STALL_DIV 和 PM_CMPLU_STALL_FXU 都变成了 0。这是因为消除了所有除法。
  • PM_CMPLU_STALL_DCACHE_MISS 和 PM_CMPLU_STALL_LSU 降低了大约 40-50%。由于 D-cache 失效和装载/存储指令而产生的流水线停滞减少了。数据局部性得到了改进。

还可以查看指标比较或 CPI 细分数据比较。图 7 显示 CPI 细分数据比较。可以看到 CPI 从 1.688 降低到 1.614,改进了 4.41%。PMD_CPI_STALL_FXU(与定点数除法相关的流水线停滞)变成了 0。

图 7. 比较 CPI 细分数据
比较 CPI 细分数据

结束语

Performance Monitor Counter 对于性能监视和度量非常重要。可以使用 hpmcount、hpmstat 和 CPC 等工具收集 PMC 数据。除了查看原始 PMC 事件之外,还可以通过指标和 CPI 细分模型实现高级度量。Counter Analyzer 支持原始 PMC 事件、指标和 CPI 细分数据这三种分析方法,有助于更好地分析 PMC 数据。它还支持比较两次数据收集过程产生的 PMC 数据,帮助您了解改进的效果,考虑进一步改进的可能性。


下载

描述名字大小
本文的源代码caesar_src.zip17KB

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=AIX and UNIX
ArticleID=382835
ArticleTitle=使用 Counter Analyzer 进行 Performance Monitor Counter 数据分析
publish-date=04162009