Skip to content

Instantly share code, notes, and snippets.

@marcorentap
Last active February 12, 2024 14:42
Show Gist options
  • Save marcorentap/c80d16adf496befb315435bfb75d68b4 to your computer and use it in GitHub Desktop.
Save marcorentap/c80d16adf496befb315435bfb75d68b4 to your computer and use it in GitHub Desktop.
calculate CPI with perf_event_open
#include <asm/unistd.h>
#include <linux/perf_event.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
static 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;
}
enum {
INST,
CLOCK
};
int do_work(int max) {
int i;
int sum = 0;
for (i = 0; i < max; i++) {
sum += i;
}
return sum;
}
int main(int argc, char *argv[]) {
struct perf_event_attr attrs[2] = {0};
int64_t inst_counts[2];
int64_t clock_counts[2];
int fds[2];
int ret;
attrs[INST].type = PERF_TYPE_HARDWARE;
attrs[INST].config = PERF_COUNT_HW_INSTRUCTIONS;
attrs[CLOCK].type = PERF_TYPE_HARDWARE;
attrs[CLOCK].config = PERF_COUNT_HW_CPU_CYCLES;
fds[INST] = perf_event_open(&attrs[INST], getpid(), -1, -1, 0);
if (fds[INST] < 0) {
return EXIT_FAILURE;
}
fds[CLOCK] = perf_event_open(&attrs[CLOCK], getpid(), -1, -1, 0);
if (fds[CLOCK] < 0) {
return EXIT_FAILURE;
}
// Initial values
ret = read(fds[INST], &inst_counts[0], sizeof(inst_counts[0]));
if (ret < 0) {
perror("cannot read initial instruction count");
return EXIT_FAILURE;
}
ret = read(fds[CLOCK], &clock_counts[0], sizeof(clock_counts[0]));
if (ret < 0) {
perror("cannot read initial instruction count");
return EXIT_FAILURE;
}
do_work(atoi(argv[1]));
// Final values
ret = read(fds[INST], &inst_counts[1], sizeof(inst_counts[1]));
if (ret < 0) {
perror("cannot read initial instruction count");
return EXIT_FAILURE;
}
ret = read(fds[CLOCK], &clock_counts[1], sizeof(clock_counts[1]));
if (ret < 0) {
perror("cannot read initial instruction count");
return EXIT_FAILURE;
}
close(fds[INST]);
close(fds[CLOCK]);
int64_t clock_diff, inst_diff;
clock_diff = clock_counts[1] - clock_counts[0];
inst_diff = inst_counts[1] - inst_counts[0];
printf("Clock Count: %ld\n", clock_diff);
printf("Instruction Count: %ld\n", inst_diff);
printf("CPI: %lf\n", (double) clock_diff / inst_diff);
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment