1

I am trying to read the hardware performance counter using PAPI and I have written the following code:

#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);
}

I compile it using the following command:

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

and I run it like this:

./pid_ex 7865

where 7865 is the process id of the running process.

The problem is it is showing zero values instead of showing the counter values.

Could anybody let me know why it is behaving like this? Why is it not getting values?

David
  • 481
  • 5
  • 14

1 Answers1

4

Couple of things, I compiled and tried to run your code. I compiled with -Wall and you should probably change:

unsigned int l2miss = 0x0;
unsigned int data_all_from_l2 = 0x0;

into

int l2miss = PAPI_NULL;
int data_all_from_l2 = PAPI_NULL;

so you get rid of a couple of warnings.

Then I tried to just run your code and I was getting this error:

Error -7 papi-test.c:line ...

which is PAPI error code from when a given event is not available for your machine, issued by the following function calls:

if ( (retval = PAPI_event_name_to_code("PM_DATA_FROM_L2MISS",&l2miss)) != PAPI_OK)

and

if ( (retval = PAPI_event_name_to_code("PM_DATA_ALL_FROM_L2",&data_all_from_l2)) != PAPI_OK)

Given this, I checked which events were available for my machine and got the following:

$ papi_avail

and your events were not available for me. So to test your code I changed the events to be recorded and set them to:

PAPI_L1_DCM

PAPI_L2_DCM

which represent respectively the L1 and L2 data cache misses. And then I run your program against four programs: firefox, java, a program that just sleeps and cinnamon (Linux Mint).

It seems that the events are recorded as you can see: Firefox:

./papi-test 3922

There are 2 events in the event set

The L2 Miss are 0

The data_all_from_l2 are 0

The L2 Miss are 130534

The data_all_from_l2 are 104151

The L2 Miss are 266181

The data_all_from_l2 are 212618
...

For the programs that just sleeps I get:

./papi-test 7870

There are 2 events in the event set

The L2 Miss are 0

The data_all_from_l2 are 0

The L2 Miss are 0

The data_all_from_l2 are 0

The L2 Miss are 0

The data_all_from_l2 are 0
...

Please disregard the string printed before the number as I kept your string when you print the events although the events registered are different and I just mentioned above which ones I used to be able to run it on my computer. So it seems that I'm not just getting zeros all the time but depend on the program that's being under observation.
The version of PAPI used is 5.4.3.
Also, although I don't have suggestions at the moment, have care of the condition in the while loop you check, since might happen that while you sleep inside the loop the program associated with PID could finish and its PID reused and assigned to another process and you will still satisfy the condition but in this case you might be looking at the wrong program you originally thought.
There's also been some discussion
https://lists.eecs.utk.edu/pipermail/ptools-perfapi/2016-October/004060.html?cm_mc_uid=57211302537614804702521&cm_mc_sid_50200000=1482029904 using some events like yours.
Plus, the events you use are defined for power8 machines (https://lkml.org/lkml/2015/5/27/858), so you're probably using a power8 machine.

fedepad
  • 4,509
  • 1
  • 13
  • 27