Как настроить и отобрать счетчики производительности 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 вручную.