Как настроить и отобрать счетчики производительности Intel в процессе работы

Короче говоря, я пытаюсь добиться следующего в процессе тестирования пользовательского пространства (псевдокод, предполагая 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 из моего эталонного жгута?

Материал, который я изучал / думал о:

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

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

Любая помощь наиболее ценится. Благодарю.

РЕДАКТИРОВАТЬ: Я только что нашел узел устройства Linux MSR, что, вероятно, будет достаточно. Я оставлю вопрос на случай, если появится лучший ответ.

1 ответ

Решение

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

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

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

Другие вопросы по тегам