Можно ли использовать профилировщик Linux Perf внутри кода C ++?

Я хотел бы измерить соотношение попаданий и промахов в кеше L1, L2 и L3 для некоторых частей моего кода C ++. Мне не интересно использовать Perf для всего моего приложения. Можно ли использовать Perf в качестве библиотеки внутри C ++?

int main() {
...
...
start_profiling()
// The part I'm interested in
...
end_profiling()
...
...
}

Я дал Intel PCM шанс, но у меня было две проблемы с ним. Во-первых, это дал мне несколько странных цифр. Во-вторых, он не поддерживает профилирование кеша L1.

Если это невозможно с Perf, какой самый простой способ получить эту информацию?

3

Решение

Похоже, все, что вы пытаетесь сделать, это прочитать несколько счетчиков перфектов, то, что PAPI Библиотека идеально подходит для.

Пример.

полный список поддерживаемых счетчиков довольно долго, но звучит так, как будто тебя больше всего интересует PAPI_L1_TCM, PAPI_L1_TCA, и их L2 а также L3 двойники. Обратите внимание, что вы также можете разбить доступ на чтение / запись, а также различать кэши команд и данных.

3

Другие решения

Да, существует специальный мониторинг для каждого потока, который позволяет считывать счетчики перфектов из пользовательского пространства. Смотрите страницу руководства для perf_event_open(2)

поскольку perf поддерживает только события кэша L1i, L1d и последнего уровня, которые вам необходимо использовать PERF_EVENT_RAW режим и использовать цифры из ручного на ваш процессор.

Для реализации профилирования вам необходимо настроить sample_interval, poll/select жду или жду SIGIO сигнал, и когда это произойдет, прочитайте образец и указатель инструкции от него. Позже вы можете попытаться разрешить возвращенные указатели инструкций в именах функций, используя отладчик, такой как GDB.


Другой вариант заключается в использовании SystemTap. Вам понадобится пустая реализация start|end_profiling(), просто чтобы включить профилирование SystemTap с чем-то вроде этого:

global traceme, prof;

probe process("/path/to/your/executable").function("start_profiling") {
traceme = 1;
}

probe process("/path/to/your/executable").function("end_profiling") {
traceme = 0;
}

probe perf.type(4).config(/* RAW value of perf event */).sample(10000) {
prof[usymname(uaddr())] <<< 1;
}

probe end {
foreach([sym+] in prof) {
printf("%16s %d\n", sym, @count(prof[sym]));
}
}
1

По вопросам рекламы [email protected]