Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Profile-Guided Optimization (PGO) använder körningsdata för att hjälpa kompilatorn att fatta bättre optimeringsbeslut. Med hjälp av körningsprofildata som samlas in från representativa arbetsbelastningar gör PGO det möjligt för kompilatorn att fatta smartare beslut om inlining, kodlayout och hot/cold code separation. Dessa beslut är omöjliga att fatta enbart från statisk analys.
SPGO har en annan metod. I stället för att instrumentera binärfilen och köra den via syntetiska träningsscenarier använder SPGO insamling av maskinvaruprestandaräknare som samlats in från dina faktiska versionsbinärfiler. Moderna processorer tillhandahåller funktioner för maskinvarusampling. Du kan samla in dessa samplingdata med försumbar prestandapåverkan, vilket gör det praktiskt att samla in profileringsdata direkt från kod i produktion.
Eftersom SPGO-profiler släpper bitar i stället för instrumenterade versioner ger det mycket mer flexibilitet i var och hur du samlar in data. Du kan samla in körningsprofiler från produktionsservrar, utvecklardatorer, prestandalabb eller valfri kombination. Resultatet är en binär fil som kör heta sökvägar mer effektivt, med en typisk prestandahastighet på 5–15% beroende på profildatans kvalitet.
I den här självstudien får du gå igenom hela SPGO-arbetsflödet: bygga en exempelapp, profilera den med hjälp av xperf, förbereda profileringsdata och sedan kompilera om den med profileringsdata. När du är klar kan du tillämpa samma process på dina egna projekt.
Prerequisites
Kontrollera att du har följande programvara och maskinvara innan du börjar.
Software
- MSVC-byggverktyg för x64/x86/ARM64 v14.51 eller senare – Installera dem via Visual Studio Installer. Under Enskilda komponenter söker du efter "MSVC-byggverktyg".
-
Windows Performance Toolkit (xperf.exe) – profileraren
xperfsamlar in exempeldata under programmets körning. Ladda ned Windows Assessment and Deployment Kit (ADK) från ADK install. När du kör ADK-installationsprogrammet väljer du komponenten Windows Performance Toolkit för att hämtaxperf. Du behöver inte installera hela ADK:t. - Textfil för Krig och fred – Används som exempelarbetsbelastning för att generera profileringsdata. Ladda ned den från Project Gutenberg: https://www.gutenberg.org/ebooks/2600. Spara den som en oformaterad textfil i arbetskatalogen.
Maskinvarukrav
Handledningen innehåller tre sätt att profilera. Vilken sökväg du använder beror på maskinvaran. Du kör identifieringskommandon i Välj din profileringsmetod för att ta reda på vilken sökväg datorn stöder. Använd den här tabellen för att bekräfta att du uppfyller minst ett av kraven.
| Path | CPU-krav | Notes |
|---|---|---|
| LBR (bästa resultat) | Last Branch Records (LBR) är prestandaräknare som tillhandahålls på Intel Haswell-processorer (4:e generationen Core, 2013) eller senare; AMD Zen 4 (2022) eller senare, ARM64 ARMv9.2-A (2020) eller senare | Tillhandahåller de bästa grendata. Mer information om LBR finns i En introduktion till de sista grenposterna |
| PMC/IP-läge (bra resultat) | Prestandaövervakningsräknare (PMC) stöds på alla x64-processorer med en prestandaövervakningsenhet (PMU) | Fungerar på de flesta moderna processorer där LBR inte är tillgängligt. Mer information om PMC finns i Spela in händelser för maskinvaruprestanda (PMU) och PMU-händelser (Recording Hardware Performance) med fullständiga exempel |
| OS-timer (fungerar överallt) | Valfri x64- eller ARM64-processor, inklusive Azure-virtuella datorer och virtuella datorer | Prover med lägre kvalitet, men alltid tillgängliga |
De flesta utvecklare på modern x64-datormaskinvara har LBR-stöd. Virtuella datorer och viss äldre maskinvara har PMC eller en OS-timer.
Så här fungerar SPGO
SPGO samlar in profildata från din binärfil som körs och matar tillbaka dem till kompilatorn när du skapar nästa gång. Kompilatorn använder dessa data för att fatta bättre beslut om inlining, kodlayout och grenförutsägelse. En bekvämlighet är att ingen instrumentation krävs.
Arbetsflödet är:
- Skapa din binär med länkarflaggan /spgo. Det här steget skapar en tom exempelprofildatabas (
.spdfil). - Profilera binärfilen med hjälp
xperfav för att skapa en ETL-spårningsfil. - Konvertera ETL till en SPT-fil med hjälp
SPTAggregate.exeav och konvertera sedan SPT till en SPD-fil med hjälpSPDConvert.exeav . - Bygg om med länkarflaggan /spdin som pekar på den ifyllda exempelprofildatabasen (SPD). Länkaren tillämpar SPGO-optimeringar.
Optimeraren använder SPD för att besvara frågor som: vilka grenar tas oftast? Vilka funktioner anropas i heta loopar? Den här processen ger bättre kodlayout och inlining av beslut än enbart statisk analys.
SPGO fungerar med både C och C++. Arbetsflödet och flaggorna är identiska för båda språken.
Bästa kandidater för SPGO: Stora, grenfyllda C/C++-program med snäva inre slingor. Ökar skalningen med codebase-storlek och grenkomplexitet. Det lilla exemplet i den här självstudiekursen visar en förbättring på cirka 7 %. Större produktionskodbaser ser ofta mer förbättring.
Jämförelse av byggprocess
Det här avsnittet behandlar hur SPGO passar in i byggpipelinen om du vill förstå hur det fungerar.
Normal byggprocess
I en vanlig C/C++-releaseversion:
-
Ingångar: Källkodsfiler (
.cpp,.h) och kompilatorflaggor i versionsläge (/O2,/GLoch så vidare). - Process: Kompilatorn tillämpar standardoptimeringar som inlining av heuristik, antaganden om grenförutsägelser och beslut om kodlayout enbart baserat på statisk analys. Den har inga data om hur programmet faktiskt beter sig när det körs.
-
Utdata: Körbara filer (
.exe), DLL-filer (.dll), felsökningsinformation (.pdb).
Utan körningsdata får heta sökvägar och kalla sökvägar liknande behandling.
SPGO-aktiverad byggprocess
SPGO lägger till profileringsdata som nya indata i build-pipelinen:
-
Ingångar: Källkod,
.spdprofilfilen (antal samplingar från en profileringskörning), kompilatorflaggor för release-läge,/link /spgooch/spdin:<path>för att ange en indata-SPD-fil (om den inte anges är standardvärdet en .spd med binärnamnet som finns i mappen obj). - Process: Länkaren läser SPD tillsammans med den mellanliggande koden. Den använder förgreningsfrekvensdata för att fatta bättre beslut om inlining, kodlayout och grenordning. Heta funktioner placeras för snabb åtkomst; kall kod flyttas bort från den kritiska exekveringsvägen.
-
Utdata: Optimerad körbar fil (
.exe), optimerade DLL-filer (.dll), felsökningsinformation (.pdb), och en ny.spd-fil för framtida profileringsiterationer.
Den viktigaste insikten: SPGO flyttar optimeringsbeslut från kompilator- och länknings-heuristik till datadrivna val baserat på verklig körning.
Nyckelflaggor
| Flagga | Type | Avsikt |
|---|---|---|
/spgo |
Linker | Aktiverar SPGO. Bäddar in SPGO-metadata i binärfilen och skapar en tom .spd utdatafil såvida inte /spdin anges, i vilket fall den angivna .spd filen används som indata. |
/spdin:<path> |
Linker | Input SPD – tillhandahåller profildata till länkaren för optimering |
/spd:<path> |
Linker | Utdata-SPD-sökväg – anger var det nya SPD:t skrivs (valfritt; standardvärdet är samma katalog som binärfilen). Används som indatasökväg för SPD om /spdin inte anges. |
/GL |
Kompilator | Hela programmets optimering krävs för att SPGO ska fungera mellan översättningsenheter |
/O1, /O2 (Minimera storlek, Maximera hastighet) |
Kompilator | Optimera för hastighet; möjliggör aggressiva optimeringar som SPGO kan förbättra |
Hur SPGO skiljer sig från PGO
PGO (Profile-Guided Optimization) kräver att du kompilerar din binärfil med instrumentationsflaggor (/GENPROFILE), kör den långsammare instrumenterade binära filen för att samla in .pgc körningsantalfiler och sedan länka om med /USEPROFILE. Kompilatorn får exakta antal exekveringar, men du måste instrumentera koden först. Mer information om den här processen finns i Profilstyrda optimeringar.
SPGO använder processorprestandaräknare för maskinvara för att samla in statistiska exempel från din oinstrumenterade binärversion. Kör din befintliga binär, profilera den med hjälp av xperf, konvertera spårningsfilen till en SPD-fil och bygg om den. Det finns ingen instrumenterad byggversion och ingen prestandaförsämring vid profilering. Kompilatorn hämtar statistiska samplingsdata i stället för exakta antal, vilket är mindre exakt men enklare att hämta och kräver inga kodändringar. Det möjliggör också profilering av systemkomponenter eller realtidskomponenter som är svåra att samla in data för med en instrumenterad metod. Du kan också profilera binärfiler för slut- eller produktionsversioner.
Den här handledningen behandlar tre profileringsmetoder: LBR, PMC och OS-timern. Du väljer din metod i Välj profileringsmetod. En detaljerad jämförelse av den normala byggprocessen jämfört med SPGO-byggprocessen, inklusive en flaggreferenstabell, finns i Jämförelse av byggprocess.
Konfigurera perfcore.ini
⚠️ Krävs: Utan det här steget
xperftillhandahåller inte nödvändiga profileringsdata. Slutför det här steget innan du körxperf.
Windows Performance Toolkit (WPT) använder perfcore.ini, som finns om du installerade WPT på standardplatsen på C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\perfcore.ini, för att registrera de DLL-providers som behövs för SPGO.
Öppna Windows Anteckningar som administratör. Öppna sedan perfcore.ini. Leta upp avsnittet för DLL-listan och lägg till följande poster, en per rad:
perf_spt.dll
perf_lbr.dll
Om xperf.exe inte har installerats kan du läsa Allmänna problem med att installera det.
Spara och stäng perfcore.ini. DLL-filerna levereras redan i samma katalog som xperf.exe så att du inte behöver kopiera dem någonstans. Du registrerar dem bara i perfcore.ini. Se till att det xperf finns i din sökväg.
Skapa exempelappen
Exempelappen för den här självstudien är ett C++-program som läser text från standardindata och genererar ett radantal, ordantal, totalt antal tecken, en teckenfrekvenstabell och förflutit tid för att bearbeta filen i millisekunder. Den är skriven i C++, men SPGO fungerar också med C. Arbetsflödet är identiskt för C-projekt.
Skapa en fil med namnet textCount.cpp i arbetskatalogen och lägg till följande källkod:
// 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;
}
Skapa och kör exemplet för att hämta en baslinje
Innan du använder SPGO skapar du textCount och kör den mot en stor textfil, till exempel War and Peace (du kan ladda ned den från Project Gutenberg) för att se hur snabbt den körs. Det här steget visar prestandan innan du optimerar den med hjälp av SPGO:
Version:
cl /EHsc /GL /O2 textCount.cpp
Köra:
textCount.exe < warAndPeace.txt
Du ser utdata som liknar:
=== TEXT STATISTICS ===
Lines: 66041
Words: 566333
Total Characters: 3227531
=== CHARACTER FREQUENCIES ===
Letters:
a: 202719
...
Elapsed time: 512.000 ms
Registrera värdet Elapsed time . Du jämför den med den SPGO-optimerade tiden i Mäta resultatet.
Skapa textCount med /spgo
Skapa nu textCount med SPGO aktiverat. Det här steget lägger grunden för att samla in profileringsdata.
cl /EHsc /GL /O2 textCount.cpp /link /debug /spgo
När bygget är klart visas ett meddelande som:
SPD textCount.spd not found, compiling without profile guided optimizations
Det här meddelandet visas i den första /spgo versionen. Länkaren skapar SPD-filen men den är fortfarande tom, så den tillämpar inga SPGO-optimeringar ännu. När du har kört binärfilen, samlat in profildata och konverterat dem till SPD visas inte det här meddelandet.
Flaggförklaringar:
| Flagga | Avsikt |
|---|---|
/EHsc |
Aktivera C++-undantagshantering |
/GL |
Optimering av hela programmet – krävs för SPGO. Skjuter upp den slutliga optimeringen till länktid, vilket möjliggör inline-expansion över modulgränser, kodlayout och eliminering av död kod. |
/O2 |
Optimera för hastighet – möjliggör aggressiv inlining, loopoptimering, borttagning av död kod och relaterade transformeringar. |
/link /debug |
Skicka med /debug till länkaren för att generera felsökningsinformation (.pdb), som xperf använder för att mappa profileringssamplingar till källkod. |
/spgo |
SPGO-länkflagga – bäddar in SPGO-metadata i binärfilen och skapar en tom textCount.spd fil tillsammans med den körbara filen. |
Note
/spgo är en länkflagga. Skicka den till länkaren via /link /spgo i kommandot cl.
Flaggan /spgo optimerar inte binärfilen ännu. Den förbereder den för profilering. Optimeringen sker i Rebuild textCount with /spdin efter att SPD har fyllts med faktiska körtidsdata.
Note
För att skriva SPD till en specifik plats lägger du till den valfria länkflaggan /spd:<path>. Till exempel: /link /debug /spgo /spd:.\profiles\textCount.spd. Om du utelämnar den här flaggan skapas SPD tillsammans med .exe.
Välj din profileringsmetod
SPGO stöder tre profileringsmetoder. Vilken metod du använder beror på maskinvaran.
De tre profileringsmetoderna
| Metod | Exempelkvalitet | Maskinvarukrav | Passar bäst för |
|---|---|---|---|
| LBR (senaste greningspost) | Högsta: registrerar sekvenser av grenar som nyligen har tagits, vilket ger optimeraren rikliga kontrollflödesdata per sampel | Intel Haswell (2013) eller senare; AMD Zen 4 (2022) eller senare; ARM64 ARMv9.2-A (2020) eller senare | Mest moderna skrivbordsmaskinvara |
| PMC/IP-läge (räknare/instruktionspekarläge för prestandaövervakning) | Bra. Samlar in stickprov av instruktionspekaren med anropsstackar med hjälp av CPU:ns prestandaövervakningsenhet (PMU) via Event Tracing for Windows (ETW) | Valfri x64- eller ARM64-PROCESSOR med en PMU | Maskinvara utan LBR-stöd |
| OS-timer | Basic – timerbaserade exempel | Alla x64- eller ARM64-processorer, virtuella datorer utan PMU-genomströmning | Virtuella datorer och äldre maskinvara |
Med PMC/IP-läge ger varje maskinvaruavbrott bara en datapunkt: "PROCESSORn var på adressen 0x1A2B3C4D när avbrottet utlöstes". Med LBR ger varje avbrott dig en stack med de senaste 16–32 grenarna som processorn tog innan avbrottet utlöstes. Optimeraren får bättre kontrollflödesdata och kan fatta bättre beslut om inlining och layout.
Identifiera din sökväg
Kör följande två kommandon för att avgöra vilken profileringssökväg datorn stöder. Dessa kommandon kräver ingen kommandotolk med förhöjd behörighet.
Steg 1: Sök efter LBR-stöd. Det här testet fungerar på Intel/AMD/ARM64.
Kör följande från kommandotolken administrator Visual Studio developer:
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"
- Om det här kommandot hittar en rad som innehåller
LBR, TimeStampstöder datorn LBR. Använd LBR-sökvägen. - Annars fortsätter du till steg 2.
Steg 2: Sök efter PMC-stöd (ingen LBR)
xperf.exe -pmcsources | findstr TotalIssues
- Om det här kommandot genererar utdata stöder datorn PMC-räknare men inte LBR. Använd PMC-sökvägen.
- Om det här kommandot inte genererar några utdata använder du operativsystemets timersökväg.
Mer information om PMU-händelseinsamling med xperf finns i Spela in PMU-maskinvaruhändelser med xperf.
Beslutstabell
LBR, TimeStamp-utdata |
TotalIssues-utdata |
Din sökväg |
|---|---|---|
| Inte tom | (inte markerat) | LBR |
| Tom | Inte tomt | PMC |
| Tom | Tom | operativsystemstimer |
| ARM64-processor | N/A | PMC (om PMU är tillgängligt) eller OS-timer |
Välj din metod
Bestäm om du vill använda lbr-, PMC- eller OS-timersökvägen baserat på identifieringsresultaten. Varje sökväg har olika xperf startparametrar för att samla in lämpliga profileringsdata. Följ den sökväg som matchar dina maskinvarufunktioner.
Din sökväg:
- LBR-användare (LBR identifierades i steg 1): Gå till LBR-sökväg.
- PMC-användare (InstructionRetired identifierades i steg 2): Gå till PMC-sökväg (ingen LBR).
- Timeranvändare för operativsystem (virtuell dator eller maskinvara utan PMU): Gå till operativsystemets timersökväg.
Alla sökvägar sammanstrålar igen vid Kör arbetsbelastningen och stoppa xperf.
Kommandona i det här avsnittet beror på den profileringssökväg som du identifierade i Välj profileringsmetod. Leta reda på underavsnittet som matchar din sökväg, kör xperf startkommandot och fortsätt sedan att köra arbetsbelastningen och stoppa xperf för att köra arbetsbelastningen och stoppa xperf.
⚠️ Kör som administratör:
xperfkräver en kommandotolk för utvecklare med administratörsbehörighet. Utan förhöjda behörigheter returnerarxperf"failed to configure counters".
LBR-sökväg
Börja xperf med LBR-kollektion:
xperf -on LOADER+PROC_THREAD+PMC_PROFILE -MinBuffers 4096 -MaxBuffers 4096 -BufferSize 4096 -pmcprofile BranchInstructionRetired -LastBranch PmcInterrupt -setProfInt BranchInstructionRetired 16384
Parameterförklaring:
| Parameter | Avsikt |
|---|---|
LOADER+PROC_THREAD+PMC_PROFILE |
Kernelprovidrar: inläsningshändelser (modulmappning), process-/trådhändelser (körningskontext) och PMC-profileringshändelser |
-MinBuffers 4096 -MaxBuffers 4096 -BufferSize 4096 |
Stora ringbuffertar för att undvika tappade prover under en fullständig War and Peace-körning |
-pmcprofile BranchInstructionRetired |
PMC-händelseutlösare: generera ett exempel på varje Nth retired branch-instruktion |
-LastBranch PmcInterrupt |
Aktiverar LBR-maskinvaruregistrering: vid varje PMC-avbrott fångas maskinvarans stack för senaste grenregistreringar upp |
-setProfInt BranchInstructionRetired 16384 |
Exempelintervall: utlösa ett avbrott var 16 384 slutförda greninstruktioner |
När du har startat xperf går du vidare till Kör arbetsbelastningen och stoppa xperf.
PMC-sökväg (utan LBR)
Starta xperf med insamling i PMC-/IP-läge:
xperf -on LOADER+PROC_THREAD+PMC_PROFILE+PROFILE -MinBuffers 4096 -BufferSize 4096 -pmcprofile InstructionRetired -setProfInt InstructionRetired 16384 -stackwalk profile
Parameterförklaring:
| Parameter | Avsikt |
|---|---|
LOADER+PROC_THREAD+PMC_PROFILE+PROFILE |
Lägger till PROFILE (CPU-sampling) och PMC_PROFILE för PMC-händelser; nej -LastBranch |
-pmcprofile InstructionRetired |
PMC-händelseutlösare: exempel på tillbakadragna instruktioner (instruktionspekarläge) |
-setProfInt InstructionRetired 16384 |
Utlös ett avbrott var 16 384 slutförda instruktioner |
-stackwalk profile |
Fånga en anropsstack vid varje profilavbrott, vilket ger anropskedjedata i stället för grensekvenser |
Jämfört med LBR: ingen -LastBranch flagga; använder InstructionRetired i stället för BranchInstructionRetired. Resultatet är instruktionspekareexempel med anropsstackar, inte grensekvenser. Den här sökvägen ger fortfarande effektiva data för optimeraren, men den är något mindre omfattande.
När du har startat xperffortsätter du att köra arbetsbelastningen och stoppa xperf.
OS-timerns sökväg
Starta xperf med OS-timerbaserad sampling:
xperf -on LOADER+PROC_THREAD+PROFILE -MinBuffers 4096 -BufferSize 4096 -setProfInt Timer 1221 -stackwalk profile
Parameterförklaring:
| Parameter | Avsikt |
|---|---|
LOADER+PROC_THREAD+PROFILE |
Inga PMC-händelser; CPU-sampling endast via operativsystemets timeravbrott |
-setProfInt Timer 1221 |
Aktivera operativsystemets timeravbrott var 1 221:e tidsinställd tick (cirka 1 kHz) |
-stackwalk profile |
Samla anropsstacken vid varje timeravbrott |
Jämfört med LBR och PMC använder den här metoden inte maskinvaruprestandaräknare. Operativsystemets timer utlöses med ungefär fasta tidsintervall oavsett CPU-aktivitet. Exemplen är mindre tätt korrelerade med frekvent kod men ger fortfarande användbara kontrollflödesdata för optimeringen.
Kör arbetsbelastningen och stoppa xperf (alla sökvägar)
Med xperf igång, kör textCount mot Krig och fred:
textCount.exe < warAndPeace.txt
När textCount är klart stoppar du xperf och skriver spårningsfilen. Att låta andra processer köras under profilering späder ut urvalskvaliteten. Stäng onödiga program innan du kör arbetsbelastningen för bästa resultat.
xperf -stop -d textCount.etl
När du har stoppat xperf (det kan ta en stund att skriva ut etl-filen) bekräftar du att den textCount.etl skapades i den aktuella katalogen.
Konvertera ETL-filen till SPT
Det här steget är detsamma för alla tre profileringsvägarna.
Kör SPTAggregate.exe för att bearbeta rå ETL-spårningen och skapa en SPT-profilfil:
SPTAggregate.exe /binary textCount.exe /etl textCount.etl textCount.spt
Parameterförklaring:
| Parameter | Avsikt |
|---|---|
/binary textCount.exe |
Binärfilen som du vill extrahera exempel från. ETL kan innehålla exempel från alla processer som kördes under profilering |
/etl textCount.etl |
Indata-ETL-spårningsfil |
textCount.spt |
Utdatafil för SPT-profil |
SPTAggregate visar en sammanfattning som visar hur många exempel som samlas in. Den här sammanfattningen är din första bekräftelse på att profilering fungerade.
Kontrollera utdata från SPTAggregate mot sökvägen du tog:
- LBR-sökväg: Leta efter antalet använda LBR-prov som inte är noll.
- PMC-sökväg: Leta efter ett PMC- eller stacksamplingsantal som är större än noll.
- OS-timersökväg: Leta efter ett antal använda stacksamplingar som är större än noll.
Om alla antal är noll läser du Felsökning innan du fortsätter.
Konvertera SPT-filen till SPD
Din sökväg:
- LBR-användare (använd
/mode:LBR): LBR-läge- PMC-användare (använd
/mode:IP): IP-läge (PMC och OS-timer)- OS timer-användare (använd
/mode:IP): IP-läge (PMC och OS timer)Både PMC- och OS-timer-sökvägarna använder
/mode:IPeftersom båda ger samplingar av instruktionspekaren.
Nästa steg förgrenas beroende på profileringssökvägen, närmare bestämt utifrån flaggan /mode som skickas till SPDConvert.exe.
LBR-läge
SPDConvert.exe /mode:LBR textCount.spd textCount.spt
/mode:LBR anger för SPDConvert att tolka SPT som att den innehåller LBR-grensekvensdata.
IP-läge (PMC- och OS-timer)
Både PMC-timern och OS-timern genererar stickprov av instruktionspekaren, så båda använder samma konverteringskommando:
SPDConvert.exe /mode:IP textCount.spd textCount.spt
/mode:IP anger åt SPDConvert att tolka SPT:n som att den innehåller samplingar av instruktionspekaren.
Varning
Om du använder fel läge för datatypen kan du skapa ett tomt eller felaktigt SPD. Om du profilerade med LBR, använd /mode:LBR.
Om du profilerade med PMC eller OS-timer, använd /mode:IP. Sammanfattningsutdata SPTAggregate från Konvertera ETL-filen till SPT visar vilka exempeltyper som samlats in och bekräftar rätt läge att använda.
När du har kört SPDConvert, bekräfta att textCount.spd har skapats (eller uppdaterats) i den aktuella katalogen.
Tolkning av SPDConvert-utdata
Kommandot SPDConvert textCount.spd textCount.spt skriver ut en sammanfattning av blocktäckning före och efter, till exempel:
Block coverage (before) : 33.90% ( 4507/ 13294)
Block coverage (after) : 45.64% ( 6067/ 13294)
Den här sammanfattningen visar procentandelen av binärfilens kodblock som har associerade profildata. En högre procentandel är bättre. Täckning över 70% är utmärkt, medan täckning under 40% kan begränsa optimeringseffektiviteten. Om täckningen är låg, kör profileringsarbetsbelastningen längre eller kombinera flera SPT-filer från separata körningar med olika arbetsbelastningar. Du kan till exempel köra textCount mot flera textfiler för att träna olika kodsökvägar.
Du kan se en varning från SPDConvert som liknar följande:
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.
Den här varningen innebär att din profileringskörning inte samlade in tillräckligt med exempel för optimeraren för att optimera alla heta funktioner på ett säkert sätt. SPD kan fortfarande användas, men du kan förbättra resultatet genom att:
- Köra arbetsbelastningen längre (till exempel 5 eller fler minuter i stället för 1 minut) eller använda olika arbetsbelastningar.
- Sänka
-setProfIntvärdet ixperfkommandot för att öka samplingsfrekvensen. Kompromissen är att den här ändringen ger en större ETL-fil, vilket tar längre tid att bearbeta. - Kombinera flera SPT-filer från separata profileringskörningar genom att skicka dem alla till
SPDConvert.
SPT-filen är ett binärt format. Om du vill kontrollera innehållet kan du köra SPTDump.exe textCount.spt. På samma sätt visar PTDump.exe textCount.spt de kompilerade profildata efter att ha kört SPDConvert. Båda verktygen är användbara för att verifiera icke-nollexempel innan du fortsätter.
Återskapa textCount med /spdin
Återskapa textCount med hjälp av den ifyllda SPD-filen. Länkaren läser profildata och tillämpar SPGO-optimeringar.
Det här steget är detsamma för alla tre profileringsvägarna.
cl /EHsc /GL /O2 textCount.cpp /link /debug /spgo /spdin:textCount.spd
Ny flagga (jämfört med Skapa textCount med /spgo):
| Flagga | Avsikt |
|---|---|
/spdin:textCount.spd |
Ange SPD-profildata till länkaren för optimering |
Kommandot innehåller /spgofortfarande . Den genererar en ny SPD-fil tillsammans med den optimerade binära filen, som du kan använda som startpunkt för efterföljande profilering av iterationer.
Varning
SPD-filen är associerad med den exakta binärfilen som den profilerar mot. Om du återskapar textCount utan /spdineller återskapar från en ändrad källa måste du generera en ny SPD-fil. Den befintliga filen matchar inte den nya binärfilens GUID, och länkaren kommer inte att använda den.
Efter ombyggnaden med /spdin genererar länkaren statistik om hur mycket av din kod som optimerades med hjälp av profildata. Som exempel:
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
En hög procentandel innebär att SPD täcker din binära brunn. Om procentandelen är låg (till exempel under 90%) har profileringsarbetsbelastningen inte tränat tillräckligt med binärfilen eller så har binärfilen ändrats avsevärt sedan profilen samlades in. I båda fallen ska du göra om profileringen mot aktuell binärfil.
Vad SPGO gör med dina profildata
SPGO använder insamlade exempeldata för att fylla i antalet för varje block och gräns i programmets kontrollflödesdiagram. Dessa antal styr optimeringar som till exempel:
- Profilstyrd inlining: Infoga frekventa anropsställen aggressivt samtidigt som kodsvällning från inlining av sällan använda kodvägar undviks.
- Separering av hot/cold-kod: Flytta kod som körs sällan till separata sektioner i binärfilen, vilket förbättrar utnyttjandet av instruktionscachen och sidningsbeteendet.
- Funktionslayout: Placera funktioner som ofta anropar varandra nära varandra i binärfilen, vilket minskar sidfel och förbättrar lokaliteten. Optimerade funktioner är ordnade i COFF-grupper med hög tillhörighet i binärfilen.
- Beslut om storlek/hastighet: Kompilera heta funktioner för hastighets- och kallfunktioner för storlek. Rutiner utan observerade profilträffar kan kompileras för storlek snarare än hastighet, vilket begränsar optimeringar som inlining och loop-avregistrering i dessa kalla sökvägar.
- Spekulativ devirtualisering: När sampling visar att ett indirekt anrop konsekvent riktar sig mot samma funktion kan SPGO spekulera i det målet och infoga det, med en reserv för det ovanliga fallet.
Mäta resultatet
Kör textCount igen och jämför förflutna tider.
textCount.exe < warAndPeace.txt
Samla in flera körningar för varje konfiguration och använd medianen. En enskild körning är inte tillförlitlig eftersom operativsystemets schemaläggning och systembrus kan snedvrida enskilda mätningar.
| Bygga | Representativ förfluten tid |
|---|---|
Baslinje (cl /EHsc /O2) |
(din mätning) |
/spgo build (inga profildata ännu) |
(bör vara nära baslinjen) |
SPGO-optimerad (/spdin) |
(bör visa förbättring) |
I ett test gav SPGO med LBR-metoden en minskning av körtiden med cirka 7 %. Dina resultat kan variera med dina egna projekt eftersom SPGO-vinster beror på hur väl profileringsarbetsbelastningen representerar typisk körning. Större, grenfyllda kodbaser tenderar att se mer förbättring inom intervallet 5–10%. Profileringsmetoden påverkar optimeringskvaliteten. LBR ger vanligtvis bättre resultat än PMC, vilket ger bättre resultat än OS-timer. Om du är på operativsystemets timerväg kan du förvänta dig mindre vinster.
LBR-sökvägen som följdes i den här självstudien tillämpades på SQLite-projektet , som är ett produktionsdatabasbibliotek. Den SPGO-optimerade SQLite-binärfilen visade ungefär 7% förbättring.
Tillämpa SPGO på ditt eget projekt
Använd den här checklistan för att tillämpa SPGO på ditt eget C- eller C++-program.
Lägg till
/link /spgoi ditt befintliga kommando för releaseversionen. Ändra byggskriptet eller projektfilen:cl /EHsc /GL /O2 myapp.cpp /link /spgoVälj en representativ arbetsbelastning. Välj ett verkligt användningsscenario som använder programmets heta sökvägar. Använd produktionsliknande data. Undvik följande som huvudsaklig arbetsbelastning vid profilering: kodtäckningstester (de belastar inte prestandaflaskhalsar), ovanliga felhanteringsvägar, start- och avstängningsfaser samt föråldrade kodvägar. Den här arbetsbelastningen styr profilen som matar optimeraren.
Kör xperf med din identifierade sökväg. Använd sökvägen som du identifierade i Välj din profileringsmetod (LBR, PMC eller OS-timer). Starta
xperf, kör arbetsbelastningen en gång, stoppaxperfoch samla in ETL-filen.För sökvägen för PMC- eller OS-timern, kör SPTAggregate och SPDConvert med rätt
/mode-flagga. Konvertera ETL till SPT och därefter till SPD. Använd/mode:LBRför LBR-data, använd/mode:IPför PMC- eller OS-timerdata.Bygg om med
/spdin:<your-spd-path>. Kompilera ditt program med det ifyllda SPD:et:cl /EHsc /GL /O2 yourApp.cpp /link /spgo /spdin:yourApp.spdMät före och efter. Kör arbetsbelastningen med både de icke-optimerade och SPGO-optimerade binärfilerna. Samla in medianvärdet för flera körningar för varje konfiguration. En enda körning är inte ett tillförlitligt underlag för prestandamätning.
Lagra
.spdfilen i versionshanteringen..spdKontrollera filen i källkontrollsystemet tillsammans med källkoden.Aktivera SPGO i utvecklarversioner. Låt ditt teams releaseversioner använda samma SPGO-optimerade binärfiler som i produktionsmiljön. Detta hjälper till att fånga prestandaregressioner tidigt.
Inaktivera SPGO i felsökningsversioner.
Visa statistik över hur fullständig länkredigerarens profil är. Efter varje version med
/spgobör du notera procentandelen profilerade funktioner som optimerats med hjälp av profildata. Om den här andelen sjunker avsevärt (under 90 %), bör du profilera om den aktuella binären. Kodändringar ansamlas och SPD:n kan bli föråldrad.
Alternativ till att använda xperf
Ett annat sätt att samla in profildata är att använda en samplingsprofilerare som Windows Performance Recorder (WPR). WPR installeras som standard på Windows 10 och senare. Den samlar in liknande data som xperf. Du kan konfigurera WPR för att samla in CPU-exempel med anropsstackar och sedan exportera data till en ETL-fil som du kan bearbeta med SPTAggregate och SPDConvert som xperf ETL. Här är ett exempel på hur du använder WPR för att samla in profildata:
wpr -start CPU.light -filemode
textCount.exe < warAndPeace.txt
wpr -stop spgo_data.etl
Mer information om hur du använder WPR finns i Using Windows Performance Recorder.
SPD-fördelning
Du kan:
-
.spdKontrollera filen direkt i källkontrollen tillsammans med källkoden. -
.spdDela filen med gruppmedlemmar så att de kan skapa med SPGO-optimeringar utan omprofilering. - Paketera
.spdfilen med dina binärfiler som en versionsartefakt (till exempel ett NuGet-paket) och registrera vilken version som motsvarar vilken binär fil. -
.spdÅterskapa filen när som helst genom att upprepa arbetsflödet för profilering.
SPD:n är knuten till den exakta binärfil som den byggdes från. Efter betydande kodändringar, omprofilera för att generera en ny SPD. Under bygget /spdin skapar kompilatorn också en ny .spd fil. Spara den här nya SPD:n som en kompileringsartefakt – det är startpunkten för nästa iteration av profilering.
Återanvända SPD-information mellan versioner
Med konceptet "carry forward" i SPGO kan du lägga till profileringsdata i en befintlig SPD-fil utan att profilera alla scenarier igen från grunden och utan att förlora befintlig profilinformation. Du kan också justera hur mycket vikt du ska ge till äldre profildata. Den här flexibiliteten är användbar när det kan finnas beteendeförändringar över tid och du inte vill förlora profilinformationen helt från tidigare scenariokörningar. En DLL kan till exempel se olika API:er som anropas när programmet som anropar det utvecklas. Du vill fortfarande ha optimeringar från hur det brukade bete sig, men vill blanda in optimeringsmöjligheter för hur det ibland beter sig annorlunda nu. Du kan utveckla profilen över tid genom att blanda gamla och nya data.
När du kör SPDConvert med en ny SPT-fil skickar du namnet på den befintliga SPD-filen. Sedan använder du alternativet /retire:N för att styra hur aggressivt SPDConvert tonar ned äldre profildata när du lägger till nya SPT-filer:
- Standardinställningen (
/retire:8) ger större vikt åt nyare data. - Använd
/retire:0för att ge samma vikt till alla körningar. - Använd
/retire:16för att endast låta de senaste uppgifterna räknas.
Felsökning
Hitta problemet:
- PROBLEM med LBR-sökväg:PROBLEM med LBR-sökväg
- Problem med PMC-sökvägar:Problem med PMC-sökvägar
- Problem med OS-timer:Problem med OS-timersökväg
- Problem som påverkar alla sökvägar:Allmänna problem
Problem med LBR-sökväg
| Problem | Sannolik orsak | Korrigera |
|---|---|---|
Inga LBR-sampel i utdata från SPTAggregate |
CPU stöder inte LBR, eller så exponerar inte den virtuella datorn LBR | Kör identifieringskommandot från Identifiera din sökväg. Om du är i en Hyper-V virtuell dator kör du Set-VMProcessor MyVMName -Perfmon @("pmu", "lbr") på värden. Om LBR inte är tillgängligt, byt till PMC- eller OS-timervägen. |
Processorn stöder LBR men SPTAggregate visar 0 LBR-exempel |
perfcore.ini DLL-registreringen är ofullständig |
Slutför konfigurationen perfcore.ini i Konfigurera perfcore.ini. Se till att perf_lbr.dll är registrerad. |
SPDConvert misslyckas eller skapar en tom SPD |
Fel /mode flagga eller SPT innehåller endast IP-lägesexempel |
Bekräfta att SPTAggregate utdata visade LBR-exempel. Om utdata endast visar IP-lägesexempel växlar du till /mode:IP. |
Problem med PMC-sökväg
| Problem | Sannolik orsak | Korrigera |
|---|---|---|
Noll PMC-exempel i SPTAggregate utdata |
perfcore.ini DLL-registreringen är felaktig |
Slutför konfigurationen perfcore.ini i Konfigurera perfcore.ini. Se till att perf_spt.dll är registrerad. Utan denna DLL-fil genererar xperf noll PMC-samplingar utan något felmeddelande.Kör xperf.exe -pmcsources för att se listan över prestandaräknare som är tillgängliga på din CPU. Om du inte ser poster som SPT_OP_RETIRE_INSTR eller SPT_OP_RETIRE_BR_INSTR kan SPT_OP_ETW_INSTRDLL-registreringen i perfcore.ini vara ofullständig eller så kanske processorn inte stöder PMC. Om du inte kan matcha DLL-registreringen kan du prova operativsystemets timersökväg i stället. |
findstr InstructionRetired returnerar utdata men xperf genererar inga exempel |
VM-maskering av PMC-räknare | Kontrollera om det körs på en virtuell dator. Aktivera PMU i Hyper-V med Set-VMProcessor eller växla till operativsystemets timersökväg. |
SPDConvert misslyckas på PMC-sökvägen |
Använda /mode:LBR på en SPT med endast IP |
Växla till /mode:IP. |
Problem med operativsystemets timersökväg
| Problem | Sannolik orsak | Korrigera |
|---|---|---|
| Mindre förbättring än förväntat | Förväntat - OS-timer har lägre precision | Detta är normalt. Optimeraren har mindre information om grenflöde från timerexempel än från LBR eller PMC. Prestandaökningarna är mindre. Överväg att uppgradera till PMC eller LBR om maskinvaran stöder det. |
| Noll timerexempel |
xperf kördes inte i en upphöjd kommandotolk, eller så saknas PROFILE-providern |
Bekräfta att du kör som administratör. Bekräfta att -stackwalk profile angavs till kommandot xperf. |
Allmänna problem (alla sökvägar)
| Problem | Sannolik orsak | Korrigera |
|---|---|---|
"failed to configure counters" Fel |
xperf körs inte som administratör |
Starta om kommandotolken som administratör (högerklicka på > Kör som administratör). xperf kräver utökade privilegier för att konfigurera maskinvaruprestandaräknare. |
xperf hittades inte |
xperf.exe finns inte i PATH |
Bekräfta att Windows ADK är installerat. Kontrollera C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\. Lägg till katalogen i PATH eller kör xperf direkt från den. |
textCount.etl har inte skapats |
xperf misslyckades tyst | Bekräfta att du kör som administratör. Kör kommandot xperf start igen och sök efter felutdata. |
SPTAggregate misslyckas med felet "binärfilen hittades inte" |
textCount.exe inte i aktuell katalog eller fel sökväg |
Bekräfta att du är i samma katalog som textCount.exeeller ange den fullständiga sökvägen till parametern /binary . |
| SPD-filen har inte skapats |
SPDConvert Misslyckades |
Kontrollera att textCount.spt storleken inte är noll. Kör SPTDump.exe textCount.spt för att inspektera innehållet. |
/spdin bygget medför ingen förbättring |
GUID/ålder stämmer inte överens mellan SPD och binärfilen | SPD:n byggdes från en annan textCount.exe. Profilera den aktuella versionen igen för att generera en ny SPD. |
MSVC-versionsfel på /spgo |
MSVC-verktygsuppsättning tidigare än v14.51 | Öppna Visual Studio Installer >och välj Individual Components> installera MSVC v14.51 eller senare. Öppna kommandotolken för utvecklare igen. |
Nästa steg
När du har slutfört den här självstudien kan du utforska de här funktionerna för att få mer från SPGO:
-
Profilblandning: Kör flera arbetsbelastningar, ackumulera SPT-filer från varje körning och skicka dem alla till
SPDConvert. Ett blandat SPD återspeglar hela utbudet av verkliga användningsmönster och ger bättre optimeringar än en profil med ett scenario. Använd alternativet/retire:Nför att styra hur aggressivtSPDConverttonar ned äldre profildata när du lägger till nya SPT-filer. Standardinställningen (/retire:8) ger större vikt åt nyare data. Använd/retire:0för att ge lika stor vikt åt alla körningar. Använd/retire:16så att endast de senaste uppgifterna räknas. - De bästa resultaten kommer av att blanda profiler från flera källor, till exempel prestandatester som utsätter viktiga scenarier för hög belastning, samt verkliga data (om sådana finns tillgängliga). Skicka SPT-filer från alla källor till
SPDConvert. Upprepa en SPT-fil i argumentlistan för att ge den mer vikt (till exempelSPDConvert myapp.spd critical.spt critical.spt common.sptviktercritical.sptdubbelt så mycket somcommon.spt). -
Iterativ optimering: Varje återskapa med
/spdingenererar en ny SPD. Du kan upprepa körningen, profilen och återskapa cykeln. Senare iterationer kan visa minskande avkastning, men en andra passning kan ibland fånga mönster som den första missade. - Kodändringar: Efter betydande källändringar ska du samla in profildata. Den befintliga SPD:n är knuten till den binärfil som den profilerades mot. Den matchar inte en binär som byggts om i grunden.
-
Profilens aktualitet: Länkaren rapporterar andelen profilerade funktioner i procent som har optimerats med profildata efter varje
/spdinbygge. Om den här procentandelen minskar avsevärt, är det en signal om att koden har avvikit från profilen. Gör om profileringen av den nuvarande binärfilen.