Googeln und ack
-ing ist vorbei! Ich habe eine Antwort.
Lassen Sie mich zunächst das Ziel der Frage etwas näher erläutern: Ich möchte unabhängige Prozesse im System und ihre Leistungsindikatoren klar unterscheiden. Zum Beispiel sind ein Kern eines Prozessors, ein Uncore-Gerät (das kürzlich kennengelernt wurde), ein Kernel oder eine Benutzeranwendung auf dem Prozessor, ein Bus (= Bus-Controller) und eine Festplatte unabhängige Prozesse, die nicht durch eine Uhr synchronisiert werden . Und heutzutage haben wahrscheinlich alle einen Process Monitoring Counter (PMC). Ich würde gerne verstehen, aus welchen Prozessen die Zähler stammen. (Es ist auch hilfreich beim Googeln: Der "Verkäufer" einer Sache setzt es besser auf Null.)
Auch das Getriebe für die Suche: Ubuntu 14.04
, linux 3.13.0-103-generic
, Prozessor Intel(R) Core(TM) i5-3317U CPU @ 1.70GHz
(ab /proc/cpuinfo
, es verfügt über 2 physische Kerne und 4 virtuelle - die physische Materie hier).
Terminologie, Dinge, die die Frage beinhaltet
Von Intel:
Der Prozessor ist ein core
Gerät (es ist 1 Gerät / Prozess) und eine Reihe von uncore
Geräten . Er core
führt das Programm aus (Uhr, ALU, Register usw.). Er uncore
ist ein Gerät, das aus Gründen der Geschwindigkeit und der geringen Latenz in der Nähe des Prozessors auf den Chip gestellt wird (der wahre Grund) ist "weil der Hersteller das kann"); Wie ich verstanden habe, handelt es sich im Grunde genommen um die Northbridge, wie auf einem PC-Motherboard, plus Caches. und AMD nennt diese Geräte tatsächlich NorthBridge instead of
uncore`;
ubox
was sich in meinem zeigt sysfs
$ find /sys/devices/ -type d -name events
/sys/devices/cpu/events
/sys/devices/uncore_cbox_0/events
/sys/devices/uncore_cbox_1/events
- ist ein uncore
Gerät, das den Last Level Cache (LLC, den letzten vor dem Erreichen des RAM) verwaltet; Ich habe 2 Kerne, also 2 LLC und 2 ubox
;
Die Prozessorüberwachungseinheit (PMU) ist ein separates Gerät, das die Operationen eines Prozessors überwacht und diese im Prozessorüberwachungszähler (PMC) aufzeichnet (zählt Cache-Fehler, Prozessorzyklen usw.). sie existieren auf core
und uncore
Geräte; Auf diese wird mit der Anweisung (PMC lesen) core
zugegriffen rdpmc
. die uncore
, da diese Geräte auf dem tatsächlichen Prozessor zur Hand abhängen, wird über Modell spezifische Register (MSR) über zugegriffen rdmsr
(natürlich);
anscheinend erfolgt der Workflow mit ihnen über Registerpaare - 1 Registersatz, welche Ereignisse der Zähler zählt, 2 Register ist der Wert im Zähler; Der Zähler kann so konfiguriert werden, dass er nach einer Reihe von Ereignissen inkrementiert wird, nicht nur nach 1. + Es gibt einige Interrupts / Tech, die Überläufe in diesen Zählern bemerken.
Weitere Informationen finden Sie in Intels "IA-32 Software Developer's Manual Vol 3B", Kapitel 18 "PERFORMANCE MONITORING".
Das MSR-Format für diese uncore
PMCs für die Version "Architectural Performance Monitoring Version 1" (es gibt die Versionen 1 bis 4 im Handbuch, ich weiß nicht, welcher mein Prozessor ist) ist in "Abbildung 18-1. Layout" beschrieben von IA32_PERFEVTSELx-MSRs "(Seite 18-3 in meinem) und Abschnitt" 18.2.1.2 Vordefinierte Architekturleistungsereignisse "mit" Tabelle 18-1. UMask- und Ereignisauswahlcodierungen für vordefinierte Architekturleistungsereignisse ", in denen die Ereignisse, die wie Hardware event
in angezeigt werden perf list
.
Vom Linux-Kernel:
Der Kernel verfügt über ein System (Abstraktion / Schicht) zum Verwalten von Leistungsindikatoren unterschiedlichen Ursprungs, sowohl Software (Kernel) als auch Hardware linux-source-3.13.0/tools/perf/design.txt
. Ein Ereignis in diesem System ist definiert als struct perf_event_attr
(Datei linux-source-3.13.0/include/uapi/linux/perf_event.h
), dessen Hauptteil wahrscheinlich ein __u64 config
Feld ist. Es kann sowohl eine CPU-spezifische Ereignisdefinition (das 64-Bit-Wort in dem in den Intel-Abbildungen beschriebenen Format) als auch ein Kernel-Ereignis enthalten
Das MSB des Konfigurationsworts gibt an, ob der Rest [das Ereignis der rohen CPU oder des Kernels] enthält.
Das Ereignis des Kernels, das mit 7 Bits für den Typ und 56 für die Kennung des Ereignisses definiert ist. enum
Dies sind -s im Code. In meinem Fall sind dies:
$ 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
ist mein Alias für ack-grep
, was der Name für ack
Debian ist; und ack
ist fantastisch);
Im Quellcode des Kernels sieht man Operationen wie "Alle auf dem System entdeckten PMUs registrieren" und Strukturtypen struct pmu
, die an so etwas wie übergeben int perf_pmu_register(struct pmu *pmu, const char *name, int type)
werden. Man könnte dieses System also einfach "PMU des Kernels" nennen, was eine Aggregation wäre aller PMUs im System; Dieser Name könnte jedoch als Überwachungssystem für die Kerneloperationen interpretiert werden, was irreführend wäre.
Nennen wir dieses Subsystem der perf_events
Klarheit halber.
Wie jedes Kernel-Subsystem kann dieses Subsystem exportiert werden sysfs
(das zum Exportieren von Kernel-Subsystemen für Benutzer bestimmt ist). und das sind diese events
Verzeichnisse in meinem /sys/
- dem exportierten (Teile von?) perf_events
Subsystem;
Außerdem ist das User-Space-Dienstprogramm perf
(in Linux integriert) immer noch ein separates Programm und verfügt über eigene Abstraktionen. Es stellt ein Ereignis dar, das vom Benutzer als perf_evsel
(Dateien linux-source-3.13.0/tools/perf/util/evsel.{h,c}
) überwacht werden soll. Diese Struktur enthält ein Feld struct perf_event_attr attr;
, aber auch ein Feld struct cpu_map *cpus;
, in dem das perf
Dienstprogramm allen oder bestimmten CPUs ein Ereignis zuweist.
Antworten
In der Tat handelt Hardware cache event
es sich um "Verknüpfungen" zu den Ereignissen der Cache-Geräte ( ubox
der Intel- uncore
Geräte), die prozessorspezifisch sind und über das Protokoll aufgerufen werden können Raw hardware event descriptor
. Und Hardware event
sind innerhalb der Architektur stabiler, die, wie ich verstehe, die Ereignisse vom core
Gerät benennen . In meinem Kernel gibt es keine anderen "Verknüpfungen" 3.13
zu anderen uncore
Ereignissen und Zählern. Alles andere - Software
und Tracepoints
- sind Kernel-Ereignisse.
Ich frage mich , ob die core
‚s Hardware event
s über das gleiche Zugriff Raw hardware event descriptor
Protokoll. Möglicherweise nicht - da der Zähler / die PMU aktiviert ist core
, wird möglicherweise anders darauf zugegriffen. Zum Beispiel mit dieser rdpmu
Anweisung anstelle von rdmsr
, auf die zugegriffen wird uncore
. Aber es ist nicht so wichtig.
Kernel PMU event
sind nur die Ereignisse, in die exportiert wird sysfs
. Ich weiß nicht, wie das gemacht wird (automatisch vom Kernel alle entdeckten PMCs auf dem System oder nur etwas fest codiertes, und wenn ich ein hinzufüge kprobe
- wird es exportiert? Usw.). Der Hauptpunkt ist jedoch, dass dies dieselben Ereignisse wie Hardware event
oder andere im internen perf_event
System sind.
Und ich weiß nicht was das ist
$ ls /sys/devices/uncore_cbox_0/events
clockticks
sind.
Details zu Kernel PMU event
Das Durchsuchen des Codes führt zu:
$ 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]);
- was in der Funktion passiert
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]); ... }
}
und perf_pmu__scan
ist in der gleichen Datei:
struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu) {
...
pmu_read_sysfs(); // that's what it calls
}
- das ist auch in der gleichen Datei:
/* Add all pmus in sysfs to pmu list: */
static void pmu_read_sysfs(void) {...}
Das ist es.
Details zu Hardware event
undHardware cache event
Anscheinend Hardware event
stammen die von Intel als "vordefinierte architektonische Leistungsereignisse", 18.2.1.2 im IA-32 Software Developer's Manual Vol 3B. Und "18.1 ÜBERBLICK ÜBER DIE LEISTUNGSÜBERWACHUNG" des Handbuchs beschreibt sie wie folgt:
Die zweite Klasse von Leistungsüberwachungsfunktionen wird als Architekturleistungsüberwachung bezeichnet. Diese Klasse unterstützt die gleiche Verwendung von Zähl- und Interrupt-basierten Ereignisabtastungen mit einem kleineren Satz verfügbarer Ereignisse. Das sichtbare Verhalten von Architekturleistungsereignissen ist bei allen Prozessorimplementierungen konsistent. Die Verfügbarkeit von Funktionen zur Überwachung der Architekturleistung wird mithilfe der CPUID.0AH aufgelistet. Diese Ereignisse werden in Abschnitt 18.2 erläutert.
- Der andere Typ ist:
Beginnend mit Intel Core Solo und Intel Core Duo Prozessoren gibt es zwei Klassen von Leistungsüberwachungsfunktionen. Die erste Klasse unterstützt Ereignisse zur Überwachung der Leistung mithilfe der Zählung oder der Verwendung von Interrupt-basierten Ereignisabtastungen. Diese Ereignisse sind nicht architektonisch und variieren von Prozessormodell zu Prozessor ...
Und diese Ereignisse sind in der Tat nur Links zu zugrunde liegenden "rohen" Hardwareereignissen, auf die über das perf
Dienstprogramm als zugegriffen werden kann Raw hardware event descriptor
.
Um dies zu überprüfen, schaut man sich an 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,
...
}
- und genau 0x412e
finden Sie in "Tabelle 18-1. UMask- und Ereignisauswahlcodierungen für vordefinierte architektonische Leistungsereignisse" für "LLC Misses":
Bit Position CPUID.AH.EBX | Event Name | UMask | Event Select
...
4 | LLC Misses | 41H | 2EH
- H
ist für hex. Alle 7 sind in der Struktur plus [PERF_COUNT_HW_REF_CPU_CYCLES] = 0x0300, /* pseudo-encoding *
. (Die Benennung ist etwas anders, die Adressen sind gleich.)
Dann sind die Hardware cache event
s in Strukturen wie (in derselben Datei):
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] =
{...}
- Was sollte für Sandbrücke sein?
Eine davon - snb_hw_cache_extra_regs[LL][OP_WRITE][RESULT_ACCESS]
ist gefüllt mit SNB_DMND_WRITE|SNB_L3_ACCESS
, wo aus den obigen Defs:
#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)
Das sollte gleich sein 0x00010102
, aber ich weiß nicht, wie ich es mit einer Tabelle überprüfen soll.
Und dies gibt eine Vorstellung davon, wie es verwendet wird in 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));
$
Die memcpy
s sind erledigt in __init int intel_pmu_init(void) {... case:...}
.
Nur attr->config1
ist ein bisschen seltsam. Aber es ist da, in perf_event_attr
(gleiche linux-source-3.13.0/include/uapi/linux/perf_event.h
Datei):
...
union {
__u64 bp_addr;
__u64 config1; /* extension of config */
};
union {
__u64 bp_len;
__u64 config2; /* extension of config1 */
};
...
Sie werden im Kernelsystem perf_events
mit Aufrufen von int perf_pmu_register(struct pmu *pmu, const char *name, int type)
(definiert in linux-source-3.13.0/kernel/events/core.c:
) registriert :
static int __init init_hw_perf_events(void)
(Datei arch/x86/kernel/cpu/perf_event.c
) mit Anrufperf_pmu_register(&pmu, "cpu", PERF_TYPE_RAW);
static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu)
(Datei arch/x86/kernel/cpu/perf_event_intel_uncore.c
gibt es auch arch/x86/kernel/cpu/perf_event_amd_uncore.c
) mit Anrufret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
Schließlich kommen alle Ereignisse von der Hardware und alles ist in Ordnung. Aber hier könnte man bemerken: Warum haben wir LLC-loads
in perf list
und nicht ubox1 LLC-loads
, da dies HW-Ereignisse sind und sie tatsächlich von ubox
es kommen?
Das ist eine Sache des perf
Dienstprogramms und seiner perf_evsel
Struktur: Wenn Sie ein HW-Ereignis von Ihnen anfordern perf
, definieren Sie das Ereignis, von welchen Prozessoren Sie es möchten (Standard ist alles), und es richtet das perf_evsel
mit dem angeforderten Ereignis und den angeforderten Prozessoren ein, dann bei Aggregation summiert die Zähler aller Prozessoren in perf_evsel
(oder führt andere Statistiken mit ihnen durch).
Man kann es sehen in 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;
}
(Für das Dienstprogramm ist perf
ein "einzelner Zähler" also nicht einmal eine perf_event_attr
allgemeine Form, die sowohl für SW- als auch für HW-Ereignisse geeignet ist. Es ist ein Ereignis Ihrer Abfrage. Dieselben Ereignisse können von verschiedenen Geräten stammen und werden aggregiert .)
Auch ein Hinweis: struct perf_evsel
enthält nur 1 struct perf_evevent_attr
, hat aber auch ein Feld struct perf_evsel *leader;
- es ist verschachtelt. Es gibt eine Funktion von "(hierarchischen) Gruppen von Ereignissen" perf_events
, bei der Sie eine Reihe von Zählern zusammen versenden können, damit sie miteinander verglichen werden können und so weiter. Nicht sicher , wie es funktioniert mit unabhängigen Ereignissen aus kernel
, core
, ubox
. Aber diese Verschachtelung perf_evsel
ist es. Und auf diese Weise wird höchstwahrscheinlich perf
eine Abfrage mehrerer Ereignisse zusammen verwaltet.