Гугл і ack
-інг закінчено! У мене є відповідь.
Але спочатку дозвольте мені ще трохи уточнити мету питання: я хочу чітко розмежувати незалежні процеси в системі та їх лічильники ефективності. Наприклад, ядро процесора, некомерційний пристрій (про це дізналися недавно), ядро або користувацька програма на процесорі, шина (= контролер шини), жорсткий диск - це все незалежні процеси, вони не синхронізуються годинником . І сьогодні, ймовірно, всі вони мають лічильник моніторингу процесів (PMC). Я хотів би зрозуміти, з яких процесів надходять лічильники. (Це також корисно в гуглінгу: "постачальник" речі нуліть це краще.)
Крім того , передача використовується для пошуку: Ubuntu 14.04
, linux 3.13.0-103-generic
, процесор Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz
(з /proc/cpuinfo
, він має 2 фізичних ядра і 4 віртуальних - фізична матерія тут).
Термінологія, що стосується питання
Від Intel:
процесор - це core
пристрій (це 1 пристрій / процес) і купа uncore
пристроїв - core
це те, що запускає програму (годинник, ALU, регістри тощо), uncore
це пристрої, які ставлять на штамп, близькі до процесора за швидкістю та низькою затримкою (справжня причина є "тому що виробник може це зробити"); як я зрозумів, це в основному Northbridge, як на материнській платі ПК, плюс кеші; AMD насправді називає ці пристрої NorthBridge instead of
uncore`;
ubox
який виявляється в моєму sysfs
$ find /sys/devices/ -type d -name events
/sys/devices/cpu/events
/sys/devices/uncore_cbox_0/events
/sys/devices/uncore_cbox_1/events
- це uncore
пристрій, який керує кешем останнього рівня (LLC, останній перед тим, як потрапляти на ОЗУ); У мене 2 ядра, таким чином, 2 ТОВ і 2 ubox
;
Блок моніторингу процесорів (PMU) - це окремий пристрій, який здійснює моніторинг операцій процесора і записує їх у лічильник моніторингу процесорів (PMC) (рахує пропуски кешу, цикли процесора тощо); вони існують на core
і uncore
пристроях; до core
них звертаються rdpmc
(читайте PMC) інструкцію; uncore
, Так як ці пристрої залежить від фактичного процесора під рукою, доступні через моделезавісімие регістри (MSR) через rdmsr
(природно);
Мабуть, робочий процес з ними здійснюється за допомогою пар регістрів - 1 набір реєстрів, який позначає лічильник, 2 регістр - це значення в лічильнику; лічильник може бути налаштований на приріст після ряду подій, а не лише 1; + в цих лічильниках є деякі переривання / техніка, що помічають переповнення;
більше ви можете знайти в Інструкції Intel «IA-32 Software Developer Guide» Vol 3B »глави 18« МОНИТОРИНГ РОБОТИ »;
також формат MSR конкретно для цих uncore
ПМК для версії "Архітектурний моніторинг продуктивності версії 1" (в посібнику є версії 1-4, я не знаю, який з них є моїм процесором) описаний у "Рисунок 18-1. Макет з MSR IA32_PERFEVTSELx "(сторінка 18-3 в шахті) та розділ" 18.2.1.2 Заздалегідь визначені події архітектурної ефективності "з" Таблиця 18-1. Кодування вибору UMask та подій для заздалегідь визначених подій архітектурної діяльності ", на якій показано події, які відображаються як Hardware event
у perf list
.
З ядра Linux:
ядро має систему (абстракція / шар) для управління лічильниками продуктивності різного походження, як програмного забезпечення (ядра), так і апаратного забезпечення, в ньому описано linux-source-3.13.0/tools/perf/design.txt
; подія в цій системі визначається як struct perf_event_attr
(файл linux-source-3.13.0/include/uapi/linux/perf_event.h
), основна частина якої, ймовірно, __u64 config
поле - вона може містити як специфічне для процесора визначення події (64-бітове слово у форматі, описаному на рисунках цих Intel), так і подія ядра
MSB слова config означає, що решта містить [raw CPU або подія ядра]
подія ядра, визначена з 7 бітів для типу та 56 для ідентифікатора події, які enum
в коді є –s, які в моєму випадку:
$ ak PERF_TYPE linux-source-3.13.0/include/
...
linux-source-3.13.0/include/uapi/linux/perf_event.h
29: PERF_TYPE_HARDWARE = 0,
30: PERF_TYPE_SOFTWARE = 1,
31: PERF_TYPE_TRACEPOINT = 2,
32: PERF_TYPE_HW_CACHE = 3,
33: PERF_TYPE_RAW = 4,
34: PERF_TYPE_BREAKPOINT = 5,
36: PERF_TYPE_MAX, /* non-ABI */
( ak
це мій псевдонім ack-grep
, який є ім'ям для ack
Debian; і ack
це приголомшливо);
у вихідному коді ядра можна побачити такі операції, як "реєструвати всі ПМУ struct pmu
, які є в системі," та типи структури , які передаються на щось подібне int perf_pmu_register(struct pmu *pmu, const char *name, int type)
- таким чином, можна було б просто назвати цю систему "PMU ядра", що було б агрегацією всіх ПМУ в системі; але цю назву можна інтерпретувати як систему моніторингу операцій ядра, що було б оманливим;
назвемо цю підсистему perf_events
для ясності;
як і будь-яка підсистема ядра, цю підсистему можна експортувати в sysfs
(що робиться для експорту ядра підсистем для використання людьми); і ось які це events
каталоги в моїй /sys/
- експортованій (частини?) perf_events
підсистеми;
також утиліта простору користувача perf
(вбудована в Linux) все ще є окремою програмою і має власні абстракції; він являє собою подію, яку вимагає моніторинг користувачем як perf_evsel
(файли linux-source-3.13.0/tools/perf/util/evsel.{h,c}
) - ця структура має поле struct perf_event_attr attr;
, але також поле, подібне struct cpu_map *cpus;
тому, як perf
утиліта призначає подію всім або певним процесорам.
Відповідь
Дійсно, Hardware cache event
це "ярлики" до подій кеш-пристроїв (пристроїв ubox
Intel uncore
), які залежать від процесора, і до них можна отримати доступ через протокол Raw hardware event descriptor
. І Hardware event
вони стабільніші в архітектурі, які, як я розумію, називають події з core
пристрою. У моєму ядрі немає інших "ярликів" 3.13
до якихось інших uncore
подій та лічильників. Всі інші - Software
і Tracepoints
- події ядра.
Цікаво , якщо core
«S Hardware event
s доступні через той же Raw hardware event descriptor
протокол. Вони можуть - ні, оскільки лічильник / PMU сидить core
, можливо, до нього звертаються інакше. Наприклад, rdpmu
замість тієї інструкції rdmsr
, яка отримує доступ uncore
. Але це не так важливо.
Kernel PMU event
- це лише події, в які експортуються sysfs
. Я не знаю, як це робиться (автоматично ядром усі виявлені ПМС в системі, або просто щось жорстко закодоване, і якщо я додам kprobe
- це експортується? Тощо). Але головне - це ті самі події, що Hardware event
і будь-які інші у внутрішній perf_event
системі.
І я не знаю, що це
$ ls /sys/devices/uncore_cbox_0/events
clockticks
є.
Детальніше про Kernel PMU event
Пошук за кодом призводить до:
$ ak "Kernel PMU" linux-source-3.13.0/tools/perf/
linux-source-3.13.0/tools/perf/util/pmu.c
629: printf(" %-50s [Kernel PMU event]\n", aliases[j]);
- що відбувається у функції
void print_pmu_events(const char *event_glob, bool name_only) {
...
while ((pmu = perf_pmu__scan(pmu)) != NULL)
list_for_each_entry(alias, &pmu->aliases, list) {...}
...
/* b.t.w. list_for_each_entry is an iterator
* apparently, it takes a block of {code} and runs over some lost
* Ruby built in kernel!
*/
// then there is a loop over these aliases and
loop{ ... printf(" %-50s [Kernel PMU event]\n", aliases[j]); ... }
}
і perf_pmu__scan
знаходиться в одному файлі:
struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) {
...
pmu_read_sysfs(); // that's what it calls
}
- який також є в одному файлі:
/* Add all pmus in sysfs to pmu list: */
static void pmu_read_sysfs(void) {...}
Це воно.
Деталі про Hardware event
таHardware cache event
Мабуть, це Hardware event
походження від того, що Intel називає «Попередньо визначеними подіями архітектурної ефективності», 18.2.1.2 в Посібнику розробника програмного забезпечення IA-32, Vol 3B. І "Огляд огляду моніторингу виконання 18.1" описує їх як:
Другий клас можливостей моніторингу продуктивності називають архітектурним моніторингом ефективності. Цей клас підтримує ті ж самі підрахунки подій для відбору проб на основі переривань, з меншим набором доступних подій. Видима поведінка подій архітектурної продуктивності узгоджується у всіх процесорах. Наявність можливостей контролю архітектури продуктивності перераховується за допомогою CPUID.0AH. Ці події обговорюються у розділі 18.2.
- інший тип:
Починаючи з процесорів Intel Core Solo та Intel Core Duo, є два класи можливостей моніторингу продуктивності. Перший клас підтримує події для моніторингу продуктивності з використанням підрахунку або використання вибірок на основі переривань. Ці події є не архітектурними і відрізняються від однієї моделі процесора до іншої ...
І ці події справді є лише посиланнями на основні "сирі" апаратні події, до яких можна отримати доступ за допомогою perf
утиліти як Raw hardware event descriptor
.
Для перевірки цього виглядає linux-source-3.13.0/arch/x86/kernel/cpu/perf_event_intel.c
:
/*
* Intel PerfMon, used on Core and later.
*/
static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
{
[PERF_COUNT_HW_CPU_CYCLES] = 0x003c,
[PERF_COUNT_HW_INSTRUCTIONS] = 0x00c0,
[PERF_COUNT_HW_CACHE_REFERENCES] = 0x4f2e,
[PERF_COUNT_HW_CACHE_MISSES] = 0x412e,
...
}
- і точно 0x412e
знайдено в "Таблиці 18-1. Кодування вибору UMask та подій для заздалегідь визначених подій архітектурної ефективності" для "LLC Misses":
Bit Position CPUID.AH.EBX | Event Name | UMask | Event Select
...
4 | LLC Misses | 41H | 2EH
- H
це для hex. Усі 7 в структурі, плюс [PERF_COUNT_HW_REF_CPU_CYCLES] = 0x0300, /* pseudo-encoding *
. (Найменування дещо інше, адреси однакові.)
Тоді Hardware cache event
s знаходяться в таких структурах, як (у тому самому файлі):
static __initconst const u64 snb_hw_cache_extra_regs
[PERF_COUNT_HW_CACHE_MAX]
[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_COUNT_HW_CACHE_RESULT_MAX] =
{...}
- що має бути для піщаного мосту?
Одне з них - snb_hw_cache_extra_regs[LL][OP_WRITE][RESULT_ACCESS]
заповнене SNB_DMND_WRITE|SNB_L3_ACCESS
, де з вищезазначених задач:
#define SNB_L3_ACCESS SNB_RESP_ANY
#define SNB_RESP_ANY (1ULL << 16)
#define SNB_DMND_WRITE (SNB_DMND_RFO|SNB_LLC_RFO)
#define SNB_DMND_RFO (1ULL << 1)
#define SNB_LLC_RFO (1ULL << 8)
яка повинна дорівнювати 0x00010102
, але я не знаю, як це перевірити за допомогою якоїсь таблиці.
Це дає уявлення про те, як він використовується у perf_events
:
$ ak hw_cache_extra_regs linux-source-3.13.0/arch/x86/kernel/cpu/
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event.c
50:u64 __read_mostly hw_cache_extra_regs
292: attr->config1 = hw_cache_extra_regs[cache_type][cache_op][cache_result];
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event.h
521:extern u64 __read_mostly hw_cache_extra_regs
linux-source-3.13.0/arch/x86/kernel/cpu/perf_event_intel.c
272:static __initconst const u64 snb_hw_cache_extra_regs
567:static __initconst const u64 nehalem_hw_cache_extra_regs
915:static __initconst const u64 slm_hw_cache_extra_regs
2364: memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
2365: sizeof(hw_cache_extra_regs));
2407: memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
2408: sizeof(hw_cache_extra_regs));
2424: memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
2425: sizeof(hw_cache_extra_regs));
2452: memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
2453: sizeof(hw_cache_extra_regs));
2483: memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
2484: sizeof(hw_cache_extra_regs));
2516: memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
$
В memcpy
s зроблені в __init int intel_pmu_init(void) {... case:...}
.
Тільки attr->config1
трохи дивно. Але він є там, у perf_event_attr
(той самий linux-source-3.13.0/include/uapi/linux/perf_event.h
файл):
...
union {
__u64 bp_addr;
__u64 config1; /* extension of config */
};
union {
__u64 bp_len;
__u64 config2; /* extension of config1 */
};
...
Вони реєструються в perf_events
системі ядра з викликами до int perf_pmu_register(struct pmu *pmu, const char *name, int type)
(визначених у linux-source-3.13.0/kernel/events/core.c:
):
static int __init init_hw_perf_events(void)
(файл arch/x86/kernel/cpu/perf_event.c
) з викликомperf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu)
(файл arch/x86/kernel/cpu/perf_event_intel_uncore.c
, також є arch/x86/kernel/cpu/perf_event_amd_uncore.c
) з викликомret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
Отже, нарешті, всі події виходять із обладнання та все гаразд. Але тут можна було помітити: чому у нас LLC-loads
в perf list
і немає ubox1 LLC-loads
, так як вони є HW події , і вони actualy приходять з ubox
ес?
Це справа perf
утиліти та її perf_evsel
структури: коли ви вимагаєте від події HW, perf
ви визначаєте подію, від яких процесорів ви хочете це (за замовчуванням це все), і вона встановлює perf_evsel
запитувані події та процесори, тоді при агрегації є підсумовує лічильники від усіх процесорів у perf_evsel
(або проводиться якась інша статистика з ними).
Його можна побачити у tools/perf/builtin-stat.c
:
/*
* Read out the results of a single counter:
* aggregate counts across CPUs in system-wide mode
*/
static int read_counter_aggr(struct perf_evsel *counter)
{
struct perf_stat *ps = counter->priv;
u64 *count = counter->counts->aggr.values;
int i;
if (__perf_evsel__read(counter, perf_evsel__nr_cpus(counter),
thread_map__nr(evsel_list->threads), scale) < 0)
return -1;
for (i = 0; i < 3; i++)
update_stats(&ps->res_stats[i], count[i]);
if (verbose) {
fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
perf_evsel__name(counter), count[0], count[1], count[2]);
}
/*
* Save the full runtime - to allow normalization during printout:
*/
update_shadow_stats(counter, count);
return 0;
}
(Отже, для утиліти perf
"єдиний лічильник" навіть не є perf_event_attr
, що є загальною формою, яка відповідає як SW, так і HW подіям, це подія вашого запиту - одні й ті ж події можуть надходити з різних пристроїв і вони агрегуються .)
Також повідомлення: struct perf_evsel
містить лише 1 struct perf_evevent_attr
, але воно також має поле struct perf_evsel *leader;
- воно є вкладеним. Існує особливість "(ієрархічних) груп подій" в perf_events
, коли ви можете розсилати купу лічильників разом, щоб їх можна було порівнювати один з одним тощо. Не знаю , як він працює з незалежними подіями з kernel
, core
, ubox
. Але це гніздування perf_evsel
це. І, швидше за все, саме так perf
керується запитом кількох подій разом.