Почему мой perf_event_open () можно использовать только 509 раз? - PullRequest
0 голосов
/ 16 апреля 2020

Я использую perf_event_open (), чтобы измерить частоту пропадания кэша. Я делаю это следующим образом:

double cachemiss(int PID_NUM){
    int i;double rate;
    struct perf_event_attr pe;
    int fd1,fd2;
    uint64_t miss,reference;
    uint64_t id1, id2;
    struct read_format buf;
    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_CACHE_MISSES;
    pe.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
    fd1 = perf_event_open(&pe, PID_NUM, -1, -1, 0);
    ioctl(fd1, PERF_EVENT_IOC_ID, &id1);
    if (fd1 == -1) {
        fprintf(stderr, "Error opening leader %llx\n", pe.config);
        exit(EXIT_FAILURE);
    }
    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_CACHE_REFERENCES;
    pe.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
    fd2 = perf_event_open(&pe, PID_NUM, -1, fd1, 0);
    ioctl(fd2, PERF_EVENT_IOC_ID, &id2);
    if (fd2 == -1) {
        fprintf(stderr, "Error opening leader %llx\n", pe.config);
        exit(EXIT_FAILURE);
    }
    ioctl(fd1, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP);
    ioctl(fd1, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP);
    usleep(10000);
    ioctl(fd1, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP);
    read(fd1, &buf, sizeof(buf));
    for (i = 0; i < buf.nr; i++) {
        if (buf.values[i].id == id1) miss = buf.values[i].value;
        else if (buf.values[i].id == id2) reference =buf.values[i].value;
    }
    rate=(double)miss/((((double)reference+(double)miss))+1);
    return rate;
}
int main()
{
    for(int i=0;1;i++) cout<<i<<"\t"<<cachemiss(11);
}

Тогда в начале 509 раз нет ничего плохого. Но когда дело доходит до 510-го раза, fd2 = -1. Я пробую это снова и снова, но проблема всегда одна и та же: 510 раз не работает.

1 Ответ

2 голосов
/ 16 апреля 2020

У вас есть утечка ресурсов на каждой итерации и некоторые ограничения активированы. Может быть подсказка о ресурсе в значении errno специальной переменной, когда fd равно -1, проверьте страницу справки http://man7.org/linux/man-pages/man2/perf_event_open.2.html#ERRORS

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ ... -1, если произошла ошибка (в этом случае значение errno установлено соответствующим образом)

Пределы ресурса можно проверить с помощью команды ulimit -a в оболочке (bash).

Пример использования perf_event_open () на странице man имеет системный вызов close на fd, возвращенном syscall:

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

   close(fd);

А у вашего cachemiss() нет системного вызова close для fd1 и fd2, поэтому файловые дескрипторы просачиваются со скоростью два за итерацию.

...