est-ce que quelqu'un sait comment configurer perf_event_attr
struct qui peut déclencher PMU pour surveiller plusieurs (type) événement via perf_event_open()
?perf_event_open - comment surveiller plusieurs événements
Comme perf record -e cycles,faults ls
, il a deux types d'événements différents (PERF_TYPE_HARDWARE et PERF_TYPE_SOFTWARE), mais dans l'exemple sur perf_event_open's manpage, perf_event_attr.type
ne peut seule valeur assignée.
Toute suggestion sera appréciée, merci!
20170208 Mise à jour Merci pour @gudok me pointant une direction, mais le résultat semble un peu anormal. programme de démonstration comme ci-dessous (pour le cycle de CPU de toute mesure système et miss cache):
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
#include <linux/hw_breakpoint.h>
#include <asm/unistd.h>
#include <errno.h>
#include <stdint.h>
#include <inttypes.h>
#include <time.h>
struct read_format {
uint64_t nr;
struct {
uint64_t value;
uint64_t id;
} values[];
};
int main(int argc, char* argv[]) {
struct perf_event_attr pea;
int fd1, fd2;
uint64_t id1, id2;
uint64_t val1, val2;
char buf[4096];
struct read_format* rf = (struct read_format*) buf;
int i,j;
struct timespec time, time2;
time.tv_sec = 1;
time.tv_nsec = 0;
memset(&pea, 0, sizeof(struct perf_event_attr));
pea.type = PERF_TYPE_HARDWARE;
pea.size = sizeof(struct perf_event_attr);
pea.config = PERF_COUNT_HW_CPU_CYCLES;
pea.disabled = 1;
pea.exclude_kernel = 1;
pea.exclude_hv = 1;
pea.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
fd1 = syscall(__NR_perf_event_open, &pea, 0, -1, -1, 0);
ioctl(fd1, PERF_EVENT_IOC_ID, &id1);
memset(&pea, 0, sizeof(struct perf_event_attr));
pea.type = PERF_TYPE_HARDWARE;
pea.size = sizeof(struct perf_event_attr);
pea.config = PERF_COUNT_HW_CACHE_MISSES;
pea.disabled = 1;
pea.exclude_kernel = 1;
pea.exclude_hv = 1;
pea.precise_ip = 2; // want to using PEBS
pea.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
fd2 = syscall(__NR_perf_event_open, &pea, 0, -1, fd1 /*!!!*/, 0);
ioctl(fd2, PERF_EVENT_IOC_ID, &id2);
ioctl(fd1, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP);
ioctl(fd1, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP);
while (1) {
nanosleep(&time, &time2);
//ioctl(fd1, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP);
read(fd1, buf, sizeof(buf));
for (i = 0; i < rf->nr; i++) {
if (rf->values[i].id == id1) {
val1 = rf->values[i].value;
} else if (rf->values[i].id == id2) {
val2 = rf->values[i].value;
}
}
printf("cpu cycles: %"PRIu64"\n", val1);
printf("cache misses: %"PRIu64"\n", val2);
}
return 0;
}
Et la sortie est:
cpu cycles: 120 // Just have about 120 CPU cycles in a second
cache misses: 0 // and doesn't have any cache miss?
cpu cycles: 233
cache misses: 0
cpu cycles: 352
cache misses: 0
cpu cycles: 455
cache misses: 0
cpu cycles: 562
cache misses: 0
cpu cycles: 673
cache misses: 0
cpu cycles: 794
cache misses: 0
cpu cycles: 907
cache misses: 0
cpu cycles: 1011
cache misses: 0
cpu cycles: 1129
cache misses: 3
cpu cycles: 1269
cache misses: 4
cpu cycles: 1423
Merci pour votre réponse utile :) Il fonctionne, mais le résultat semble un peu inhabituel .. Je veux compter les cycles CPU par seconde, et il montre environ 120 cycles. La méthode que j'ai utilisée est-elle incorrecte? (Programme de démonstration mis à jour dans ma question) Merci encore. –
@KevinChi, les cycles de cpu ne seront pas comptés pendant les appels de sommeil. Le temps CPU pendant le sommeil n'appartient pas au processus en cours.À l'intérieur de 'do_something', vous devez créer une boucle factice de 1-2 bln. itérations et compte 1) cycles cpu 2) temps nécessaire à l'exécution de cette boucle ('clock_gettime (CLOCK_THREAD_CPUTIME_ID)'). En divisant ces deux valeurs vous obtiendrez des cycles de cpu par seconde. Vous pouvez également configurer une minuterie d'une seconde et exécuter une boucle infinie jusqu'à ce qu'elle se déclenche. – gudok
Oh, maintenant. J'ai utilisé la mauvaise méthode! –