¡Google y ack
-ing ha terminado! Tengo alguna respuesta.
Pero, en primer lugar, permítanme aclarar un poco más el objetivo de la pregunta: quiero distinguir claramente los procesos independientes en el sistema y sus contadores de rendimiento. Por ejemplo, el núcleo de un procesador, un dispositivo sin núcleo (aprendido recientemente), el kernel o la aplicación de usuario en el procesador, un bus (= controlador de bus), un disco duro son procesos independientes, no están sincronizados por un reloj . Y hoy en día probablemente todos tengan algún Contador de Monitoreo de Procesos (PMC). Me gustaría entender de qué procesos provienen los contadores. (También es útil para buscar en Google: el "vendedor" de una cosa lo pone a cero).
Además, el equipo utilizado para la búsqueda: Ubuntu 14.04
, linux 3.13.0-103-generic
, procesador Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz
(de /proc/cpuinfo
, cuenta con 2 núcleos físicos y virtuales - 4 de la materia física aquí).
Terminología, cosas que involucra la pregunta
De Intel:
el procesador es un core
dispositivo (es 1 dispositivo / proceso) y un montón de uncore
dispositivos , core
es lo que ejecuta el programa (reloj, ALU, registros, etc.), uncore
son dispositivos que se mueren, cerca del procesador por velocidad y baja latencia (la verdadera razón es "porque el fabricante puede hacerlo"); como lo entendí es básicamente el Northbridge, como en la placa base de la PC, más cachés; y AMD en realidad llama a estos dispositivos NorthBridge instead of
uncore`;
ubox
que aparece en mi sysfs
$ find /sys/devices/ -type d -name events
/sys/devices/cpu/events
/sys/devices/uncore_cbox_0/events
/sys/devices/uncore_cbox_1/events
- es un uncore
dispositivo que gestiona Last Level Cache (LLC, el último antes de llegar a RAM); Tengo 2 núcleos, por lo tanto, 2 LLC y 2 ubox
;
La Unidad de Monitoreo del Procesador (PMU) es un dispositivo separado que monitorea las operaciones de un procesador y las registra en el Contador de Monitoreo del Procesador (PMC) (cuenta errores de caché, ciclos de procesador, etc.); existen en core
y uncore
dispositivos; a los core
que se accede con la rdpmc
instrucción (leer PMC); el uncore
, dado que estos dispositivos dependen del procesador real disponible, se accede a través de Registros específicos del modelo (MSR) a través de rdmsr
(naturalmente);
aparentemente, el flujo de trabajo con ellos se realiza a través de pares de registros: 1 registro establece qué eventos cuenta el contador, 2 registros es el valor en el contador; el contador se puede configurar para aumentar después de un montón de eventos, no solo 1; + hay algunos interrupciones / interrupciones de notar la tecnología en estos contadores;
más se puede encontrar en el "Manual del desarrollador de software IA-32 Vol. 3B" del capítulo 18 "MONITOREO DEL DESEMPEÑO";
también, el formato de MSR concretamente para estos uncore
PMC para la versión "Architectural Performance Monitoring Version 1" (hay versiones 1-4 en el manual, no sé cuál es mi procesador) se describe en la "Figura 18-1. Diseño de IA32_PERFEVTSELx MSR "(página 18-3 en la mía), y la sección" 18.2.1.2 Eventos de rendimiento arquitectónico predefinidos "con" Tabla 18-1. Codificaciones de selección de máscaras y eventos para eventos de rendimiento arquitectónicos predefinidos ", que muestra el eventos que aparecen como Hardware event
en perf list
.
Desde el kernel de Linux:
kernel tiene un sistema (abstracción / capa) para administrar contadores de rendimiento de diferente origen, tanto software (kernel) como hardware, se describe en linux-source-3.13.0/tools/perf/design.txt
; un evento en este sistema se define como struct perf_event_attr
(archivo linux-source-3.13.0/include/uapi/linux/perf_event.h
), la parte principal del cual probablemente sea un __u64 config
campo; puede contener tanto una definición de evento específica de la CPU (la palabra de 64 bits en el formato descrito en las figuras de Intel) como el evento de un núcleo
El MSB de la palabra de configuración significa si el resto contiene [CPU sin procesar o evento del núcleo]
el evento del kernel definido con 7 bits para el tipo y 56 para el identificador del evento, que son enum
-s en el código, que en mi caso son:
$ 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
es mi alias ack-grep
, que es el nombre de ack
Debian; y ack
es increíble);
en el código fuente del kernel se pueden ver operaciones como "registrar todas las PMU descubiertas en el sistema" y tipos de estructura struct pmu
, que se pasan a algo int perf_pmu_register(struct pmu *pmu, const char *name, int type)
así, por lo tanto, uno podría llamar a este sistema "PMU del kernel", que sería una agregación de todas las PMU en el sistema; pero este nombre podría interpretarse como un sistema de monitoreo de las operaciones del kernel, lo que sería engañoso;
llamemos a este subsistema perf_events
por claridad;
como cualquier subsistema de kernel, este subsistema puede exportarse a sysfs
(que está hecho para exportar subsistemas de kernel para que la gente los use); y eso es lo que son esos events
directorios en mi /sys/
- el perf_events
subsistema exportado (¿partes de?) ;
Además, la utilidad de espacio de usuario perf
(integrada en Linux) sigue siendo un programa separado y tiene sus propias abstracciones; representa un evento solicitado por el usuario como monitoreo perf_evsel
(archivos linux-source-3.13.0/tools/perf/util/evsel.{h,c}
): esta estructura tiene un campo struct perf_event_attr attr;
, pero también un campo como el struct cpu_map *cpus;
que así la perf
utilidad asigna un evento a todas o CPU en particular.
Responder
De hecho, Hardware cache event
son "accesos directos" a los eventos de los dispositivos de caché ( ubox
de los uncore
dispositivos de Intel ), que son específicos del procesador, y se puede acceder a ellos a través del protocolo Raw hardware event descriptor
. Y Hardware event
son más estables dentro de la arquitectura, que, según tengo entendido, nombra los eventos del core
dispositivo. No hay otros "atajos" en mi kernel 3.13
para algunos otros uncore
eventos y contadores. Todo lo demás - Software
y Tracepoints
- son eventos del kernel.
Me pregunto si se accede a los core
's Hardware event
a través del mismo Raw hardware event descriptor
protocolo. Es posible que no lo hagan, ya que el contador / PMU se sienta core
, tal vez se accede de manera diferente. Por ejemplo, con esa rdpmu
instrucción, en lugar de rdmsr
, que accede uncore
. Pero no es tan importante.
Kernel PMU event
son solo los eventos, que se exportan a sysfs
. No sé cómo se hace esto (automáticamente por el núcleo todos los PMC descubiertos en el sistema, o simplemente algo codificado, y si agrego un kprobe
- ¿se exporta? Etc.). Pero el punto principal es que estos son los mismos eventos Hardware event
o cualquier otro en el perf_event
sistema interno .
Y no sé lo que esos
$ ls /sys/devices/uncore_cbox_0/events
clockticks
son.
Detalles sobre Kernel PMU event
Buscar a través del código conduce a:
$ 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]);
- lo que sucede en la función
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]); ... }
}
y perf_pmu__scan
está en el mismo archivo:
struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) {
...
pmu_read_sysfs(); // that's what it calls
}
- que también está en el mismo archivo:
/* Add all pmus in sysfs to pmu list: */
static void pmu_read_sysfs(void) {...}
Eso es.
Detalles sobre Hardware event
yHardware cache event
Aparentemente, Hardware event
proviene de lo que Intel llama "Eventos de rendimiento arquitectónico predefinidos", 18.2.1.2 en el Manual del desarrollador de software IA-32 Vol. 3B. Y "18.1 DESCRIPCIÓN GENERAL DEL MONITOREO DEL DESEMPEÑO" del manual los describe como:
La segunda clase de capacidades de supervisión del rendimiento se conoce como supervisión del rendimiento arquitectónico. Esta clase admite los mismos usos de muestreo de eventos basados en conteo e interrupción, con un conjunto más pequeño de eventos disponibles. El comportamiento visible de los eventos de rendimiento arquitectónico es consistente en las implementaciones de procesadores. La disponibilidad de las capacidades de supervisión del rendimiento arquitectónico se enumera utilizando el CPUID.0AH. Estos eventos se discuten en la Sección 18.2.
- el otro tipo es:
Comenzando con los procesadores Intel Core Solo e Intel Core Duo, hay dos clases de capacidades de monitoreo de rendimiento. La primera clase admite eventos para monitorear el rendimiento mediante el uso de conteo o muestreo de eventos basados en interrupciones. Estos eventos no son arquitectónicos y varían de un modelo de procesador a otro ...
Y estos eventos son solo enlaces a eventos de hardware "en bruto" subyacentes, a los que se puede acceder a través de la perf
utilidad como Raw hardware event descriptor
.
Para comprobar esto, mira 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,
...
}
- y 0x412e
se encuentra exactamente en la "Tabla 18-1. Codificaciones de UMask y Event Select para eventos de rendimiento arquitectónico predefinidos" para "LLC Misses":
Bit Position CPUID.AH.EBX | Event Name | UMask | Event Select
...
4 | LLC Misses | 41H | 2EH
- H
es para hex. Los 7 están en la estructura, más [PERF_COUNT_HW_REF_CPU_CYCLES] = 0x0300, /* pseudo-encoding *
. (El nombre es un poco diferente, las direcciones son las mismas).
Entonces los Hardware cache event
s están en estructuras como (en el mismo archivo):
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] =
{...}
- ¿Cuál debería ser para el puente de arena?
Uno de estos - snb_hw_cache_extra_regs[LL][OP_WRITE][RESULT_ACCESS]
está lleno de SNB_DMND_WRITE|SNB_L3_ACCESS
, donde de los def-s anteriores:
#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)
que debería ser igual a 0x00010102
, pero no sé cómo verificarlo con alguna tabla.
Y esto da una idea de cómo se usa en 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));
$
Los memcpy
s están terminados __init int intel_pmu_init(void) {... case:...}
.
Solo attr->config1
es un poco extraño. Pero está ahí, en perf_event_attr
(mismo linux-source-3.13.0/include/uapi/linux/perf_event.h
archivo):
...
union {
__u64 bp_addr;
__u64 config1; /* extension of config */
};
union {
__u64 bp_len;
__u64 config2; /* extension of config1 */
};
...
Están registrados en el perf_events
sistema del kernel con llamadas a int perf_pmu_register(struct pmu *pmu, const char *name, int type)
(definidas en linux-source-3.13.0/kernel/events/core.c:
):
static int __init init_hw_perf_events(void)
(archivo arch/x86/kernel/cpu/perf_event.c
) con llamadaperf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu)
(archivo arch/x86/kernel/cpu/perf_event_intel_uncore.c
, también hay arch/x86/kernel/cpu/perf_event_amd_uncore.c
) con llamadaret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
Finalmente, todos los eventos provienen del hardware y todo está bien. Pero aquí se podría notar: ¿por qué tenemos LLC-loads
en perf list
no ubox1 LLC-loads
, ya que estos son eventos HW y que podía comprender venimos ubox
es?
Eso es una cosa de la perf
utilidad y su perf_evsel
estructura: cuando solicita un evento HW perf
, define el evento de qué procesadores desea (el valor predeterminado es todo), y configura perf_evsel
el evento y los procesadores solicitados, luego, en la agregación es suma los contadores de todos los procesadores en perf_evsel
(o hace algunas otras estadísticas con ellos).
Se puede ver en 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;
}
(Entonces, para la utilidad, perf
un "contador único" ni siquiera es un perf_event_attr
, que es una forma general, que se adapta tanto a eventos SW como a HW, es un evento de su consulta: los mismos eventos pueden provenir de diferentes dispositivos y se agregan .)
También un aviso: struct perf_evsel
contiene solo 1 struct perf_evevent_attr
, pero también tiene un campo struct perf_evsel *leader;
: está anidado. Hay una característica de "grupos de eventos (jerárquicos)" en el perf_events
que puede enviar un conjunto de contadores juntos, para que puedan compararse entre sí y así sucesivamente. No está seguro de cómo funciona con eventos independientes de kernel
, core
, ubox
. Pero este anidamiento perf_evsel
es. Y, muy probablemente, así es como perf
gestiona una consulta de varios eventos juntos.