PAPI 是非常好的性能测试工具,使用十分方便。对于分析程序的性能提供很好的依据。
下面对使用PAPI 做一个小结。
在PAPI主站上下载最新的tar包,解压缩,然后进入到papi文件夹下的src文件夹下:
./configure–prefix=${PAPI_HOME}
make
make test
make install
设置环境变量: PATH= ${PAPI_HOME}/bin:${PATH}
LD_LIBRARY_PATH=${PAPI_HOME}/lib:${LD_LIBRARY_PATH}
编译选项: -I ${PAPI_HOME}/include -lpapi -L ${PAPI_HOME}/lib
Userful binaries:
papi_avail: 查看当前机器上可以选择测试的性能选项。
papi_meminfo: 查看TLB,Cache信息
papi_cost: 查看papi开销
使用PAPI需要在源码进行插桩, 但是非常简单,一共5个阶段
/* 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();
simple_papi.c
#include "papi.h"
#include <stdlib.h>
#include <stdio.h>
int main() {
int EventSet;
int i, sum;
long_long values[2], values1[2], values2[2];
if (PAPI_library_init(PAPI_VER_CURRENT) != PAPI_VER_CURRENT)
exit(-1);
EventSet = PAPI_NULL;
if (PAPI_create_eventset(&EventSet) != PAPI_OK)
exit(-1);
if (PAPI_add_event(EventSet, PAPI_TOT_INS) != PAPI_OK)
exit(-1);
if (PAPI_add_event(EventSet, PAPI_L1_DCM) != PAPI_OK)
exit(-1);
if (PAPI_start(EventSet) != PAPI_OK)
exit(-1);
if (PAPI_read(EventSet, values1) != PAPI_OK)
exit(-1);
for (i=0;i<10000;i++)
sum+=i;
if (PAPI_stop(EventSet, values2) != PAPI_OK)
exit(-1);
if (PAPI_cleanup_eventset(EventSet) != PAPI_OK)
exit(-1);
if (PAPI_destroy_eventset(&EventSet) != PAPI_OK)
exit(-1);
PAPI_shutdown();
/* Get value */
values[0]=values2[0]-values1[0];
values[1]=values2[1]-values1[1];
printf("TOT_INS:%lld\nL1_DCM: %lld\n",values[0], values[1]);
return 0;
}
编译:
gcc -o simple_papi simple_papi.c -I ${PAPI_HOME}/include -L ${PAPI_HOME}/lib -lpapi -Wall -O3
运行结果:
TOT_INS:820
L1_DCM: 11