Last active
February 12, 2024 14:42
-
-
Save marcorentap/c80d16adf496befb315435bfb75d68b4 to your computer and use it in GitHub Desktop.
calculate CPI with perf_event_open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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