Вкратце, я пытаюсь добиться следующих результатов в тестовом процессе пользовательской среды (псевдокод, предполагая 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, чего, вероятно, было бы достаточно. Я оставлю вопрос на случай, если появится лучший ответ.