Как настроить и отобразить счетчики производительности Intel In-Process

Вкратце, я пытаюсь добиться следующих результатов в тестовом процессе пользовательской среды (псевдокод, предполагая x86_64 и систему UNIX):

results[] = ...
for (iteration = 0; iteration < num_iterations; iteration++) {
    pctr_start = sample_pctr();
    the_benchmark();
    pctr_stop = sample_pctr();
    results[iteration] = pctr_stop - pctr_start;
}

FWIW, счетчик производительности, который я собираюсь использовать, - это CPU_CLK_UNHALTED.THREAD_ALL, чтобы прочитать количество циклов ядра, не зависящих от изменений частоты часов (в более раннем вопросе. планировал использовать регистр TSC для этого, но, увы, это не то, что этот регистр вообще измеряет).

Мое первоначальное намерение состояло в том, чтобы использовать встроенный ассемблер для первой настройки счетчика с помощью WRMSR, затем для чтения счетчика с помощью RDPMC внутри sample_pctr().

Я наткнулся на первое препятствие, так как написание MSR требует привилегий ядра. Похоже, вы можете на самом деле прочитать счетчики из пользовательского пространства (если он настроен правильно), но ядро ​​должен выполнить действие настройки счетчика (с помощью MSR).

Кто-нибудь знает легкий способ попросить ядро ​​настроить счетчики производительности из пользовательского пространства, чтобы затем я мог использовать RDPMC из моей контрольной системы?

Материал, о котором я подумал:

  • Инструменты Perf для Linux. Кажется, что он предназначен для выборки на протяжении всего жизненного цикла процесса, а не внутри процесса как конкретные точки (до и после каждой итерации).
  • Использовать прямые syscalls непосредственно (т.е. perf_event_open). Похоже, что значение счетчика будет обновляться только периодически (с использованием частоты дискретизации) или после превышения порогового значения счетчика. Мне нужно значение счетчика точно в тот момент, когда я спрашиваю. Вот почему RDPMC казался таким привлекательным. Я полагаю, что выборка часто сама искажает показания счетчика производительности.
  • PAPI основывается на perf, поэтому, вероятно, наследует вышеупомянутую проблему.
  • Запишите модуль ядра - слишком много усилий, слишком подвержено ошибкам.

В идеале я бы хотел найти решение, которое работает на OpenBSD и Linux, но почему-то я считаю, что это высокий порядок. Возможно, сейчас для Linux.

Любая помощь наиболее ценится. Спасибо.

EDIT: я нашел Linux msr device node, чего, вероятно, было бы достаточно. Я оставлю вопрос на случай, если появится лучший ответ.

Ответ 1

Кажется, лучший способ - по крайней мере для Linux - использовать устройство msr node.

Вы просто открываете устройство node, ищите адрес требуемого MSR и читаете или записываете 8 байтов.

OpenBSD сложнее, поскольку (на момент написания) не существует прокси-сервера пользователя для MSR. Поэтому вам нужно будет написать модуль ядра или реализовать sysctl вручную.