Поиск в Google и ack
окончание! У меня есть какой-то ответ.
Но сначала позвольте мне прояснить цель вопроса немного подробнее: я хочу четко различать независимые процессы в системе и их счетчики производительности. Например, ядро процессора, неосновное устройство (о котором недавно узнали), ядро или пользовательское приложение на процессоре, шина (= контроллер шины), жесткий диск - все это независимые процессы, они не синхронизируются по часам , И в настоящее время, вероятно, все они имеют некоторый счетчик мониторинга процесса (PMC). Я хотел бы понять, из каких процессов происходят счетчики. (Это также полезно при поиске в Google: «продавец» вещи обнуляет это лучше.)
Кроме того , передача используется для поиска: 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
устройства, установленные на кристалле, близкие к процессору по скорости и низкой задержке (настоящая причина «потому что производитель может это сделать»); как я понял, это в основном северный мост, как на материнской плате ПК, плюс кеши; и 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 LLC и 2 ubox
;
Блок мониторинга процессора (PMU) - это отдельное устройство, которое отслеживает операции процессора и записывает их в счетчик мониторинга процессора (PMC) (подсчитывает потери в кэш-памяти, циклы процессора и т. Д.); они существуют core
и на uncore
устройствах; в core
них доступны с rdpmc
(чтение PMC) инструкции; uncore
, так как эти устройства зависит от фактического процессора под рукой, доступны через моделезависимые регистры (MSR) через rdmsr
(естественно);
по-видимому, рабочий процесс с ними осуществляется через пары регистров - 1 регистр устанавливает, какие события счетчик считает, 2 регистр - значение в счетчике; счетчик может быть настроен на увеличение после нескольких событий, а не только 1; + в этих счетчиках есть некоторые перехваты / технические заметки переполнения;
больше можно найти в главе 18 «Руководства разработчика программного обеспечения IA-32», том 3 «Мониторинг производительности»;
также, формат MSR конкретно для этих uncore
PMC для версии «Мониторинг производительности архитектуры, версия 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 слова конфигурации указывает, содержит ли остальное [событие необработанного ЦП или ядра]
событие ядра, определенное с 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
это здорово);
в исходном коде ядра можно увидеть такие операции, как «зарегистрировать все PMU, обнаруженные в системе» и типы структур struct pmu
, которые передаются в нечто подобное int perf_pmu_register(struct pmu *pmu, const char *name, int type)
- таким образом, можно просто назвать эту систему «PMU ядра», который будет агрегировать всех 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
. Я не знаю, как это сделать (автоматически ядром все обнаруженные PMC в системе, или просто что-то жестко запрограммированное, и если я добавлю 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, том 3B. И «18.1 ОБЗОР МОНИТОРИНГА ЭФФЕКТИВНОСТИ» руководства описывает их как:
Второй класс возможностей мониторинга производительности называется мониторингом производительности архитектуры. Этот класс поддерживает то же использование подсчета и выборки событий на основе прерываний с меньшим набором доступных событий. Видимое поведение событий производительности архитектуры является единым для всех реализаций процессора. Доступность возможностей мониторинга производительности архитектуры перечисляется с помощью CPUID.0AH. Эти события обсуждаются в разделе 18.2.
- другой тип:
Начиная с процессоров Intel Core Solo и Intel Core Duo, существует два класса возможностей мониторинга производительности. Первый класс поддерживает события для мониторинга производительности, используя подсчет или использование выборок событий на основе прерываний. Эти события не являются архитектурными и варьируются от одной модели процессора к другой ...
И эти события действительно просто ссылки на базовые «сырые» аппаратные события, к которым можно получить доступ через perf
утилиту as 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
для гекса. Все 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
сделано в __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
управляет запросом нескольких событий вместе.