2015-05-18 3 views
3

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

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

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

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

ответ

2

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

Example.

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

1

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

Поскольку perf поддерживает только L1i, L1D и события кэш последнего уровня, вы должны будете использовать режим PERF_EVENT_RAW и использовать номера от руководства на ваш CPU.

Для реализации профилирование, вам нужно настроить sample_interval, poll/select FD или ждать 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])); 
    } 
} 
Смежные вопросы