Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Profile-Guided Optimization (PGO) verwendet Laufzeitdaten, damit der Compiler bessere Optimierungsentscheidungen treffen kann. Durch die Verwendung von Ausführungsprofildaten, die von repräsentativen Workloads gesammelt werden, ermöglicht PGO dem Compiler, intelligentere Entscheidungen zur Inlinierung, zum Codelayout und zur Trennung von Hot/Cold Code. Diese Entscheidungen können nicht allein aus statischer Analyse getroffen werden.
SPGO verfolgt einen anderen Ansatz. Anstatt Ihre Binärdatei zu instrumentieren und sie in synthetischen Schulungsszenarien auszuführen, verwendet SPGO Hardware Performance Counter Samplings, die aus Ihren tatsächlichen Release-Binärdateien gesammelt werden. Moderne Prozessoren bieten Hardware-Samplingfunktionen. Sie können diese Beispiele mit vernachlässigbarem Laufzeitaufwand sammeln, wodurch es praktisch ist, Laufzeitprofile direkt aus Produktionscode zu sammeln.
Da SPGO-Profile Bits anstelle von instrumentierten Builds freigeben, ist es wesentlich flexibler, wo und wie Sie Daten sammeln. Sie können Laufzeitprofile von Produktionsservern, Entwicklercomputern, Leistungslabors oder einer beliebigen Kombination sammeln. Das Ergebnis ist eine Binärdatei, die hot paths effizienter ausführt, mit einer typischen Leistungsgeschwindigkeit von 5-15% abhängig von der Qualität der Profildaten.
In diesem Lernprogramm werden Sie durch den vollständigen SPGO-Workflow geführt: Erstellen Sie eine Beispiel-App, profilieren Sie sie mithilfe xperf, bereiten Sie die Profildaten vor und erstellen Sie sie mit den Profildaten neu. Wenn Sie fertig sind, können Sie denselben Prozess auf Ihre eigenen Projekte anwenden.
Voraussetzungen
Bevor Sie beginnen, stellen Sie sicher, dass Sie über die folgende Software und Hardware verfügen.
Software
- MSVC-Buildtools für x64/x86/ARM64 v14.51 oder höher – Installieren Sie sie über den Visual Studio Installer. Suchen Sie unter "Einzelne Komponenten" nach "MSVC-Buildtools".
-
Windows Performance Toolkit (xperf.exe) – Der
xperfProfiler sammelt Beispieldaten während der Ausführung Ihres Programms. Laden Sie das Windows Assessment and Deployment Kit (ADK) von ADK install herunter. Wenn Sie das ADK-Installationsprogramm ausführen, wählen Sie die Komponente Windows Performance Toolkit aus, umxperfabzurufen. Sie müssen das vollständige ADK nicht installieren. - Kriegs- und Friedenstextdatei – Wird als Beispielarbeitsauslastung verwendet, um Profilerstellungsdaten zu generieren. Laden Sie es von Project Gutenberg herunter: https://www.gutenberg.org/ebooks/2600. Speichern Sie sie als Nur-Text-Datei in Ihrem Arbeitsverzeichnis.
Hardwareanforderungen
Das Lernprogramm enthält drei Profilerstellungspfade. Welcher Pfad Sie verwenden, hängt von Ihrer Hardware ab. Sie führen Erkennungsbefehle in "Auswählen Ihrer Profilerstellungsmethode " aus, um herauszufinden, welchen Pfad Ihr Computer unterstützt. Verwenden Sie jetzt diese Tabelle, um zu bestätigen, dass Sie mindestens eine der Anforderungen erfüllen.
| Path | CPU-Anforderung | Hinweise |
|---|---|---|
| LBR (beste Ergebnisse) | Last Branch Records (LBR) sind Leistungsindikatoren, die auf Intel Haswell-CPUs (4. Generation Core, 2013) oder höher bereitgestellt werden; AMD Zen 4 (2022) oder höher, ARM64 ARMv9.2-A (2020) oder höher | Liefert die besten Branch-Daten. Weitere Informationen zu LBR finden Sie unter Einführung in Last Branch Records |
| PMC/IP-Modus (gute Ergebnisse) | Leistungsüberwachungsindikatoren (Performance Monitoring Counters, PMC) werden auf jeder x64-CPU mit einer Leistungsüberwachungseinheit (Performance Monitoring Unit, PMU) unterstützt. | Funktioniert auf den meisten modernen CPUs, bei denen LBR nicht verfügbar ist. Weitere Informationen zu PMC finden Sie unter PMU-Ereignisse (Recording Hardware Performance) und PmU-Ereignisse (Recording Hardware Performance) mit vollständigen Beispielen |
| Betriebssystemzeitgeber (funktioniert überall) | Beliebige x64- oder ARM64-CPU, einschließlich Azure VMs und virtuellen Computern | Beispiele mit geringerer Genauigkeit, aber immer verfügbar |
Die meisten Entwickler auf moderner x64-Desktophardware unterstützen LBR. VMs und einige ältere Hardware verfügen über PMC oder einen Betriebssystemtimer.
Funktionsweise von SPGO
SPGO sammelt Profildaten aus der ausgeführten Binärdatei und leitet sie beim nächsten Build wieder in den Compiler ein. Der Compiler verwendet diese Daten, um bessere Entscheidungen zu Inlining, Codelayout und Verzweigungsvorhersage zu treffen. Ein Komfort besteht darin, dass keine Instrumentierung erforderlich ist.
Der Workflow lautet:
- Erstellen Sie Ihre Binärdatei mit dem /spgo-Linker-Flag. In diesem Schritt wird eine leere Beispielprofildatenbank (
.spdDatei) erstellt. - Erstellen Sie mithilfe von
xperfein Profil der Binärdatei, um eine ETL-Trace-Datei zu erzeugen. - Konvertieren Sie die ETL-Datei mithilfe von
SPTAggregate.exein eine SPT-Datei, und konvertieren Sie dann die SPT-Datei mithilfe vonSPDConvert.exein eine SPD-Datei. - Erstellen Sie mit dem Linker-Flag /spdin erneut, das auf die gefüllte Beispielprofildatenbank (SPD) verweist. Der Linker wendet SPGO-Optimierungen an.
Der Optimierer verwendet die SPD, um Fragen wie die folgende zu beantworten: Welche Zweige werden am häufigsten durchlaufen? Welche Funktionen werden in Hot Loops aufgerufen? Dieser Prozess liefert ein besseres Code-Layout und bessere Inlining-Entscheidungen als die statische Analyse allein.
SPGO funktioniert sowohl mit C als auch mit C++. Der Workflow und die Flags sind für beide Sprachen identisch.
Beste Kandidaten für SPGO: Große, verzweigte C/C++-Anwendungen mit engen inneren Schleifen. Die Vorteile steigen mit der Größe der Codebasis und der Komplexität der Branches. Das kleine Beispiel in diesem Lernprogramm zeigt rund 7% Verbesserung. Größere Produktionscodebasen sehen häufig mehr Verbesserung.
Vergleich von Build-Prozessen
In diesem Abschnitt wird erläutert, wie SPGO in die Build-Pipeline passt, wenn Sie die Funktionsweise verstehen möchten.
Normaler Buildprozess
In einem Standard-C/C++-Release-Build:
-
Eingänge: Quellcodedateien (
.cpp,.h) und Compilerflags für den Releasemodus (/O2,/GLusw.). - Prozess: Der Compiler wendet Standardoptimierungen an, z. B. Inlining heuristiken, Verzweigungsvorhersagen und Codelayoutentscheidungen basierend auf statischer Analyse allein. Es gibt keine Daten darüber, wie sich das Programm tatsächlich verhält, wenn es ausgeführt wird.
-
Ausgabe: Ausführbare Dateien (), DLL-Dateien (
.exe.dll), Debuginformationen (.pdb).
Ohne Laufzeitdaten erhalten heiße Pfade und kalte Pfade eine ähnliche Behandlung.
SPGO-aktivierter Build-Prozess
SPGO fügt Profilingdaten als neue Eingabe für die Buildpipeline hinzu:
-
Eingänge: Quellcode, die
.spdProfildatei (Beispielanzahlen aus einer Profilerstellungsausführung), Compilerflags für den Releasemodus und/link /spgo/spdin:<path>zum Angeben einer SPD-Eingabedatei (sofern nicht angegeben, wird standardmäßig eine SPD-Datei mit dem binären Namen verwendet und befindet sich im Obj-Ordner). - Prozess: Der Linker liest die SPD zusammen mit dem Zwischencode vor. Es verwendet Verzweigungsfrequenzdaten, um bessere Entscheidungen über Inlining, das Code-Layout und die Anordnung von Verzweigungen zu treffen. Heiße Funktionen sind für den schnellen Zugriff ausgelegt; Kaltcode verschiebt sich aus dem kritischen Pfad.
-
Ausgabe: Optimierte ausführbare Datei (), optimierte DLL-Dateien (
.exe.dll), Debuginformationen (.pdb) und eine neue.spdDatei für zukünftige Profilerstellungsiterationen.
Die wichtigsten Erkenntnisse: SPGO verschiebt Optimierungsentscheidungen von Compiler- und Linker heuristiken zu datengesteuerten Entscheidungen basierend auf der realen Ausführung.
Wichtige Flags
| Flag | Typ | Purpose |
|---|---|---|
/spgo |
Linker | Aktiviert SPGO. Bettet SPGO-Metadaten in die Binärdatei ein und erstellt eine leere .spd-Ausgabedatei, es sei denn, /spdin wird angegeben; in diesem Fall wird die angegebene .spd-Datei als Eingabe verwendet. |
/spdin:<path> |
Linker | Eingabe-SPD – stellt dem Linker Profildaten zur Optimierung bereit. |
/spd:<path> |
Linker | Ausgabe-SPD-Pfad - gibt an, wo die neue SPD geschrieben wird (optional; Standardwert ist dasselbe Verzeichnis wie die Binärdatei). Dient als Eingabe-SPD-Pfad, falls /spdin nicht angegeben ist. |
/GL |
Compiler | Für SPGO ist eine Gesamtprogrammoptimierung erforderlich, um über Übersetzungseinheiten hinweg zu funktionieren. |
/O1, /O2 (Minimieren der Größe, Maximieren der Geschwindigkeit) |
Compiler | Für Geschwindigkeit optimieren; aktiviert aggressive Optimierungen, die SPGO verbessern kann |
Wie sich SPGO von PGO unterscheidet
PGO (profilgesteuerte Optimierung) erfordert, dass Sie Ihre Binärdatei mit Instrumentierungs-Flags kompilieren (/GENPROFILE), die langsamere instrumentierte Binärdatei ausführen, um Dateien mit Ausführungszählern (.pgc) zu erfassen, und sie anschließend mit /USEPROFILE neu linken. Der Compiler ruft genaue Ausführungsanzahlen ab, Sie müssen den Code jedoch zuerst instrumentieren. Weitere Informationen zu diesem Prozess finden Sie unter Profilgeführte Optimierungen.
SPGO verwendet Hardware-Leistungszähler der CPU zur Erfassung statistischer Samples aus Ihrer nicht instrumentierten Releasebinärdatei. Führen Sie Ihre vorhandene Binärdatei aus, profilieren Sie sie mithilfe von xperf, konvertieren Sie die Ablaufverfolgung in eine SPD-Datei, und erstellen Sie sie neu. Es gibt keinen instrumentierten Build und keine Verlangsamung während der Profilerstellung. Der Compiler ruft statistische Samplingdaten anstelle exakter Zählungen ab, was weniger präzise, aber einfacher zu erhalten ist und keine Codeänderungen erfordert. Es ermöglicht auch das Profiling von Systemkomponenten oder Echtzeitkomponenten, für die sich mit einem instrumentierten Ansatz nur schwer Daten erfassen lassen. Sie können auch Binärdateien für den endgültigen/Versand profilieren.
In diesem Lernprogramm werden drei Profilerstellungsmethoden behandelt: LBR, PMC und Betriebssystemtimer. Sie wählen Ihre Methode unter Profiling-Methode auswählen aus. Einen detaillierten Vergleich des normalen Buildprozesses mit dem SPGO-Buildprozess, einschließlich einer Referenztabelle für Flags, finden Sie unter Vergleich der Buildprozesse.
perfcore.ini konfigurieren
⚠– Erforderlich: Ohne diesen Schritt
xperfwerden die erforderlichen Profilerstellungsdaten nicht bereitgestellt. Führen Sie diesen Schritt aus, bevor Siexperfausführen.
Das Windows Performance Toolkit (WPT) verwendet perfcore.ini, das sich dort befindet, wenn Sie WPT am Standardspeicherort unter C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\perfcore.ini installiert haben, um die für SPGO benötigten DLL-Provider zu registrieren.
Öffnen Sie den Windows-Editor als Administrator. Öffnen Sie dann perfcore.ini. Suchen Sie den DLL-Listenabschnitt, und fügen Sie die folgenden Einträge pro Zeile hinzu:
perf_spt.dll
perf_lbr.dll
Wenn xperf.exe nicht installiert ist, lesen Sie Allgemeine Probleme, um es zu installieren.
Speichern Sie und schließen Sie perfcore.ini. Die DLL-Dateien werden bereits im selben Verzeichnis ausgeliefert, xperf.exe sodass Sie sie nicht überall kopieren müssen. Sie registrieren sie nur in perfcore.ini. Stellen Sie sicher, dass sich xperf in Ihrem Pfad befindet.
Erstellen der Beispiel-App
Die Beispiel-App für dieses Lernprogramm ist ein C++-Programm, das Text aus der Standardeingabe liest und eine Zeilenanzahl, Wortanzahl, Gesamtzeichenanzahl, eine Zeichenhäufigkeitstabelle und verstrichene Zeit zum Verarbeiten der Datei in Millisekunden erzeugt. Es ist in C++ geschrieben, aber SPGO funktioniert auch mit C. Der Workflow ist für C-Projekte identisch.
Erstellen Sie eine Datei namens textCount.cpp in Ihrem Arbeitsverzeichnis, und fügen Sie den folgenden Quellcode hinzu:
// textCount.cpp : Text Statistics Counter
// Counts words, lines, and character frequencies from standard input
// Usage: textCount < file.txt
#include <iostream>
#include <string>
#include <map>
#include <cctype>
#include <chrono>
int main()
{
auto start = std::chrono::steady_clock::now();
std::map<unsigned char, int> charFrequency;
int wordCount = 0;
int lineCount = 0;
int totalChars = 0;
std::string line;
bool inWord = false;
while (std::getline(std::cin, line))
{
lineCount++;
for (char c : line)
{
totalChars++;
unsigned char uc = static_cast<unsigned char>(c);
charFrequency[uc]++;
if (std::isspace(static_cast<unsigned char>(c)))
{
inWord = false;
}
else
{
if (!inWord)
{
wordCount++;
inWord = true;
}
}
}
inWord = false;
}
std::cout << "\n=== TEXT STATISTICS ===" << std::endl;
std::cout << "Lines: " << lineCount << std::endl;
std::cout << "Words: " << wordCount << std::endl;
std::cout << "Total Characters: " << totalChars << std::endl;
std::cout << "\n=== CHARACTER FREQUENCIES ===" << std::endl;
std::cout << "\nLetters:" << std::endl;
for (unsigned char ch = 'a'; ch <= 'z'; ch++)
{
unsigned char upperCh = static_cast<unsigned char>(std::toupper(ch));
int count = charFrequency[ch] + charFrequency[upperCh];
if (count > 0)
{
std::cout << static_cast<char>(ch) << ": " << count << std::endl;
}
}
std::cout << "\nDigits:" << std::endl;
for (unsigned char ch = '0'; ch <= '9'; ch++)
{
if (charFrequency[ch] > 0)
{
std::cout << static_cast<char>(ch) << ": " << charFrequency[ch] << std::endl;
}
}
std::cout << "\nSpecial Characters:" << std::endl;
for (const auto& pair : charFrequency)
{
unsigned char ch = pair.first;
if (!std::isalnum(ch))
{
std::string displayChar;
switch (ch)
{
case ' ': displayChar = "[space]"; break;
case '\t': displayChar = "[tab]"; break;
case '\n': displayChar = "[newline]"; break;
case '\r': displayChar = "[return]"; break;
default:
if (ch >= 32 && ch < 127)
{
displayChar = std::string(1, static_cast<char>(ch));
}
else
{
displayChar = "[byte:" + std::to_string(static_cast<int>(ch)) + "]";
}
break;
}
std::cout << displayChar << ": " << pair.second << std::endl;
}
}
auto end = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration<double, std::milli>(end - start);
std::cout << "Elapsed time: " << std::fixed;
std::cout.precision(3);
std::cout << elapsed.count() << " ms\n";
return 0;
}
Erstellen und führen Sie das Beispiel aus, um eine Baseline zu erhalten
Erstellen Sie vor dem Anwenden von SPGO textCount und führen Sie sie für eine große Textdatei aus, z. B. War and Peace (Sie können es aus Project Gutenberg herunterladen), um zu sehen, wie schnell es ausgeführt wird. In diesem Schritt wird die Leistung gezeigt, bevor Sie sie mithilfe von SPGO optimieren:
Build:
cl /EHsc /GL /O2 textCount.cpp
Ausführen:
textCount.exe < warAndPeace.txt
Es wird eine ähnliche Ausgabe angezeigt wie:
=== TEXT STATISTICS ===
Lines: 66041
Words: 566333
Total Characters: 3227531
=== CHARACTER FREQUENCIES ===
Letters:
a: 202719
...
Elapsed time: 512.000 ms
Notieren Sie sich den Wert Elapsed time. Sie vergleichen sie mit der SPGO-optimierten Zeit in "Messen der Ergebnisse".
TextCount mit /spgo erstellen
Erstellen Sie jetzt textCount mit aktivierter SPGO. Dieser Schritt legt die Grundlage für die Erfassung von Profilerstellungsdaten.
cl /EHsc /GL /O2 textCount.cpp /link /debug /spgo
Nach Abschluss des Builds wird eine Meldung wie folgt angezeigt:
SPD textCount.spd not found, compiling without profile guided optimizations
Diese Meldung wird im ersten /spgo Build angezeigt. Der Linker erstellt die SPD-Datei, ist aber noch leer, sodass noch keine SPGO-Optimierungen angewendet werden. Nachdem Sie die Binärdatei ausgeführt, Profildaten gesammelt und in SPD konvertiert haben, wird diese Meldung nicht angezeigt.
Erläuterungen zur Kennzeichnung:
| Flag | Purpose |
|---|---|
/EHsc |
Aktivieren der C++-Ausnahmebehandlung |
/GL |
Optimierung des gesamten Programms – erforderlich für SPGO. Verzögert die endgültige Optimierung der Verknüpfungszeit, wodurch modulübergreifende Inlining-, Codelayout- und Totcode-Eliminierungsentscheidungen ermöglicht werden. |
/O2 |
Für Geschwindigkeit optimieren – ermöglicht aggressives Inlining, Schleifenoptimierung, die Entfernung toten Codes und verwandte Transformationen. |
/link /debug |
Übergeben Sie dem Linker /debug, um Debuginformationen zu generieren (.pdb), die xperf verwendet, um Profilingstichproben dem Quellcode zuzuordnen. |
/spgo |
SPGO-Linker-Flag – bettet SPGO-Metadaten in die Binärdatei ein und erstellt neben der ausführbaren Datei eine leere textCount.spd Datei. |
Note
/spgo ist ein Linker-Flag. Übergeben Sie ihn über den /link /spgo Befehl an den Linkercl.
Das /spgo Flag optimiert die Binärdatei noch nicht. Dadurch wird es für das Profiling vorbereitet. Die Optimierung erfolgt in Rebuild textCount with /spdin, nachdem die SPD mit echten Laufzeitdaten befüllt wurde.
Note
Um die SPD an einen bestimmten Speicherort zu schreiben, fügen Sie das optionale /spd:<path> Linker-Flag hinzu. Beispiel: /link /debug /spgo /spd:.\profiles\textCount.spd. Wenn Sie dieses Flag weglassen, wird die SPD zusammen mit dem .exe erstellt.
Auswählen Ihrer Profilerstellungsmethode
SPGO unterstützt drei Profilerstellungsmethoden. Welche Methode Sie verwenden, hängt von Ihrer Hardware ab.
Die drei Profilerstellungsmethoden
| Methode | Musterqualität | Hardwareanforderung | Am besten geeignet für: |
|---|---|---|---|
| LBR (Last Branch Record) | Höchste Anzahl – Zeichnet Sequenzen kürzlich aufgenommener Verzweigungen auf, sodass der Optimierer umfangreiche Steuerungsflussdaten pro Stichprobe erhält. | Intel Haswell (2013) oder höher; AMD Zen 4 (2022) oder höher; ARM64 ARMv9.2-A (2020) oder höher | Modernste Desktophardware |
| PMC/IP-Modus (Leistungsüberwachungszähler/Anweisungszeigermodus) | Gut. Erfasst Stichproben des Befehlszeigers mit Aufrufstapeln unter Verwendung der Performance Monitoring Unit (PMU) der CPU, die über Event Tracing for Windows (ETW) erfasst werden. | Jede x64- oder ARM64-CPU mit einer PMU | Hardware ohne LBR-Unterstützung |
| Betriebssystemtimer | Einfach – timerbasierte Abtastwerte | Beliebige x64- oder ARM64-CPU, VMs ohne PMU-Passthrough | VMs und ältere Hardware |
Im PMC/IP-Modus erhalten Sie bei jedem Hardware-Interrupt nur einen Datenpunkt: "Die CPU war an adresse 0x1A2B3C4D, wenn der Interrupt ausgelöst wurde". Mit LBR erhalten Sie bei jedem Interrupt den Verlauf der letzten 16 bis 32 Verzweigungen, die die CPU vor dem Auslösen des Interrupts genommen hat. Der Optimierer erhält bessere Kontrollflussdaten und kann bessere Inlining- und Layout-Entscheidungen treffen.
Erkennen Des Pfads
Führen Sie die folgenden beiden Befehle aus, um zu bestimmen, welchen Profilerstellungspfad Ihr Computer unterstützt. Für diese Befehle ist keine Eingabeaufforderung mit erhöhten Rechten erforderlich.
Schritt 1: Überprüfen Sie die LBR-Unterstützung. Dieser Test funktioniert auf Intel/AMD/ARM64.
Führen Sie folgendes aus einer administrator Visual Studio Entwickler-Eingabeaufforderung aus:
xperf.exe -on PMC_PROFILE -pmcprofile TotalIssues -LastBranch PmcInterrupt -setProfInt TotalIssues 2560000
xperf -stop -d lbrtest.etl
xperf -tle -i lbrtest.etl -a dumper | findstr "LBR, TimeStamp"
- Wenn dieser Befehl eine Zeile findet, die
LBR, TimeStampenthält, unterstützt Ihr System LBR. Verwenden Sie den LBR-Pfad. - Fahren Sie andernfalls mit Schritt 2 fort.
Schritt 2: Überprüfen der PMC-Unterstützung (kein LBR)
xperf.exe -pmcsources | findstr TotalIssues
- Wenn dieser Befehl die Ausgabe erzeugt, unterstützt Ihr Computer PMC-Zähler, aber nicht LBR. Verwenden Sie den PMC-Pfad.
- Wenn dieser Befehl keine Ausgabe erzeugt, verwenden Sie den Betriebssystemzeitgeberpfad.
Weitere Informationen zur PMU-Ereignissammlung mit xperf finden Sie unter Aufzeichnen von Hardware-PMU-Ereignissen mit xperf.
Entscheidungstabelle
LBR, TimeStamp Ausgabe |
TotalIssues-Ausgabe |
Ihr Pfad |
|---|---|---|
| Nicht leer | (nicht aktiviert) | LBR |
| Leer | Nicht leer | PMC |
| Leer | Leer | Betriebssystemtimer |
| ARM64-Prozessor | N/A | PMC (sofern PMU verfügbar) oder Betriebssystemtimer |
Wählen Sie Ihren Ansatz aus.
Entscheiden Sie anhand der Erkennungsergebnisse, ob der LBR-, PMC- oder OS-Timerpfad verwendet werden soll. Jeder Pfad hat unterschiedliche xperf Startparameter, um die entsprechenden Profilerstellungsdaten zu sammeln. Folgen Sie dem Pfad, der Ihren Hardwarefunktionen entspricht.
Ihr Pfad:
- LBR-Nutzer (LBR in Schritt 1 erkannt): Gehen Sie zu LBR-Pfad.
- PMC-Benutzer (InstructionRetired wurde in Schritt 2 erkannt): Wechseln Sie zum PMC-Pfad (kein LBR).
- Benutzer des Betriebssystemtimers (VM oder Hardware ohne PMU): Wechseln Sie zum Betriebssystemzeitgeberpfad.
Alle Pfade laufen bei Führen Sie die Workload aus und beenden Sie xperf wieder zusammen.
Die Befehle in diesem Abschnitt hängen vom Profilerstellungspfad ab, den Sie in "Profilerstellungsmethode auswählen" identifiziert haben. Suchen Sie den Unterabschnitt, der Ihrem Pfad entspricht, führen Sie den xperf start-Befehl aus, und fahren Sie dann mit Workload ausführen und xperf beenden fort, um die Workload auszuführen und xperf zu beenden.
⚠️ Als Administrator ausführen:
xperferfordert eine Entwickler-Eingabeaufforderung mit erhöhten Rechten (Administrator). Ohne Erhöhung wirdxperfzurückgegeben"failed to configure counters".
LBR-Pfad
Starten Sie xperf mit der LBR-Kollektion:
xperf -on LOADER+PROC_THREAD+PMC_PROFILE -MinBuffers 4096 -MaxBuffers 4096 -BufferSize 4096 -pmcprofile BranchInstructionRetired -LastBranch PmcInterrupt -setProfInt BranchInstructionRetired 16384
Parametererklärung:
| Parameter | Purpose |
|---|---|
LOADER+PROC_THREAD+PMC_PROFILE |
Kernanbieter: Loaderereignisse (Modulzuordnung), Prozess- und Threadereignisse (Ausführungskontext) und PMC-Profilierungsereignisse |
-MinBuffers 4096 -MaxBuffers 4096 -BufferSize 4096 |
Große Ringpuffer, um bei einem vollständigen War-and-Peace-Durchlauf keine Samples zu verlieren |
-pmcprofile BranchInstructionRetired |
PMC-Ereignistrigger: bei jeder N-ten abgeschlossenen Verzweigungsanweisung ein Sample erzeugen |
-LastBranch PmcInterrupt |
Ermöglicht die LBR-Hardwareaufzeichnung: Erfassen Sie auf jedem PMC-Interrupt den Hardware-Last-Branch-Datensatzstapel. |
-setProfInt BranchInstructionRetired 16384 |
Beispielintervall: Auslösen einer Unterbrechung alle 16.384 eingestellten Verzweigungsanweisungen |
Fahren Sie nach dem Starten von xperf mit der Ausführung der Workload fort, und beenden Sie xperf.
PMC-Pfad (kein LBR)
Starten Sie xperf mit der PMC/IP-Modus-Erfassung:
xperf -on LOADER+PROC_THREAD+PMC_PROFILE+PROFILE -MinBuffers 4096 -BufferSize 4096 -pmcprofile InstructionRetired -setProfInt InstructionRetired 16384 -stackwalk profile
Parametererklärung:
| Parameter | Purpose |
|---|---|
LOADER+PROC_THREAD+PMC_PROFILE+PROFILE |
Fügt PROFILE (CPU-Sampling) und PMC_PROFILE für PMC-Ereignisse hinzu; kein -LastBranch |
-pmcprofile InstructionRetired |
PMC-Ereignistrigger: Beispiel für zurückgezogene Anweisungen (Anweisungszeigermodus) |
-setProfInt InstructionRetired 16384 |
Einen Interrupt nach jeweils 16.384 abgeschlossenen Anweisungen auslösen |
-stackwalk profile |
Bei jeder Profiling-Unterbrechung einen Aufrufstapel erfassen und Aufrufkettendaten statt Verzweigungsfolgen bereitstellen |
Im Vergleich zu LBR: keine -LastBranch Kennzeichnung; verwendet InstructionRetired anstelle von BranchInstructionRetired. Das Ergebnis sind Anweisungszeigerbeispiele mit Aufrufstapeln, nicht Verzweigungssequenzen. Dieser Pfad bietet weiterhin effektive Daten für den Optimierer, aber es ist etwas weniger reich.
Fahren Sie nach dem Starten von xperf dann mit dem Ausführen der Workload und dem Beenden von xperf fort.
Betriebssystemzeitgeberpfad
Starten Sie xperf mit OS-Timer-basiertem Sampling:
xperf -on LOADER+PROC_THREAD+PROFILE -MinBuffers 4096 -BufferSize 4096 -setProfInt Timer 1221 -stackwalk profile
Parametererklärung:
| Parameter | Purpose |
|---|---|
LOADER+PROC_THREAD+PROFILE |
Keine PMC-Ereignisse; CPU-Sampling nur über den Timer-Interrupt des Betriebssystems |
-setProfInt Timer 1221 |
Bei jedem 1.221. Timer-Tick des Betriebssystem-Timerinterrupts auslösen (ca. 1 kHz) |
-stackwalk profile |
Einen Aufrufstapel bei jedem Timer-Interrupt erfassen |
Im Vergleich zu LBR und PMC verwendet diese Methode keine Hardwareleistungsindikatoren. Der Betriebssystemtimer wird unabhängig von der CPU-Aktivität in ungefähr festen Zeitintervallen ausgelöst. Beispiele sind weniger dicht mit heißem Code korreliert, bieten aber dennoch nützliche Steuerungsflussdaten für den Optimierer.
Führen Sie die Workload aus und beenden Sie xperf (alle Pfade)
Während xperf ausgeführt wird, führen Sie textCount mit Krieg und Frieden aus:
textCount.exe < warAndPeace.txt
Nachdem textCount abgeschlossen ist, beenden Sie xperf und schreiben Sie die Trace-Datei. Wenn andere Prozesse während der Profilerstellung ausgeführt werden, wird die Probenqualität verwässert. Um optimale Ergebnisse zu erzielen, schließen Sie unnötige Anwendungen, bevor Sie die Workload ausführen.
xperf -stop -d textCount.etl
Nachdem xperf beendet wurde (das Erstellen der ETL-Datei kann eine Weile dauern), vergewissern Sie sich, dass textCount.etl im aktuellen Verzeichnis erstellt wurde.
Konvertieren der ETL-Datei in SPT
Dieser Schritt ist für alle drei Profilerstellungspfade identisch.
Führen Sie die Ausführung SPTAggregate.exe aus, um die unformatierte ETL-Ablaufverfolgung zu verarbeiten und eine SPT-Profildatei zu erstellen:
SPTAggregate.exe /binary textCount.exe /etl textCount.etl textCount.spt
Parametererklärung:
| Parameter | Purpose |
|---|---|
/binary textCount.exe |
Die Binärdatei, aus der Stichproben extrahiert werden sollen. Das ETL kann Beispiele aus allen Prozessen enthalten, die während der Profilerstellung ausgeführt wurden. |
/etl textCount.etl |
Eingabe-ETL-Ablaufverfolgungsdatei |
textCount.spt |
SPT-Profildatei ausgeben |
SPTAggregate gibt eine Zusammenfassung aus, die zeigt, wie viele Beispiele sie gesammelt haben. Diese Zusammenfassung ist Ihre erste Bestätigung, dass die Profilerstellung funktioniert hat.
Vergleichen Sie die Ausgabe von SPTAggregate mit dem Pfad, den Sie genommen haben:
- LBR-Pfad: Achten Sie auf eine Anzahl verwendeter LBR-Samples ungleich null.
- PMC-Pfad: Suchen Sie nach einer Nichtzero-PMC- oder Stapelbeispielanzahl.
- OS-Timer-Pfad: Suchen Sie nach einer Anzahl verwendeter Stack-Samples, die ungleich null ist.
Wenn alle Zählungen null sind, lesen Sie die Problembehandlung , bevor Sie fortfahren.
Konvertieren der SPT-Datei in SPD
Ihr Pfad:
- LBR-Benutzer (verwenden Sie
/mode:LBR): LBR-Modus- PMC-Nutzer (mit
/mode:IP): IP-Modus (PMC- und Betriebssystemtimer)- Benutzer des Betriebssystemtimers (Verwendung
/mode:IP): IP-Modus (PMC- und Betriebssystemtimer)Sowohl PMC- als auch OS-Timerpfade verwenden
/mode:IP, da beide Instruction-Pointer-Samples erzeugen.
Der nächste Schritt verzweigt je nach Profilierungspfad, insbesondere abhängig vom Flag /mode, das an SPDConvert.exe übergeben wird.
LBR-Modus
SPDConvert.exe /mode:LBR textCount.spd textCount.spt
/mode:LBR weist SPDConvert an, den SPT so zu interpretieren, dass er LBR-Verzweigungssequenzdaten enthält.
IP-Modus (PMC- und Betriebssystemtimer)
Sowohl PMC als auch OS-Timer erzeugen Instruction-Pointer-Samples, daher verwenden beide denselben Konvertierungsbefehl:
SPDConvert.exe /mode:IP textCount.spd textCount.spt
/mode:IP weist SPDConvert an, den SPT so zu interpretieren, dass er Instruction-Pointer-Samples enthält.
Warnung
Wenn Sie den falschen Modus für Ihren Datentyp verwenden, kann ein leerer oder falsch formatierter SPD-Code erzeugt werden. Wenn Sie mit LBR profiliert haben, verwenden Sie /mode:LBR.
Wenn Sie mit PMC oder dem OS-Timer profiliert haben, verwenden Sie /mode:IP. Die SPTAggregate Zusammenfassungsausgabe aus ETL-Datei in SPT konvertieren zeigt, welche Stichprobentypen erfasst wurden, und bestätigt, welcher Modus verwendet werden soll.
Vergewissern Sie sich nach der Ausführung SPDConvert, dass textCount.spd im aktuellen Verzeichnis erstellt (oder aktualisiert) wurde.
Interpretieren der SPDConvert-Ausgabe
Der Befehl SPDConvert textCount.spd textCount.spt druckt beispielsweise eine Zusammenfassung der Blockabdeckung vor und nachher:
Block coverage (before) : 33.90% ( 4507/ 13294)
Block coverage (after) : 45.64% ( 6067/ 13294)
Diese Zusammenfassung zeigt den Prozentsatz der Codeblöcke der Binärdatei mit zugeordneten Profildaten. Ein höherer Prozentsatz ist besser. Die Abdeckung über 70% ist hervorragend, während die Abdeckung unter 40% die Optimierungseffizienz einschränken kann. Wenn die Abdeckung gering ist, führen Sie den Profiling-Workload länger aus oder kombinieren Sie mehrere SPT-Dateien aus separaten Läufen mit unterschiedlichen Workloads. Sie könnten beispielsweise textCount mit mehreren Textdateien ausführen, um verschiedene Codepfade zu testen.
Möglicherweise wird Ihnen eine Warnung von SPDConvert wie die folgende angezeigt:
Compiler may be conservative on some hot functions due to sparse sample coverage.
SPGO is estimated to optimize better if sample density is increased to 5.4x of current level.
Sample density can be increased by sampling for longer period, or increasing sample rate.
Diese Warnung bedeutet, dass Ihr Profiling-Durchlauf nicht genügend Samples erfasst hat, damit der Optimierer alle leistungskritischen Funktionen mit ausreichender Sicherheit optimieren kann. Die SPD ist weiterhin verwendbar, aber Sie können die Ergebnisse verbessern, indem Sie:
- Die Workload länger ausführen (z. B. 5 oder mehr Minuten statt 1 Minute) oder andere Workloads verwenden.
- Verringern des
-setProfIntWerts imxperfBefehl, um die Samplingrate zu erhöhen. Der Kompromiss besteht darin, dass diese Änderung eine größere ETL-Datei erzeugt, die längere Verarbeitung dauert. - Das Kombinieren mehrerer SPT-Dateien aus getrennten Profilerstellungsläufen durch Übergeben aller Dateien an
SPDConvert.
Die SPT-Datei ist ein Binärformat. Um den Inhalt zu prüfen, können Sie ausführen SPTDump.exe textCount.spt. Ebenso zeigt PTDump.exe textCount.spt die kompilierten Profildaten nach dem Ausführen von SPDConvert an. Beide Tools sind nützlich, um Nichtzerobeispiele zu überprüfen, bevor Sie fortfahren.
TextCount mit /spdin neu erstellen
Erstellen Sie textCount neu, indem Sie die ausgefüllte SPD-Datei verwenden. Der Linker liest die Profildaten und wendet SPGO-Optimierungen an.
Dieser Schritt ist für alle drei Profilerstellungspfade identisch.
cl /EHsc /GL /O2 textCount.cpp /link /debug /spgo /spdin:textCount.spd
Neues Flag (im Vergleich zu Build textCount mit /spgo):
| Flag | Purpose |
|---|---|
/spdin:textCount.spd |
Die SPD-Profildaten dem Linker zur Optimierung übergeben |
Der Befehl enthält weiterhin /spgo. Es generiert eine neue SPD-Datei zusammen mit der optimierten Binärdatei, die Sie als Ausgangspunkt für nachfolgende Profilerstellungs-Iterationen verwenden können.
Warnung
Die SPD-Datei ist mit der exakten Binärdatei verknüpft, die sie profiliert. Wenn Sie textCount ohne /spdin neu erstellen oder aus geändertem Quellcode neu erstellen, müssen Sie eine neue SPD-Datei erstellen. Das vorhandene Objekt stimmt nicht mit der GUID der neuen Binärdatei überein, und der Linker wird es nicht verwenden.
Nach dem erneuten Erstellen mit /spdin gibt der Linker Statistiken dazu aus, wie viel Ihres Codes mithilfe von Profildaten optimiert wurde. Beispiel:
221 of 221 (100.00%) profiled functions will be compiled for speed
201 of 1383 inline instances were from dead/cold paths
474 of 474 profiled functions (100.0%) were optimized using profile data
202738780 of 202738780 instructions (100.0%) were optimized using profile data
Ein hoher Prozentsatz bedeutet, dass die SPD Ihre Binärdatei gut abdeckt. Wenn der Prozentsatz niedrig ist (z. B. unter 90 %), hat entweder die Profiling-Workload nicht genügend Teile der Binärdatei abgedeckt, oder die Binärdatei hat sich erheblich verändert, seit das Profil erstellt wurde. Profilieren Sie in beiden Fällen neu gegen die aktuelle Binärdatei.
Funktionsweise von SPGO mit Ihren Profildaten
SPGO verwendet die gesammelten Beispieldaten, um die Anzahl der einzelnen Bausteine und Kanten im Steuerungsflussdiagramm des Programms aufzufüllen. Diese Werte ermöglichen Optimierungen wie z. B.:
- Profilgesteuertes Inlining: Hot-Callsites aggressiv inlinen, wobei eine Code-Aufblähung durch das Inlining kalter Pfade vermieden wird.
- Hot/Cold Code Separation: Verschieben Sie selten ausgeführten Code, um Abschnitte der Binärdatei zu trennen, um die Verwendung des Anweisungscaches und das Pagingverhalten zu verbessern.
- Funktionslayout: Platzieren Sie Funktionen, die sich häufig gegenseitig aufrufen, nahe beieinander in der Binärdatei, um Seitenfehler zu reduzieren und die Lokalität zu verbessern. Optimierte Funktionen sind in COFF-Gruppen mit hoher Affinität in der Binärdatei organisiert.
- Größen-/Geschwindigkeitsentscheidungen: Kompilieren sie heiße Funktionen für Geschwindigkeits- und Kältefunktionen für größe. Routinen ohne beobachtete Treffer im Profil werden möglicherweise eher auf geringe Codegröße als auf Geschwindigkeit optimiert, wodurch Optimierungen wie Inlining und Schleifenentfaltung in diesen kalten Codepfaden eingeschränkt werden.
- Spekulative Devirtualisierung: Wenn samplings erkennen, dass ein indirekter Aufruf konsistent auf dieselbe Funktion ausgerichtet ist, kann SPGO auf dieses Ziel spekulieren und es inline mit einem Fallback für den ungewöhnlichen Fall angeben.
Messen der Ergebnisse
Führen Sie textCount erneut aus und vergleichen Sie die verstrichene Zeit.
textCount.exe < warAndPeace.txt
Führen Sie für jede Konfiguration mehrere Durchläufe durch und verwenden Sie den Median. Eine einzelne Ausführung ist nicht zuverlässig, da die Planung des Betriebssystems und Systemgeräusche einzelne Messungen verzerren können.
| Build | Repräsentative verstrichene Zeit |
|---|---|
Baseline (cl /EHsc /O2) |
(Ihre Messung) |
/spgo build (bisher keine Profildaten) |
(sollte nahe an der Basislinie liegen) |
SPGO-optimiert (/spdin) |
(sollte Verbesserung zeigen) |
In einem Test ergab SPGO bei Verwendung der LBR-Methode eine Reduzierung der Ausführungszeit um etwa 7 %. Ihre Ergebnisse können sich je nach Ihren eigenen Projekten unterscheiden, da SPGO-Gewinne davon abhängen, wie gut die Profilerstellungsauslastung die typische Ausführung darstellt. Größere, verzweigte Codebasen sehen in der Regel mehr Verbesserungen innerhalb des Bereichs von 5 bis 10%. Die Profilerstellungsmethode wirkt sich auf die Optimierungsqualität aus. LBR erzeugt in der Regel bessere Ergebnisse als PMC, was bessere Ergebnisse als der Betriebssystemzeitgeber erzeugt. Wenn Sie den Betriebssystem-Timer verwenden, rechnen Sie mit geringeren Leistungszuwächsen.
Der LBR-Pfad, gefolgt in diesem Lernprogramm, wurde auf das SQLite-Projekt angewendet, das eine Produktionsdatenbankbibliothek ist. Die SPGO-optimierte SQLite-Binärdatei zeigte ungefähr eine Verbesserung von 7%.
Anwenden von SPGO auf Ihr eigenes Projekt
Verwenden Sie diese Checkliste, um SPGO auf Ihre eigene C- oder C++-Anwendung anzuwenden.
Fügen Sie
/link /spgoIhrem vorhandenen Release-Build-Befehl hinzu. Ändern Sie das Buildskript oder die Projektdatei:cl /EHsc /GL /O2 myapp.cpp /link /spgoWählen Sie eine repräsentative Arbeitsauslastung aus. Wählen Sie ein echtes Nutzungsszenario aus, in dem die heißen Pfade Ihrer Anwendung ausgeführt werden. Verwenden Sie produktionsähnliche Daten. Vermeiden Sie Folgendes als primäre Workload für die Profilerstellung: Codeabdeckungstests (da sie Leistungsengpässe nicht ausreichend auslasten), ungewöhnliche Fehlerpfade, Start- und Herunterfahrphasen und veraltete Codepfade. Diese Workload bestimmt das Profil, das den Optimierer mit Daten versorgt.
Führen Sie xperf mit dem erkannten Pfad aus. Verwenden Sie die Methode, die Sie unter Ihre Profilerstellungsmethode auswählen (LBR, PMC oder OS-Timer) identifiziert haben. Starten Sie
xperf, führen Sie den Workload einmal aus, beenden Siexperf, und zeichnen Sie die ETL-Datei auf.Führen Sie für den PMC- oder OS-Timerpfad SPTAggregate und SPDConvert mit dem richtigen
/mode-Flag aus. Konvertieren Sie ETL zu SPT und anschließend zu SPD. Verwenden Sie/mode:LBRfür LBR-Daten; verwenden Sie/mode:IPfür PMC- oder OS-Timer-Daten.Neu erstellen mit
/spdin:<your-spd-path>. Kompilieren Sie Ihre Anwendung mit der ausgefüllten SPD:cl /EHsc /GL /O2 yourApp.cpp /link /spgo /spdin:yourApp.spdMessen Sie vor und nachher. Führen Sie Ihre Workload sowohl mit den nicht optimierten als auch mit SPGO-optimierten Binärdateien aus. Ermitteln Sie den Median mehrerer Läufe für jede Konfiguration. Ein einzelner Lauf ist für Benchmarking nicht zuverlässig.
Speichern Sie die
.spdDatei in der Versionsverwaltung. Checken Sie die Datei.spdzusammen mit Ihrem Quellcode in Ihr Versionsverwaltungssystem ein.Aktivieren Sie SPGO in Developer-Release-Builds. Lassen Sie die Releasebuilds Ihres Teams dieselben SPGO-optimierten Binärdateien wie die Produktion verwenden. Dies hilft, Leistungsregressionen frühzeitig abzufangen.
Deaktivieren Sie SPGO in Debugbuilds.
Sehen Sie sich die Statistiken zur Profilvollständigkeit des Verknüpfers an. Notieren Sie nach jedem Build den Prozentsatz der profilierten Funktionen, die mit
/spgoanhand von Profildaten optimiert wurden. Wenn dies erheblich abfällt (unter 90%), stellen Sie die aktuelle Binärdatei neu ein. Codeänderungen sammeln sich an, und die SPD kann veraltet werden.
Alternative zur Verwendung xperf
Eine weitere Möglichkeit zum Sammeln von Profildaten besteht darin, einen Sampling-Profiler wie Windows Performance Recorder (WPR) zu verwenden. WPR ist standardmäßig auf Windows 10 und höher installiert. Es sammelt ähnliche Daten wie xperf. Sie können WPR so konfigurieren, dass CPU-Beispiele mit Aufrufstapeln gesammelt werden, und dann die Daten in eine ETL-Datei exportieren, die Sie mit SPTAggregate und SPDConvert wie der xperf ETL verarbeiten können. Hier ist ein Beispiel für die Verwendung von WPR zum Sammeln von Profildaten:
wpr -start CPU.light -filemode
textCount.exe < warAndPeace.txt
wpr -stop spgo_data.etl
Weitere Informationen zur Verwendung von WPR finden Sie unter Using Windows Performance Recorder.
SPD-Verteilung
Sie haben folgende Möglichkeiten:
- Checken Sie die
.spdDatei direkt zusammen mit Ihrem Quellcode in die Versionsverwaltung ein. - Teilen Sie die
.spd-Datei mit Teammitgliedern, damit sie mit SPGO-Optimierungen erstellen können, ohne erneut profilieren zu müssen. - Packen Sie die
.spdDatei mit Ihren Binärdateien als Versionsartefakt (z. B. ein NuGet-Paket) und notieren Sie, welche Version der Binärdatei entspricht. - Generieren Sie die
.spdDatei jederzeit neu, indem Sie den Profilerstellungsworkflow wiederholen.
Die SPD ist an genau die Binärdatei gebunden, aus der sie erstellt wurde. Nachdem erhebliche Codeänderungen vorgenommen wurden, müssen Sie ein erneutes Profil erstellen, um eine neue SPD zu generieren. Während des /spdin Builds erzeugt der Compiler auch eine neue .spd Datei. Speichern Sie diese neue SPD als Build-Artefakt – sie ist der Ausgangspunkt für Ihre nächste Profiling-Iteration.
Erneutes Verwenden von SPD-Informationen über Builds hinweg
Das Konzept des „Fortschreibens“ in SPGO ermöglicht es Ihnen, Profiling-Daten zu einer vorhandenen SPD-Datei hinzuzufügen, ohne alle Ihre Szenarien erneut komplett von Grund auf zu profilieren und ohne vorhandene Profilinformationen zu verlieren. Sie können auch anpassen, wie viel Gewicht sie älteren Profildaten zuordnen soll. Diese Flexibilität ist nützlich, wenn verhaltensbedingte Änderungen im Laufe der Zeit vorliegen und Sie die Profilerstellungsinformationen aus früheren Szenarien nicht vollständig verlieren möchten. Eine DLL kann beispielsweise erleben, dass unterschiedliche APIs aufgerufen werden, während sich die Anwendung, die sie aufruft, weiterentwickelt. Sie möchten weiterhin von den Optimierungen profitieren, die sich aus dem früheren Verhalten ergeben haben, aber zugleich auch Optimierungsmöglichkeiten nutzen, die sich daraus ergeben, dass es sich jetzt manchmal anders verhält. Sie können das Profil im Laufe der Zeit weiterentwickeln, indem Sie alte und neue Daten mischen.
Wenn Sie SPDConvert mit einer neuen SPT-Datei ausführen, geben Sie den Namen der vorhandenen SPD-Datei an. Verwenden Sie dann die Option /retire:N, um zu steuern, wie stark SPDConvert ältere Profildaten weniger stark gewichtet, wenn Sie neue SPT-Dateien hinzufügen:
- Der Standardwert (
/retire:8) gewichtet neuere Daten stärker. - Wird verwendet
/retire:0, um allen Laufläufen die gleiche Gewichtung zu verleihen. - Verwenden Sie
/retire:16, damit nur die neuesten Daten zählen.
Problembehandlung
Finden Sie Ihr Problem:
- LBR-Pfadprobleme:LBR-Pfadprobleme
- PMC-Pfadprobleme:PMC-Pfadprobleme
- Probleme mit dem OS-Timer:Pfadprobleme des OS-Timers
- Probleme, die sich auf alle Pfade auswirken:Allgemeine Probleme
Probleme mit dem LBR-Pfad
| Das Problem | Wahrscheinliche Ursache | Reparatur |
|---|---|---|
Keine LBR-Proben in der SPTAggregate-Ausgabe |
CPU unterstützt LBR nicht, oder VM macht LBR nicht verfügbar. | Führen Sie den Erkennungsbefehl über " Pfad erkennen" aus. Wenn Sie eine Hyper-V-VM verwenden, führen Sie Set-VMProcessor MyVMName -Perfmon @("pmu", "lbr") auf dem Host aus. Wenn LBR nicht verfügbar ist, schalten Sie auf den PMC- oder OS-Timer-Pfad um. |
Der Prozessor unterstützt LBR, aber SPTAggregate zeigt 0 LBR-Proben an |
perfcore.ini DLL-Registrierung unvollständig |
Schließen Sie die perfcore.ini Einrichtung in Configure perfcore.ini ab. Stellen Sie sicher, dass perf_lbr.dll registriert ist. |
SPDConvert schlägt fehl oder erzeugt eine leere SPD |
Falsche /mode Kennzeichnung oder SPT enthält nur Beispiele für den IP-Modus. |
Bestätigen Sie, dass SPTAggregate die Ausgabe LBR-Proben zeigte. Wenn in der Ausgabe nur Beispiele für den IP-Modus angezeigt werden, wechseln Sie zu /mode:IP. |
PMC Pfadprobleme
| Das Problem | Wahrscheinliche Ursache | Reparatur |
|---|---|---|
Keine PMC-Proben in der Ausgabe SPTAggregate |
perfcore.ini DLL-Registrierung falsch |
Schließen Sie die perfcore.ini Einrichtung in Configure perfcore.ini ab. Stellen Sie sicher, dass perf_spt.dll registriert ist. Ohne diese DLL liefert xperf keine PMC-Samples, ohne eine Fehlermeldung auszugeben.Führen Sie die Ausführung xperf.exe -pmcsources aus, um die Liste der Leistungsindikatorenquellen anzuzeigen, die auf Ihrer CPU verfügbar sind. Wenn einträge wie SPT_OP_RETIRE_INSTR oder SPT_OP_RETIRE_BR_INSTRSPT_OP_ETW_INSTRnicht angezeigt werden, ist die DLL-Registrierung perfcore.ini möglicherweise unvollständig, oder Ihre CPU unterstützt möglicherweise PMC nicht. Wenn Sie die DLL-Registrierung nicht auflösen können, versuchen Sie es stattdessen mit dem Betriebssystem-Timerpfad. |
findstr InstructionRetired gibt Ausgabe zurück, erzeugt aber xperf keine Beispiele. |
VM maskieren PMC-Zähler | Überprüfen Sie, ob sie auf einem virtuellen Computer ausgeführt wird. Aktivieren Sie PMU in Hyper-V mit Set-VMProcessor, oder wechseln Sie zum Betriebssystemzeitgeberpfad. |
SPDConvert schlägt auf dem PMC-Pfad fehl |
Verwenden von /mode:LBR auf einem nur-IP-SPT |
Wechseln zu /mode:IP. |
Probleme mit dem Betriebssystemzeitgeberpfad
| Das Problem | Wahrscheinliche Ursache | Reparatur |
|---|---|---|
| Weniger Verbesserung als erwartet | Erwartet – der Betriebssystemtimer ist von geringerer Genauigkeit | Dies ist normal. Der Optimierer verfügt aus Timer-Stichproben über weniger Informationen über den Verzweigungsfluss als aus LBR oder PMC. Leistungsgewinne sind kleiner. Erwägen Sie ein Upgrade auf PMC oder LBR, wenn die Hardware dies unterstützt. |
| Null-Timer-Beispiele |
xperf wurde nicht in einer Eingabeaufforderung mit erhöhten Rechten ausgeführt, oder PROFILE der Anbieter fehlt. |
Bestätigen Sie die Ausführung als Administrator. Bestätigen Sie, dass -stackwalk profile für den Befehl xperf angegeben wurde. |
Allgemeine Probleme (alle Pfade)
| Das Problem | Wahrscheinliche Ursache | Reparatur |
|---|---|---|
"failed to configure counters" Fehler |
xperf nicht als Administrator ausgeführt |
Starten Sie die Eingabeaufforderung als Administrator neu (klicken Sie mit der rechten Maustaste auf > 'Als Administrator ausführen'). xperf erfordert erhöhte Berechtigungen zum Konfigurieren von Hardwareleistungsindikatoren. |
xperf nicht gefunden |
xperf.exe nicht im PATH |
Vergewissern Sie sich, dass die Windows ADK installiert ist. Überprüfen Sie C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\. Fügen Sie dieses Verzeichnis ihrem PATH hinzu, oder führen Sie xperf direkt aus. |
textCount.etl nicht erstellt |
xperf ist ohne Meldung fehlgeschlagen. | Bestätigen Sie die Ausführung als Administrator. Führen Sie den Befehl „xperf start“ erneut aus, und prüfen Sie, ob eine Fehlerausgabe erscheint. |
SPTAggregate schlägt mit "binär nicht gefunden" fehl. |
textCount.exe nicht im aktuellen Verzeichnis oder falschem Pfad |
Vergewissern Sie sich, dass Sie sich im selben Verzeichnis befinden wie textCount.exe, oder geben Sie den vollständigen Pfad zum /binary Parameter an. |
| SPD-Datei nicht erstellt |
SPDConvert Fehlgeschlagen |
Überprüfen Sie, ob die textCount.spt Größe ungleich Null ist. Führen Sie den Befehl aus SPTDump.exe textCount.spt , um den Inhalt zu überprüfen. |
/spdin Build bringt keine Verbesserung |
GUID-/Alters-Nichtübereinstimmung zwischen SPD und Binärdatei | Die SPD wurde aus einem anderen textCount.exe gebaut. Profilieren Sie den aktuellen Build erneut, um eine neue SPD zu generieren. |
MSVC-Versionsfehler bei /spgo |
MSVC-Toolset vor v14.51 | Öffnen Sie den Visual Studio Installer >Einzelne Komponenten> und installieren Sie MSVC v14.51 oder höher. Öffnen Sie die Entwickler-Eingabeaufforderung erneut. |
Nächste Schritte
Erkunden Sie nach Abschluss dieses Lernprogramms diese Funktionen, um mehr von SPGO zu erhalten:
-
Profilzusammenführung: Führen Sie mehrere Workloads aus, sammeln Sie SPT-Dateien bei jedem Durchlauf und übergeben Sie alle an
SPDConvert. Eine gemischte SPD spiegelt das gesamte Spektrum an realen Nutzungsmustern wider und erzeugt bessere Optimierungen als ein Szenarioprofil. Verwenden Sie die/retire:N-Option, um zu steuern, wie starkSPDConvertältere Profildaten abschwächt, wenn Sie neue SPT-Dateien hinzufügen. Der Standardwert (/retire:8) gewichtet neuere Daten stärker. Verwenden Sie/retire:0, um alle Läufe gleich zu gewichten; verwenden Sie/retire:16, um nur die neuesten Daten zu berücksichtigen. - Die besten Ergebnisse stammen aus der Mischung von Profilen aus mehreren Quellen, z. B. Benchmarks, die wichtige Szenarien sowie reale Daten (sofern verfügbar) hervorheben. Übergeben Sie SPT-Dateien aus allen Quellen an
SPDConvert. Wiederholen Sie eine SPT-Datei in der Argumentliste, um ihr mehr Gewicht zu verleihen (z. B. wirdcritical.sptdoppelt so stark gewichtet wiecommon.spt, wennSPDConvert myapp.spd critical.spt critical.spt common.sptwiederholt wird). -
Iterative Optimierung: Jede Neuerstellung mit
/spdinerzeugt eine neue SPD. Sie können die Ausführung, das Profil, den Neuerstellungszyklus wiederholen. Spätere Iterationen könnten einen abnehmenden Nutzen zeigen, aber ein zweiter Durchlauf kann manchmal Muster erkennen, die der erste Durchlauf übersehen hat. - Codeänderungen: Nach wesentlichen Änderungen am Quellcode Profildaten erneut erfassen. Die vorhandene SPD ist an die Binärdatei gebunden, gegen die sie profiliert wurde. Es entspricht nicht einer wesentlich neu aufgebauten Binärdatei.
-
Profilaktualität: Der Linker meldet den Prozentsatz der profilierten Funktionen, die nach jedem
/spdinBuildvorgang mithilfe von Profildaten optimiert werden. Wenn dieser Prozentsatz signifikant abfällt, ist es ein Signal, dass der Code vom Profil abweicht. Profilieren Sie die aktuelle Binärdatei neu.