我正在尝试使用PAPI读取硬件性能计数器,并编写了以下代码:
#include <stdio.h>
#include <stdlib.h>
#include "papi.h" /* This needs to be included every time you use PAPI */
#include <unistd.h>
#define NUM_EVENTS 2
#define ERROR_RETURN(retval) { fprintf(stderr, "Error %d %s:line %d: \n", retval,__FILE__,__LINE__); exit(retval); }
int main(int argc, char *argv[])
{
if(argc<=1) {
printf("Pid is not provided, I will die now :( ...");
exit(1);
} //otherwise continue on our merry way....
int EventSet = PAPI_NULL;
int tmp, i;
/*must be initialized to PAPI_NULL before calling PAPI_create_event*/
long long values[NUM_EVENTS];
/*This is where we store the values we read from the eventset */
/* We use number to keep track of the number of events in the EventSet */
int retval, number;
char errstring[PAPI_MAX_STR_LEN];
pid_t pid = atoi(argv[1]);
unsigned int l2miss = 0x0;
unsigned int data_all_from_l2 = 0x0;
/***************************************************************************
* This part initializes the library and compares the version number of the*
* header file, to the version of the library, if these don't match then it *
* is likely that PAPI won't work correctly.If there is an error, retval *
* keeps track of the version number. *
***************************************************************************/
if((retval = PAPI_library_init(PAPI_VER_CURRENT)) != PAPI_VER_CURRENT )
ERROR_RETURN(retval);
/* Creating the eventset */
if ( (retval = PAPI_create_eventset(&EventSet)) != PAPI_OK)
ERROR_RETURN(retval);
/* Add Native event to the EventSet */
// if ( (retval = PAPI_event_name_to_code("PM_DATA_FROM_L2MISS",&l2miss)) != PAPI_OK)
if ( (retval = PAPI_event_name_to_code("PM_L3_CO_MEM",&l2miss)) != PAPI_OK)
ERROR_RETURN(retval);
if ( (retval = PAPI_add_event(EventSet, l2miss)) != PAPI_OK)
ERROR_RETURN(retval);
/* Add Native event to the EventSet */
if ( (retval = PAPI_event_name_to_code("PM_DATA_ALL_FROM_L2",&data_all_from_l2)) != PAPI_OK)
ERROR_RETURN(retval);
if ( (retval = PAPI_add_event(EventSet, data_all_from_l2)) != PAPI_OK)
ERROR_RETURN(retval);
/* get the number of events in the event set */
number = 0;
if ( (retval = PAPI_list_events(EventSet, NULL, &number)) != PAPI_OK)
ERROR_RETURN(retval);
printf("There are %d events in the event set\n", number);
retval = PAPI_attach( EventSet, ( unsigned long ) pid );
if ( retval != PAPI_OK )
ERROR_RETURN(retval);
/* Start counting */
if ( (retval = PAPI_start(EventSet)) != PAPI_OK)
ERROR_RETURN(retval);
while(kill(pid,0)==0)
{
if ( (retval=PAPI_read(EventSet, values)) != PAPI_OK)
ERROR_RETURN(retval);
printf("The L2 Miss are %lld \n",values[0]);
printf("The data_all_from_l2 are %lld \n",values[1]);
sleep(1);
}//while
/* Stop counting and store the values into the array */
if ( (retval = PAPI_stop(EventSet, values)) != PAPI_OK)
ERROR_RETURN(retval);
printf("Total L2 Miss are %lld \n",values[0]);
printf("Total data_all_from_l2 are %lld \n",values[1]);
/* free the resources used by PAPI */
PAPI_shutdown();
exit(0);
}
我使用以下命令编译它:
gcc -I/apps/PAPI/5.5.0/GCC/5.4.0/CUDA/8.0/include -O0 pid_ex.c -L/apps/PAPI/5.5.0/GCC/5.4.0/CUDA/8.0/lib -lpapi -o pid_ex
我这样运行它:
./pid_ex 7865
其中7865是正在运行的进程的进程id。
问题是它显示的是零值而不是计数器值。
有人能告诉我为什么它会这样吗?为什么它得不到价值?
最佳答案
有几件事,我编译并试着运行你的代码。
我用-Wall编译,你可能应该改一下:
unsigned int l2miss = 0x0;
unsigned int data_all_from_l2 = 0x0;
进入之内
int l2miss = PAPI_NULL;
int data_all_from_l2 = PAPI_NULL;
所以你摆脱了一些警告。
然后我试着运行你的代码,我得到了这个错误:
错误-7 papi test.c:行。。。
当给定的事件不可用于您的计算机时,由以下函数调用发出的PAPI错误代码:
if ( (retval = PAPI_event_name_to_code("PM_DATA_FROM_L2MISS",&l2miss)) != PAPI_OK)
和
if ( (retval = PAPI_event_name_to_code("PM_DATA_ALL_FROM_L2",&data_all_from_l2)) != PAPI_OK)
鉴于此,我检查了哪些事件可用于我的机器,并得到以下结果:
$papi可用
你的活动对我来说是不可用的。所以为了测试你的代码,我把要记录的事件改为:
PAPI_L1_DCM公司
乳头状扩张型心肌病
分别表示一级和二级数据缓存未命中。
然后我用四个程序运行你的程序:firefox,java,一个只会睡觉的程序和肉桂(Linux Mint)。
似乎这些事件都被记录下来了,如你所见:
火狐:
/papi测试3922
事件集中有两个事件
二级未命中为0
所有来自l2的数据都是0
二级失误是130534
所有来自l2的数据是104151
二级失误是266181
所有来自l2的数据是212618
...
对于那些只会睡觉的程序,我得到:
/papi测试7870
事件集中有两个事件
二级未命中为0
所有来自l2的数据都是0
二级未命中为0
所有来自l2的数据都是0
二级未命中为0
所有来自l2的数据都是0
...
请忽略数字前面的字符串,因为我在打印事件时保留了字符串,尽管注册的事件不同,我刚才提到了我以前可以在计算机上运行的事件。
所以看来我并不是一直都在得到零,而是取决于正在观察的程序。
使用的PAPI版本为5.4.3。
另外,虽然我目前没有建议,但是请注意您检查的while循环中的条件,因为可能会发生这样的情况:当您在循环中睡眠时,与PID相关的程序可以完成,其PID可以重用并分配给另一个进程,您仍将满足该条件,但在这种情况下,您可能会看到你原来以为的程序不对。
也有一些讨论
https://lists.eecs.utk.edu/pipermail/ptools-perfapi/2016-October/004060.html?cm_mc_uid=57211302537614804702521&cm_mc_sid_50200000=1482029904
利用一些像你这样的活动。
另外,您使用的事件是为power8机器定义的(https://lkml.org/lkml/2015/5/27/858),因此您可能正在使用power8机器。
关于c - 性能计数器值使用papi Attach返回零,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40240325/