¡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 coredispositivo (es 1 dispositivo / proceso) y un montón de uncoredispositivos , corees lo que ejecuta el programa (reloj, ALU, registros, etc.), uncoreson 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 ofuncore`;
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 uncoredispositivo 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 corey uncoredispositivos; a los coreque se accede con la rdpmcinstrucció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 uncorePMC 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 eventen 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 configcampo; 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 */
( akes mi alias ack-grep, que es el nombre de ackDebian; y ackes 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_eventspor 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 eventsdirectorios en mi /sys/- el perf_eventssubsistema 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 perfutilidad asigna un evento a todas o CPU en particular.
Responder
De hecho, Hardware cache eventson "accesos directos" a los eventos de los dispositivos de caché ( uboxde los uncoredispositivos 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 eventson más estables dentro de la arquitectura, que, según tengo entendido, nombra los eventos del coredispositivo. No hay otros "atajos" en mi kernel 3.13para algunos otros uncoreeventos y contadores. Todo lo demás - Softwarey Tracepoints- son eventos del kernel.
Me pregunto si se accede a los core's Hardware eventa través del mismo Raw hardware event descriptorprotocolo. 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 rdpmuinstrucción, en lugar de rdmsr, que accede uncore. Pero no es tan importante.
Kernel PMU eventson 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 evento cualquier otro en el perf_eventsistema 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__scanestá 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 eventyHardware cache event
Aparentemente, Hardware eventproviene 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 perfutilidad 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 0x412ese 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
- Hes 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 events 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 memcpys están terminados __init int intel_pmu_init(void) {... case:...}.
Solo attr->config1es un poco extraño. Pero está ahí, en perf_event_attr(mismo linux-source-3.13.0/include/uapi/linux/perf_event.harchivo):
...
union {
__u64 bp_addr;
__u64 config1; /* extension of config */
};
union {
__u64 bp_len;
__u64 config2; /* extension of config1 */
};
...
Están registrados en el perf_eventssistema 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-loadsen perf listno ubox1 LLC-loads, ya que estos son eventos HW y que podía comprender venimos uboxes?
Eso es una cosa de la perfutilidad y su perf_evselestructura: cuando solicita un evento HW perf, define el evento de qué procesadores desea (el valor predeterminado es todo), y configura perf_evselel 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, perfun "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_evselcontiene 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_eventsque 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_evseles. Y, muy probablemente, así es como perfgestiona una consulta de varios eventos juntos.