Question

I run the program on Ubuntu 12.04, The counters' value is awalys 0.It seems that my counters didn't work for me.

When I run the program,the ouput is :


Get the number of CPU:8
Create counters for each CPU finished!
run_perf_stat()!
Cache miss in cpu1:0
Cache miss in cpu2:0
Cache miss in cpu3:0
Cache miss in cpu4:0
Cache miss in cpu5:0
Cache miss in cpu6:0
Cache miss in cpu7:0
Cache miss in cpu8:0

I can't make sense of the values'meaning.What I want to get is every cpu's cache reference and it's cache miss.But obviously the result seems not correct!

I have read the doc about the perf method at: http://www.man7.org/linux/man-pages/man2/perf_event_open.2.html

#include <string.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <asm-generic/unistd.h>
#include <dirent.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <asm/unistd.h>
#include "perf_event.h"

#define MAX_COUNTERS        256


static int fd[MAX_COUNTERS];
static unsigned int counter;
static unsigned int nr_cpus =  0; // amount of cpus

//open counter 
long sys_perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
                int cpu, int group_fd, unsigned long flags)
{
    int ret;

    ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
                   group_fd, flags);
    return ret;
}



void run_perf_stat()
{

    long long eventContents=0;
    for (counter = 0; counter < nr_cpus; counter++){
        if(fd[counter]!=-1){
            read(fd[counter],&eventContents,sizeof(long long));
            printf("Cache miss in cpu%d:%lld\n",counter+1,eventContents);
        }
        else{
            fprintf(stderr, "Fail to read counter %d\n", counter);
        }
    }
        
        
}




int main(int argc, const char **argv){

    DIR *dir;  //access to dir
    struct dirent *drp;
    int run_count, p, pid;
    struct timespec tim, tim2;
    tim.tv_sec = 1; tim.tv_nsec = 0;
    

    
    nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);// the number of CPU

    printf("Get the number of CPU:%d\n",nr_cpus);


    //create counters for each CPU (system-wide)
    struct perf_event_attr attr; //cache miss
    memset(&attr, 0, sizeof(struct perf_event_attr));
    attr.type = PERF_TYPE_HARDWARE;
    attr.config = PERF_COUNT_HW_CACHE_MISSES;
    attr.size = sizeof(struct perf_event_attr);
    attr.disabled = 0;
        attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |  
                    PERF_FORMAT_TOTAL_TIME_RUNNING;  



    unsigned int cpu = 0;
    for(cpu = 0; cpu < nr_cpus; cpu++)
    fd[cpu] = sys_perf_event_open(&attr, -1, cpu, -1, 0);

    printf("Create counters for each CPU finished!\n");

    //get perf report
    while (1) {
        nanosleep(&tim , &tim2);
        printf("run_perf_stat()!\n");
        run_perf_stat();
    }



    return 1;
}

And I also run the example given at http://www.man7.org/linux/man-pages/man2/perf_event_open.2.html

But,unfortunaely,The result is always 0,too.Here comes the example in the man-page.

The following is a short example that measures the total instruction count of a call to printf(3).

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <asm/unistd.h>

long
perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
               int cpu, int group_fd, unsigned long flags)
{
   int ret;

   ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
                  group_fd, flags);
   return ret;
}

int
main(int argc, char **argv)
{
   struct perf_event_attr pe;
   long long count;
   int fd;

   memset(&pe, 0, sizeof(struct perf_event_attr));
   pe.type = PERF_TYPE_HARDWARE;
   pe.size = sizeof(struct perf_event_attr);
   pe.config = PERF_COUNT_HW_INSTRUCTIONS;
   pe.disabled = 1;
   pe.exclude_kernel = 1;
   pe.exclude_hv = 1;

   fd = perf_event_open(&pe, 0, -1, -1, 0);
   if (fd == -1) {
      fprintf(stderr, "Error opening leader %llx\n", pe.config);
      exit(EXIT_FAILURE);
   }

   ioctl(fd, PERF_EVENT_IOC_RESET, 0);
   ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);

   printf("Measuring instruction count for this printf\n");

   ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
   read(fd, &count, sizeof(long long));

   printf("Used %lld instructions\n", count);

   close(fd);
}
Was it helpful?

Solution

I just tried your code and removing following lines (line no 75,76) makes the code work for me.

attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
                   PERF_FORMAT_TOTAL_TIME_RUNNING;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top