一、PAPI简介

PAPI是田纳西大学创新计算实验室开发的一组可以在多个处理器平台上对硬件性能计数器进行访问的标准接口,它的目标是方便用户在程序运行时监测和采集由硬件性能计数器记录的处理器事件信息。用户可以使用其提供的high/low api对程序某一段的使用时钟周期数,执行指令数,L1/L2 cache miss/access数,TLB miss数等等都统计出来,使用户能够直观的了解到程序的局部性如何。

不同的处理器会根据自身的体系结构特征定义出不同的处理器事件集合,在 PAPI 中这些事件被称为原生事件(Native Event)。同时,不同的处理器也会具有不同数量的硬件性能计数器,而在任意时刻一个计数器只能对一个指定的原生事件进行监测。考虑到事件监测和性能分析的需求,不同处理器的原生事件集合往往在功能上会有交集(例如那些和存储层次访问、Cache 一致性协议、周期和指令计数、功能单元和流水线状态等方面相关的事件),但是其对应的原生事件名称却未必相同。为了便于事件甄别,PAPI 将这些在不同处理器中存在功能共性的原生事件抽象成了 PAPI 接口专用的预制事件(Preset Event)并统一命名,所以具有一定的可移植性。

1、支持的性能计数器事件:

PAPI 支持一百多个事件。其标准事件分为 4 类:存储层次访问事件;周期与指令计数;功能部件与流水线状态事件; Cache 一致性事件,与 SMP 系统的 cache 一致性协议相关。

PAPI 包含一个工具程序papi_avail,,可以检测用户平台具有哪些事件,如:

此外还有papi_mem_info和papi_cost等命令,用来查看TLB,Cache信息和 查看papi开销等。

2、PAPI提供了两个向底层硬件的接口:

高层接口:比较简单,用于完成基本的计数测量(提供启动、停止和读取特定事件的能力)

PAPI 高层接口提供了一些访问硬件性能计数器所需的基本功能,例如配置计数器、启动计数、停止计数、读取计数器的数值等。高层接口只能利用 PAPI 预制事件,而不能够通过配置计数器去监测超出预制事件覆盖范围以外的处理器原生事件。不过,PAPI 高层接口能够直接返回在程序测评中最经常使用的一些性能指标,例如每个周期执行完成的指令数、每秒执行完成的浮点指令 / 浮点操作数、程序的运行时间等;另外,高层接口还能获取一些系统信息,例如处理器能够支持的硬件性能计数器的个数等。

底层接口:管理用户定义的事件组(称为 EventSet)中的事件,完全可编程,线程安全,为工具开发人员和高级用户提供方便。

高层接口获得的数据很多是未经过加工的原始数据,从中不能直接看出应用程序的存储层次与流水线利用情况的好坏。不同于高层接口只能使用 PAPI 预制事件,PAPI 底层接口能够直接使用原生事件对程序运行时的处理器硬件行为进行监测。用户可以将一个或多个原生事件组成一个事件组(Event Set),然后通过设置硬件性能计数器对事件组中所有的原生事件同时进行监测,进而根据监测结果分析程序的性能问题,例如通过同时采集每秒执行完成的浮点 指令数和 L1 Cache 失次数就有助于分析是否是因为 L1 Cache 的命中率不高导致了程序浮点性能的下降。需要注意的是,事件组中的原生事件个数不能够超过处理器所能支持的硬件性能计数器个数。

list . 常用的 PAPI 底层接口(C语言)

PAPI_library_init

初始化 PAPI 接口库

PAPI_create_eventset

创建事件组

PAPI_add_event / PAPI_add_events

向事件组中添加原生事件或者 PAPI 预制事件

PAPI_remove_event  PAPI_remove_events

从事件组中删除事件

PAPI_start

启动计数器对事件组的计数

PAPI_read

读取计数器数值

PAPI_stop

停止计数器计数并读取当前的计数器数值

PAPI_cleanup_eventset

清除事件组中的事件

PAPI_destroy_eventset

销毁事件组

PAPI_shutdown

终止使用 PAPI 并释放所有相关资源

//具体使用见后面实例2

PAPI是一组可以在多个处理器平台上对硬件性能计数器进行访问的本地接口,所以对于不同的处理器,安装方法也不同,部分AMD的CPU和INTEL的奔腾系列,至强系列都需要打补丁。补丁使用perfctr-2.6.x,对内核打补丁,重新编译的步骤比较繁琐,安装步骤在PAPI压缩包的Install.txt文件里有说明。

下面是对于一般的处理器(INTEL的i系列等)的安装步骤。

二、PAPI安装方法

在Ubuntu14.10上安装:

1、到PAPI官网下载PAPI 5.4.1压缩包。http://icl.cs.utk.edu/papi/software/index.html

2、将压缩包拷贝至/usr/local/下并解压。

3、测试PAPI

进入src目录并依次执行以下指令。

% ./configure% make% make test

如果出现PASSED则是通过测试,可以安装。

% make fulltest (相当于./run_tests.sh,简单测试,可忽略)% ./run_tests.sh -v(详细测试)

如果提示没有权限就使用chmod命令更改权限即可。

这个过程比较缓慢,下面是部分过程截图。

4、安装PAPI

a) To install PAPI libraries and header files from the build tree:

% make install

b) To install PAPI manual pages from the build tree:

% make install-man

c) To install PAPI test programs from the build tree:

% make install-tests

d) To install all of the above in one step from the build tree:

% make install-all

e) To create a binary kit, papi-<arch>.tgz:

% make dist

papi默认是安装在 /usr/local 下的,
papi可执行命令安装在bin下

papi的头文件放在include下

papi的库文件放在lib下,包括静态库libpapi.a,动态库libpapi.so.5.4.1.0

还有share、man目录下也安装了一些东西

5、由于papi的相关库安装在 /usr/local/lib 下,而我们编译程序链接动态或者静态库时,默认不会再 /usr/local/lib 下查找相关库的,所以为了在编译程序时可以自动链接/usr/local/lib下的papi相关库(例如: gcc ** -lpapi),我们做如下操作:

将 /usr/local/lib  加入文件 /etc/ld.so.conf 的最后一行,然后执行 ldconfig 命令,在编译时需要加入编译选项 -lpapi,使得程序可以动态链接到相应的函数实现。

6、编写一个C程序,调用 papi 相关函数,使用命令 gcc *.c -lpapi 命令编译,查看是否能够正常使用 PAPI .

三、使用PAPI

使用PAPI需要在源码进行插桩, 但是非常简单,一共5个阶段

初始化papi

/* Initialize the PAPI library */if (PAPI_library_init(PAPI_VER_CURRENT) != PAPI_VER_CURRENT)exit(1);/*Initialize the papi thread support:初始化线程支持,不使用线程这个部分可以省略。*/if (PAPI_thread_init(pthread_self) != PAPI_OK)exit(1);

创建事件集

事件就是指的是你要测试哪些性能数据,可以选择的性能指标通过papi_avail可以查看。例如L1,L2,L3 cache miss,clock cycle等等。

/* Create an EventSet */int EventSet = PAPI_NULL;int retval = PAPI_create_eventset (&EventSet);assert(retval==PAPI_OK);/* Add an event*/retval = PAPI_add_event(EventSet, PAPI_L3_TCM);assert(retval==PAPI_OK);

有些Event是支持一起测试的,如果想一次测试多个数据,再增加一个Event,至于哪些可以一起测试,需要自我探索一下。有一些可以一起测,有些是不可以的。

/*Add another event*/retval = PAPI_add_event(EventSet, PAPI_TOT_INS);assert(retval==PAPI_OK);开始计数/* Start counting events */if (PAPI_start(EventSet) != PAPI_OK)retval = PAPI_start (EventSet);assert(retval==PAPI_OK);

读取数据

long long values1[2];long long values2[2];PAPI_read(EventSet, values1);assert(retval==PAPI_OK);//Do something/* Stop counting events */retval = PAPI_stop (EventSet,values2);assert(retval==PAPI_OK);

得到结果

L3_TCM: values2[0] – values1[0]   L3 cache miss

TOT_INS:   values2[1] – values1[1]  total instruction counts

释放事件,清理工作

/* Clean up EventSet */if (PAPI_cleanup_eventset(EventSet) != PAPI_OK)exit(-1);/* Destroy the EventSet */if (PAPI_destroy_eventset(&EventSet) != PAPI_OK)exit(-1);/* Shutdown PAPI */PAPI_shutdown();

四、实例测试

实例一

http://icl.cs.utk.edu/projects/papi/wiki/PAPITopics:Getting_Started  官网的例子

我的电脑输出的结果为:

实例二

 1 #include "papi.h"
 2
 3 #include <stdlib.h>
 4
 5 #include <stdio.h>
 6
 7 int main() {
 8
 9 int EventSet;
10
11 int i, sum;
12
13 long_long values[2], values1[2], values2[2];
14
15 if (PAPI_library_init(PAPI_VER_CURRENT) != PAPI_VER_CURRENT)
16
17 exit(-1);
18
19 EventSet = PAPI_NULL;
20
21 if (PAPI_create_eventset(&EventSet) != PAPI_OK)
22
23 exit(-1);
24
25 if (PAPI_add_event(EventSet, PAPI_TOT_INS) != PAPI_OK)
26
27 exit(-1);
28
29 if (PAPI_add_event(EventSet, PAPI_L1_DCM) != PAPI_OK)
30
31 exit(-1);
32
33 if (PAPI_start(EventSet) != PAPI_OK)
34
35 exit(-1);
36
37 if (PAPI_read(EventSet, values1) != PAPI_OK)
38
39 exit(-1);
40
41 for (i=0;i<10000;i++)
42
43 sum+=i;
44
45 if (PAPI_stop(EventSet, values2) != PAPI_OK)
46
47 exit(-1);
48
49 if (PAPI_cleanup_eventset(EventSet) != PAPI_OK)
50
51 exit(-1);
52
53 if (PAPI_destroy_eventset(&EventSet) != PAPI_OK)
54
55 exit(-1);
56
57 PAPI_shutdown();
58
59 /* Get value */
60
61 values[0]=values2[0]-values1[0];
62
63 values[1]=values2[1]-values1[1];
64
65 printf("TOT_INS:%lld\nL1_DCM: %lld\n",values[0], values[1]);
66
67 return 0;
68
69 }

我的电脑输出的结果为:

TOT_INS:50919

L1_DCM:14

实例三

 1 #include "papi.h"
 2
 3 #include <stdlib.h>
 4
 5 #include <stdio.h>
 6
 7 int main() {
 8
 9     int EventSet;
10
11     int i, sum;
12
13 long_long values[1], values1[1], values2[1];
14
15     /* Initialize the PAPI library */
16
17     if (PAPI_library_init(PAPI_VER_CURRENT) != PAPI_VER_CURRENT)
18
19                 exit(-1);
20
21       // exit(-1);
22
23     /* Create an EventSet */
24
25     EventSet = PAPI_NULL;
26
27     if (PAPI_create_eventset(&EventSet) != PAPI_OK)
28
29         exit(-1);
30
31     /* Add an event about Total Instructions Executed (PAPI_TOT_INS) to EventSet */
32
33     if (PAPI_add_event(EventSet, PAPI_TOT_INS) != PAPI_OK)
34
35         exit(-1);
36
37     /* Start counting events */
38
39     if (PAPI_start(EventSet) != PAPI_OK)
40
41         exit(-1);
42
43     /* Read counters before workload running*/
44
45     if (PAPI_read(EventSet, values1) != PAPI_OK)
46
47         exit(-1);
48
49     /* Do some computation here */
50
51         for (i=0;i<10000;i++)
52
53                 sum+=i;
54
55     /* Stop counting events */
56
57     /* Stop counting events */
58
59     if (PAPI_stop(EventSet, values2) != PAPI_OK)
60
61         exit(-1);
62
63     /* Clean up EventSet */
64
65     if (PAPI_cleanup_eventset(EventSet) != PAPI_OK)
66
67         exit(-1);
68
69     /* Destroy the EventSet */
70
71     if (PAPI_destroy_eventset(&EventSet) != PAPI_OK)
72
73         exit(-1);
74
75     /* Shutdown PAPI */
76
77     PAPI_shutdown();
78
79     /* Get value */
80
81 // values[0] = values2[0] – values1[0];
82
83         values[0]=values2[0]-values1[0];
84
85         printf("%lld\n",values[0]);
86
87         return 0;
88
89 }

我的电脑输出的结果为50891

实例四

#include "papi.h"
#include<stdlib.h>#include<stdio.h>
int a[1000][1000];
int c[1000][1000];
int main()
{
int EventSet = PAPI_NULL;
int retval;
long_long values[1];
/* Initialize the PAPI library */
retval = PAPI_library_init(PAPI_VER_CURRENT);
if (retval != PAPI_VER_CURRENT) {
fprintf(stderr, "PAPI library init error!\n");
exit(1);
}
/* Create an EventSet */
if (PAPI_create_eventset(&EventSet) != PAPI_OK)
{
printf("create error\n");
exit(1);
}
/* Add Total Instructions Executed to our EventSet */
if (PAPI_add_event(EventSet, PAPI_L1_DCM) != PAPI_OK)
{
printf("add error\n");
exit(1);
}
if (PAPI_start(EventSet) != PAPI_OK)
{
printf("start error\n");
exit(1);
}
if (PAPI_read(EventSet, values) != PAPI_OK)
{
printf("read error\n");
exit(1);
}int m,n;
for(m=0;m<1000;m++)
{
for(n=0;n<1000;n++)
{
a[n][m]=a[n][m]+m+n;
}
}
/* Do some computation here */
if (PAPI_read(EventSet, values) != PAPI_OK)
{
printf("read error\n");
exit(1);
}
long_long b=values[0];
if(PAPI_reset(EventSet)!=PAPI_OK)
{
printf("reset error\n");
exit(1);
}
for(m=0;m<1000;m++)
{
for(n=0;n<1000;n++)
{
c[m][n]=c[m][n]+m+n;
}
}
/* Do some computation here */
if (PAPI_stop(EventSet, values) != PAPI_OK)
{
printf("stop error\n");
exit(1);
}if (PAPI_remove_event(EventSet, PAPI_L1_DCM) != PAPI_OK)
{
printf("stop error\n");
exit(1);
}if (PAPI_destroy_eventset(&EventSet) != PAPI_OK)
{
printf("stop error\n");
exit(1);
}PAPI_shutdown();
printf("%lld\n",b);
printf("%lld",values[0]);
getchar();
return 0;
}

我的电脑输出的结果为:

1364841

34786

最后推荐 http://www.ibm.com/developerworks/cn/java/j-lo-papi/  这篇文章写得很好。

转载于:https://www.cnblogs.com/dmyu/p/4648413.html

PAPI性能测试工具的安装、使用及实例相关推荐

  1. php性能测试下载,PHP性能测试工具xhprof安装与使用方法详解

    本文实例分析了PHP性能测试工具xhprof安装与使用方法.分享给大家供大家参考,具体如下: xhprof概述: XHProf是一个分层PHP性能分析工具.它报告函数级别的请求次数和各种指标,包括阻塞 ...

  2. HTTP性能测试工具wrk安装及使用

    wrk 是一个很简单的 http 性能测试工具,没有Load Runner那么复杂,他和 apache benchmark(ab)同属于HTTP性能测试工具,但是比 ab 功能更加强大,并且可以支持l ...

  3. 性能测试工具 wrk 安装与初步使用

    开源的性能测试工具 wrk,简单易用,没有Load Runner那么复杂,他和 apache benchmark(ab)同属于性能测试工具,但是比 ab 功能更加强大,并且可以支持lua脚本来创建复杂 ...

  4. C++性能测试工具gprof安装和应用

    一.gprof的安装和说明 在前面谈过了gperftools的安装,今天来看一下gprof的安装.虽然说gperftools安装比较复杂,但是gprof就好说了,因为只要你的机器上装有GCC,那么自然 ...

  5. Fabric性能测试工具Caliper安装使用

    文章目录 Pre-requisites 安装 make,g++ 编译工具 安装node.js 安装 node-gyp 安装 Docker 安装 Docker-compose Clone caliper ...

  6. 性能测试工具wrk安装使用详解

    建议练习时可以使用FastApi或Flask等Web服务端框架在本地搭建一个HTTP服务. wrk简介 wrk是一个用于HTTP协议的基准测试工具.基准测试是一种性能测试方法,它通过设计科学的测试方法 ...

  7. influxDB性能测试工具 influx-stress安装使用

    influxdata提供的测试工具,influx-stress用于写入压力测试, 安装使用步骤: 1.GO运行环境 详见另一篇博客: https://blog.csdn.net/rclijia/art ...

  8. Linux CENTOS7 Linux网络性能测试工具-iperf 安装过程以及示例!

    要在网址的这个位置下载才可以! https://iperf.fr/iperf-download.php#archlinux 我的:https://download.csdn.net/download/ ...

  9. linux的netperf测试,性能测试工具netperf安装使用

    一.安装1,下载liunx下载地址:ftp://ftp.netperf.org/netperf/ windows版下载地址:ftp://ftp.netperf.org/netperf/misc/ 这里 ...

最新文章

  1. 编写一个最简单的.php,学习猿地- 说明 如果我们要编写一个简单的PHP脚本,需要学习哪些...
  2. 【新功能,新插件】-全新来袭,CSDN浏览器助手这一款无广告干净界面插件你值得拥有!
  3. 使用seek()函数与read()快速实现读取文件中的一段数据
  4. microsoft已暂时停用你的用户_Windows10 20年10月重大更新来了,但它已存在问题
  5. POJ - 2778 DNA Sequence(AC自动机+矩阵快速幂)
  6. 《码出高效:Java开发手册》背后的故事
  7. GDIPlus灰度化图像
  8. 最新37网游JS逆向分析
  9. 写给新入IT的新人们(转载)
  10. android scroll 中 scroll Bar 修改
  11. 唐宇迪pytorch课程全部代码数据集github
  12. 【Proteus仿真】TLC5615输出1024点正弦波(振幅可调)
  13. uni-app学习笔记(1):模板语法
  14. 多窗口电脑文件管理器
  15. Docker 生产环境之安全性 - 适用于 Docker 的 AppArmor 安全配置文件
  16. java转go之初体验(一)
  17. TabLayout的属性介绍
  18. 工具开发|键盘记录工具原理及代码实现
  19. C# Socket客户端采用双线程断网重连断线重连)
  20. 几种自动目标跟踪算法的比较研究

热门文章

  1. sql server 约束 查找
  2. 常用的 iptables配置脚本
  3. 利用HTML+JS+CSS实现简单的网页计算器,附html所有源代码,可直接黏贴运行
  4. svg html5 ajax,jQuery附加到AJAX加载的SVG问题
  5. 轻量级linux iso,antiX 17.2 发布,基于Debian的轻量级Linux发行版
  6. linux网卡驱动对XDP支持情况
  7. Ubuntu下编译SHTOOLS
  8. git——IntelliJ中配置使用git,码云管理项目
  9. golang控制台颜色输出(for windows)
  10. 20 个很棒的 jQuery Mobile 教程