konstrukce p řekladačů
Post on 19-Jan-2016
23 Views
Preview:
DESCRIPTION
TRANSCRIPT
Konstrukce překladačů
David Bednárek
www.ksi.mff.cuni.cz
Pravidla studia
SWI109
2/1
Z,Zk
3 Pravidla studia
CvičeníKaždých 14 dníZápis v SISZápočtové testy
Hromadný termín na cvičení koncem semestru Opravné termíny individuálně ve zkušebních termínech
Alternativa: Implementace části překladače Podle zadání ze šk.r. 2010/11
PřednáškaZkouška - písemná
Literatura
5 Literatura A.V. Aho, R. Sethi, J.D. Ullman
Compiler: Principles, Techniques and Tools (1986) Grune, Bal, Jacobs, Langendoen
Modern Compiler Design (2000)• Přehled včetně front-endů a překladu neprocedurálních jazyků
Steven S. MuchnickAdvanced Compiler Design and Implementation (1997)
• Přehled optimalizací v back-endech Randy Allen, Ken Kennedy
Optimizing Compilers for Modern Architectures (2001)• Hardwarově závislé optimalizace
R. MorganBuilding an Optimized Compiler (1998)
Srikant, Shankar (eds.)The Compiler Design Handbook (2003)– Optimizations and Machine Code Generation
• Sbírka 22 článků J. R. Levine
Linkers and Loaders (1999)
Architektura překladače
7 Architektura překladače
Amatérský pohled
Lexikální analyzátor
Parser
Sémantický analyzátor
Generátor kódu
Posloupnost tokenů
Derivační strom
Derivační stromDerivační strom
Cílový kód
8 Architektura překladače
Z velké dálky
Generátor mezikódu
Lexikální analyzátor
Parser
Sémantický analyzátor
Generátor kódu
Posloupnost tokenů
Derivační strom
Derivační strom
Mezikód
Derivační strom
Cílový kód
front-endzávislý na vstupním jazyku
back-endzávislý na cílovém stroji
9 Architektura překladače
S optimalizacemi
Optimalizace
Generátor mezikódu
Strojově závislé optimalizace
Lexikální analyzátor
Parser
Sémantický analyzátor
Optimalizace
Generátor kódu
Strojově závislé optimalizace
Posloupnost tokenů
Derivační strom
Derivační strom
Derivační strom
Mezikód (střední úrovně)
Derivační strom
Mezikód (střední úrovně)
Mezikód (střední úrovně)
Mezikód nízké úrovně
Cílový kód
front-endzávislý na vstupním jazyku
back-endzávislý na cílovém stroji
10 Architektura překladače
Detailní pohled akademika (pouze optimalizace)• Muchnick: Advanced Compiler Design and Implementation
Scalar replacement of array referencesData-cache optimizations
Procedure integrationTail-call optimizationScalar replacement of aggregatesSparse conditional constant propagationInterprocedural constant propagationProcedure specialization and cloningSparse conditional constant propagation
Global value numberingLocal and global copy propagationSparse conditional constant propagationDead-code eliminationLocal and global common-subexpression eliminationLoop-invariant code motionDead-code eliminationCode hoistingInduction-variable strength reductionLinear-function test replacementInduction-variable removalUnnecessary bounds-checking eliminationControl-flow optimizations
In-line expansionLeaf-routine optimizationShrink wrappingMachine idiomsTail mergingBranch optimizations and conditional movesDead-code eliminationSoftware pipelining, loop unrollingBasic-block and branch schedulingRegister allocationBasic-block and branch schedulingIntraprocedural I-cache optimizationInstruction prefetchingData prefetchingBranch prediction
Interprocedural register allocationAggregation of global referencesInterprocedural I-cache optimization
Constant foldingAlgebraic simplification and reassociation
11 Architektura překladače
Realita GNU
CompilerCollectionInternals
Remove useless statements Mudflap declaration registration Lower control flow Lower exception handling control flow Build the control flow graph Find all referenced variables
RTL generation Generate exception handling landing pads Cleanup control flow graph Common subexpression elimination Global common subexpression elimination. Loop optimization Jump bypassing If conversion Web construction Life analysis Instruction combination Register movement Optimize mode switching Modulo scheduling Instruction scheduling Register class preferencingLocal register allocationGlobal register allocationReloadingBasic block reordering Variable tracking Delayed branch scheduling Branch shortening Register-to-stack conversion Final Debugging information output
Enter static single assignment form Warn for uninitialized variables Dead code elimination Dominator optimizations Redundant phi elimination Forward propagation of single-use variables Copy renaming PHI node optimizations May-alias optimization Profiling Lower complex arithmetic Scalar replacement of aggregates Dead store elimination
Tail recursion elimination Forward store motion Partial redundancy elimination Loop invariant motionCanonical induction variable creationInduction variable optimizationsLoop unswitchingVectorizationTree level if-conversion for vectorizer Conditional constant propagation Folding builtin functions Split critical edges Partial redundancy elimination Control dependence dead code elimination Tail call elimination Warn for function return without value Mudflap statement annotation Leave static single assignment form
Názvosloví
13 Základní bloky
Procedura Procedura nebo funkce
Call graph Graf (možného) volání mezi procedurami
Základní blok (BB – basic block) Část procedury bez větvení a smyček, se vstupem pouze na
začátku a výstupem pouze na konci Volání procedury může a nemusí být považováno za předěl BB
Tok řízení - control-flow (graph) Možnosti předávání řízení mezi základními bloky v proceduře Reprezentováno orientovaným (cyklickým) grafem
Tok dat - data-flow Předávání dat, obvykle uvnitř jednoho základního bloku Pro jeden BB může být reprezentováno dagem
14 Dag
Závislost (dependence) Povinnost provést jednu operaci/instrukci po jiné Částečné uspořádání operací/instrukcí v jednom BB
Datová závislost (dependence) Závislost producent-konzument v toku dat
Antidependence Read-Write: Čtení se musí stihnout před zápisem Write-Write: Pořadí zápisů se nesmí změnit Jiné důvody, obvykle nízkoúrovňového původu
Dag (directed acyclic graph) Orientovaný acyklický graf použitý pro zaznamenání
• data-flow
• závislostí
15 Typy
Skalární/jednoduchý/atomický typ (scalar) Typ, s nímž dokáže přímo pracovat cílový stroj
Složený typ (aggregate) Pole, struktura, třída, řetězec apod.
Zarovnání (alignment) Požadavek na umístění proměnné/paměťového místa na adrese
dělitelné 2, 4, 8, nebo 16 Striktní: Při nedodržení procesor vyvolá výjimku Optimalizační: Při nedodržení bude kód pomalejší
16 Proměnné
Proměnná (variable) Proměnná deklarovaná ve vstupním jazyce, včetně parametrů Pomocná proměnná (temporary) vytvořená překladačem
Statická/globální proměnná Proměnná s jedinou instancí přístupná všem procedurám
(Lokální) proměnná Parametr, deklarovaná či pomocná proměnná přístupná pouze
jedné proceduře
Jazyky s vnořenými procedurami vyžadují další kategorii proměnných přístupných z vnořených procedur
Paměťové místo Část proměnné nebo dynamicky alokované paměti
17 Alias
Alias Situace (nebo možnost výskytu situace), kdy k jedné proměnné, její
části, či paměťovému místu, vedou dvě různé přistupové cesty
int x; int a[ 20];int * p = & x; a[ i] = ...;
a[ j] = ...;
Rozhodnutí, zda může jít o alias, je obecně algoritmicky neřešitelná úloha
Pokud si překladač není jist, že o alias nejde, musí se chovat, jako by to alias byl
• Nejistý alias je ještě horší, než jistý
Proměnná bez aliasu Lokální proměnná, která prokazatelně nemá alias
• Všechny přístupy k ní lze jednoznačně určit
18 Live range
Doba života/rozsah platnosti proměnné (live range) Množina míst v proceduře, kdy je proměnná zapotřebí
• Tedy existuje možnost, že by ještě byla čtena (před zápisem)
Zkoumá se obvykle pouze pro skalární lokální proměnné bez aliasu
Variable splitting/renaming Proměnnou s nesouvislým rozsahem platnosti lze nahradit několika
jinými• Odpadne omezení na shodnou alokaci v jednotlivých souvislých
oblastích rozsahu platnosti
19 Alokace – přidělování místaStatická alokace (static allocation)
Pro statické proměnné Vyhrazení místa na „pevné“ adrese
• Podléhá relokaci při spojování linkerem a zavádění loaderem
Registrová alokace (register allocation) Pro skalární lokální proměnné bez aliasu Umístění do fyzického registru cílového stroje
• Pouze po dobu života proměnné• Omezeno počtem fyzických registrů
Zásobníková alokace (stack allocation) Umístění na zásobníku
• Zásobník může být definován procesorem nebo emulován Složené nebo aliasované lokální proměnné Proměnné, které se nevešly do registrů
Spill-code Kód „navíc“, který musel být přidán pro manipulaci s proměnnými, které se
nevešly do registrů
20 Volací konvence
Volací konvence• Úmluva o způsobu spolupráce volající a volané procedury• Definována cílovým prostředím nebo autorem překladače
Umístění parametrů• Zásobník nebo registry• Pořadí• Přesné umístění je komplikováno zarovnáním
Umístění návratové hodnoty• Obvykle registr• Složené typy se obvykle řeší jako parametry předávané odkazem
Odpovědnost za úklid zásobníku• Volající/volaný
Povinnost zachovat obsah registrů• Všechny, některé, nebo žádné
Další technické definice• Úprava jména procedury jako symbolu pro linker
• Pokročilá interprocedurální optimalizace: Automatická úprava volací konvence podle místních podmínek volaného a všech volajících
21 Činnost překladače, optimalizace
Intraprocedurální Uvnitř jedné procedury
Lokální Uvnitř jednoho základního bloku
• Příklad: Jednodušší verze schedulingu nebo CSE
Globální Pro celou proceduru najednou
• Příklad: Přidělování registrů, složitější CSE
Interprocedurální Pro celý program najednou Při separátním překladu modulů je součástí linkeru Obvykle exponenciální nebo algoritmicky neřešitelné úlohy
• Příklad: Interprocedurální analýza aliasů
• Srovnání: In-line expanze procedury patří formálně mezi intraprocedurální optimalizace
22 Typy
Logický typ Datový typ definovaný vstupním jazykem Základní typy + typové konstrukce Neomezená množina typů
Fyzický typ Typ rozeznávaný cílovým strojem Konečná množina vestavěných typů
• Celá čísla několika velikostí (znaménková a bezznaménková)
• Ukazatel (pokud nesplývá s celým číslem)
• Reálná čísla několika velikostí/přesností
Na ostatní typy se pohlíží jako na posloupnost bajtů• Rozhoduje délka, případně požadavek na zarovnání
23 Mezikódy Vysokoúrovňový mezikód
Reprezentace vstupního programu• Během fází, řešících konstrukce a pravidla vstupního jazyka• Užívá logické typy a operace vstupního jazyka
Nejčastěji ve formě anotovaného AST (abstract syntax tree)• Derivační strom podle abstraktní gramatiky
Mezikód střední úrovně Nejčastější hranice mezi front- a back-endem Na vstupním jazyce nezávislá reprezentace
• Užívá fyzické typy a operace na nich
Nejčastěji ve formě čtveřic• Tříadresové pseudoinstrukce, pomocné proměnné• Někdy ve speciálních formách (SSA – static single assignment)• Control-flow může být ve formě grafu BB (základních bloků)
Nízkoúrovňový mezikód Ekvivalent strojových instrukcí
• Nekompaktní forma, symbolické a relokované operandy• Před alokací registrů forma s neomezeným počtem virtuálních registrů
Někdy v univerzální strojově nezávislé formě (GCC RTL)
Mezikódy
25 Mezikódy
Informace uložené v mezikódu střední úrovněSeznam globálních proměnnýchDalší globální informace pro generovaný kódSeznam procedurDalší informace pro debugger
26 Mezikódy
Informace uložené v mezikódu střední úrovněSeznam globálních proměnných
• Velikost
• Inicializace
• Příznak konstantnosti
• Jméno (pro linker)
• Logický typ (pro debugger)
Další globální informace pro generovaný kód Konstanty (reálné, řetězcové, strukturované) Tabulky virtuálních funkcí, RTTI Často splývají s globálními proměnnými
Seznam procedurDalší informace pro debugger
Jména a konstrukce typů
27 Mezikódy
Popis procedury Jméno (pro linker a chybová hlášení)
Seznam parametrů Fyzický typ (+ velikost) Umístění podle volací konvence Jméno (pro debugger a chybová hlášení) Logický typ (pro debugger a určení aliasů)
Seznam lokálních proměnných Fyzický typ (+ velikost) Jméno (pro debugger a chybová hlášení) Logický typ (pro debugger a určení aliasů) Proměnné ve vnořených blocích se obvykle povyšují na úroveň
procedury
Kód proceduryDalší informace (popisy výjimek apod.)
28 Mezikódy
Kód proceduryPlně sekvenční forma
Posloupnost (pseudo-)instrukcí virtuálního stroje Tok řízení popsán skokovými instrukcemi
Částečně sekvenční forma Tok řízení popsán grafem, jehož uzly jsou základní bloky Každý základní blok obsahuje posloupnost (pseudo-)instrukcí
• Skokové instrukce pouze na konci BB nebo zaznamenány jinak
Nesekvenční forma Tok řízení popsán grafem, jehož uzly jsou základní bloky Tok dat uvnitř základního bloku popsán dagem
• Různé formy podle stupně analýzy aliasů a rozsahů platnosti
• Pokročilejší formy nahrazují lokální proměnné rozhraními bloků
29 Plně sekvenční čtveřicový mezikódint gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
TMP:(T1,B),(T2,B),(T3,I32)
ENTER
GT_I32 T1,Px,Py
JF T1,L1
MOV_I32 Vz,Py
MOV_I32 Py,Px
MOV_I32 Px,Vz
L1:
GT_I32 T2,Px,C1
JF T2,L2
MOD_I32 T3,Py,Px
MOV_I32 Vz,T3
MOV_I32 Py,Px
MOV_I32 Px,Vz
JMP L1
L2:
RET_I32 Py
30 Částečně sekvenční čtveřicový mezikódint gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
TMP:(T1,B),(T2,B),(T3,I32)
ENTERGT_I32 T1,Px,PyJC T1
GT_I32 T2,Px,C1JC T2
RET_I32 Py
MOV_I32 Vz,PyMOV_I32 Py,PxMOV_I32 Px,Vz
MOD_I32 T3,Py,PxMOV_I32 Vz,T3MOV_I32 Py,PxMOV_I32 Px,Vz
31 Nesekvenční mezikód (před analýzou aliasů)int gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
GT_I32
LD_I32(Px) LD_I32(Py)
JC
ENTER
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
GTC_I32(C1)
JC
LD_I32(Px)
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
LD_I32(Py)
RET_I32
Control-Flow
vždy
if true
if false
Dag
Data-flow
Závislosti
32 Mezikódy střední úrovně
Plně sekvenční formaČástečně sekvenční formaNesekvenční forma
Všechny tyto formy lze generovat přímoz abstraktního syntaktického stromu
Jedním průchodem zdola nahoru• goto je nutné ošetřit dodatečnými zásahy (backpatching)
Strom nemusí fyzicky existovat,postačí průchod myšleným stromem
• LR analýza: pravá derivace pozpátku
• LL analýza rekurzivním sestupem
Většina front-endů přesto strom konstruuje• Složité konstrukce jazyka (šablony, předkompilované části)
• Rozhraní mezi syntaktickým a sémantickým analyzátorem
• Optimalizace
33 Mezikódy střední úrovně
Plně sekvenční formaČástečně sekvenční formaNesekvenční forma
Táž forma se obvykle v průběhu překladu upravuje Připojují se odvozené informace a optimalizační rozhodnutí Provádějí se ekvivalentní úpravy (optimalizace)
Jedna forma může mít různé variace A to i uvnitř jednoho překladače Odráží různé způsoby a/nebo různé stupně analýzy
Řada překladačů užívá dvě z těchto forem Z historických důvodů (stabilita rozhraní front-end/back-end) Pro vytvoření druhé formy je nutná analýza první formy
34 Detekce základních blokůCONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
TMP:(T1,B),(T2,B),(T3,I32)
ENTER
GT_I32 T1,Px,Py
JF T1,L1
MOV_I32 Vz,Py
MOV_I32 Py,Px
MOV_I32 Px,Vz
L1:
GT_I32 T2,Px,C1
JF T2,L2
MOD_I32 T3,Py,Px
MOV_I32 Vz,T3
MOV_I32 Py,Px
MOV_I32 Px,Vz
JMP L1
L2:
RET_I32 Py
V sekvenčním mezikódu Základní blok
Začíná• Na začátku procedury• V cíli skoku• Za podmíněným skokem
Končí• Podmíněným skokem• Nepodmíněným skokem• Návratem z procedury• Před cílem skoku
35 Detekce základních blokůCONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
TMP:(T1,B),(T2,B),(T3,I32)
ENTER
GT_I32 T1,Px,Py
JF T1,L1
MOV_I32 Vz,Py
MOV_I32 Py,Px
MOV_I32 Px,Vz
L1:
GT_I32 T2,Px,C1
JF T2,L2
MOD_I32 T3,Py,Px
MOV_I32 Vz,T3
MOV_I32 Py,Px
MOV_I32 Px,Vz
JMP L1
L2:
RET_I32 Py
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
TMP:(T1,B),(T2,B),(T3,I32)
ENTERGT_I32 T1,Px,PyJC T1
GT_I32 T2,Px,C1JC T2
RET_I32 Py
MOV_I32 Vz,PyMOV_I32 Py,PxMOV_I32 Px,Vz
MOD_I32 T3,Py,PxMOV_I32 Vz,T3MOV_I32 Py,PxMOV_I32 Px,Vz
36 Detekce základních blokůint gcd( int x, int y){ int z; if ( x > y ) { z = y; y = x; x = z; } while ( x > 0 ) { z = y % x; y = x; x = z; } return y;}
Ve zdrojovém kódu Základní blok
Začíná• Na začátku procedury• Na začátku then a else bloku• Na začátku těla cyklu• Za if příkazem• Za while cyklem
Končí• Na konci procedury• Na konci then a else bloku• Na konci těla cyklu• Na konci podmínky v if• Na konci podmínky ve while• Příkazem return/break apod.
Komplikace Zkrácené vyhodnocování
booleovských výrazů Podmíněný výraz Příkaz goto
37 Detekce základních blokůint gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
TMP:(T1,B),(T2,B),(T3,I32)
ENTERGT_I32 T1,Px,PyJC T1
GT_I32 T2,Px,C1JC T2
RET_I32 Py
MOV_I32 Vz,PyMOV_I32 Py,PxMOV_I32 Px,Vz
MOD_I32 T3,Py,PxMOV_I32 Vz,T3MOV_I32 Py,PxMOV_I32 Px,Vz
38 Nesekvenční mezikód s hranicemi příkazůint gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
GT_I32
LD_I32(Px) LD_I32(Py)
JC
ENTER
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
GTC_I32(C1)
JC
LD_I32(Px)
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
LD_I32(Py)
RET_I32
Control-Flow
vždy
if true
if false
Dag
operand
39 Nesekvenční mezikód před analýzou aliasůint gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
GT_I32
LD_I32(Px) LD_I32(Py)
JC
ENTER
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
GTC_I32(C1)
JC
LD_I32(Px)
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
LD_I32(Py)
RET_I32
Control-Flow
vždy
if true
if false
Dag
operand
pořadí
40 Odstranění závislostí po analýze aliasů
LD_I32(Py)
ST_I32(Vz)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
MOD_I32
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
LD_I32(Px)
41 Odstranění závislostí po analýze aliasů
GT_I32
LD_I32(Px) LD_I32(Py)
JC
ENTER
GTC_I32(C1)
JC
LD_I32(Px)
LD_I32(Py)
RET_I32
LD_I32(Py)
ST_I32(Vz)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
GT_I32
LD_I32(Px) LD_I32(Py)
JC
ENTER
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
GTC_I32(C1)
JC
LD_I32(Px)
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
LD_I32(Py)
RET_I32
42 Nesekvenční mezikód po analýze aliasůint gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
GT_I32
LD_I32(Px) LD_I32(Py)
JC
ENTER
GTC_I32(C1)
JC
LD_I32(Px)
LD_I32(Py)
RET_I32
LD_I32(Py)
ST_I32(Vz)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
Control-Flow
vždy
if true
if false
Dag
dependence:
operand
w-r
w-?
antidependence:
r-w
?-w
43 Nesekvenční mezikód s rozsahy platnostiint gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
Dag
operand
antidependence:
r-w GT_I32
LD_I32(Px) LD_I32(Py)
JC
ENTER
GTC_I32(C1)
JC
LD_I32(Px)
LD_I32(Py)
RET_I32
LD_I32(Py)
ST_I32(Vz)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
Oblasti platnosti
Px
Py
Vz/1
Vz/2
44 Algoritmus: Určení rozsahů platnosti VAR – množina proměnných Orientovaný graf control-flow v proceduře: (BB,CF)
BB – množina základních bloků CF BB BB – přechody mezi základními bloky
Lokální analýza Vnitřní chování každého základního bloku W : BB VAR → Bool – blok zapisuje do proměnné R : BB VAR → Bool – blok čte proměnnou před prvním zápisem Triviální algoritmus
Globální analýza Platnost proměnných na začátku každého základního bloku L : BB VAR → Bool – proměnná je živá na začátku bloku Polynomiální algoritmus
Dopočet Platnost proměnných na koncích bloků a uvnitř bloků Detekce čtení nezapsaných proměnných Triviální algoritmus
Vylepšení Určení komponent souvislosti a přeznačení proměnných
45 Algoritmus: Určení rozsahů platnostiVstup
(BB,CF) – graf control flow W(b,v) – blok b zapisuje do proměnné v R(b,v) – blok b čte proměnnou v před prvním zápisem do ní
Výstup L(b,v) – proměnná v je živá na začátku bloku b
for each b in BB L(b,v) = R(b,v);do { for each <b1,b2> in CF L(b1,v) |= ~ W(b1,v) & L(b2,v);} while changed;
Algoritmus se provádí vektorově Pro všechny proměnné (v) najednou
• Překladač využije SIMD instrukce O(|BB|*|CF|*|VAR|)
46 Určení rozhraní BB
GT_I32
LD_I32(Px) LD_I32(Py)
JC
ENTER
GTC_I32(C1)
JC
LD_I32(Px)
LD_I32(Py)
RET_I32
LD_I32(Py)
ST_I32(Vz)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
GT_I32
LD_I32(Px) LD_I32(Py)
JC
ENTER
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Py)
ST_I32(Vz)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
GTC_I32(C1)
JC
LD_I32(Px)
LD_I32(Py)
RET_I32
47 Nesekvenční mezikód s rozhraními BBint gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
VAR:(Vz,I32,”z”)
Rozhraní 1
Px
Py
Rozhraní 2
Px
Py
GT_I32
LD_I32(Px) LD_I32(Py)
JC
ENTER
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Py)
ST_I32(Vz)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
GTC_I32(C1)
JC
LD_I32(Px)
LD_I32(Py)
RET_I32
Dag
operand
antidependence:
r-w
48 Náhrada proměnných rozhraním BB
GT_I32
JC
ENTER
GTC_I32(C1)
JC
RET_I32
MOD_I32
GT_I32
LD_I32(Px) LD_I32(Py)
JC
ENTER
LD_I32(Py)
ST_I32(Vz)
LD_I32(Px)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Py)
ST_I32(Vz)
ST_I32(Py)
LD_I32(Vz)
ST_I32(Px)
LD_I32(Px)
MOD_I32
GTC_I32(C1)
JC
LD_I32(Px)
LD_I32(Py)
RET_I32
49 Nesekvenční mezikód bez proměnnýchint gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
Dag
data
Rozhraní 1
Px
Py
Rozhraní 2
Px
Py
GT_I32
JC
ENTER
GTC_I32(C1)
JC
RET_I32
MOD_I32
50 Nesekvenční mezikód po duplikaci BBint gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
Dag
data
Rozhraní 1
Px
Py
Rozhraní 2
Px
PyRET_I32
GTC_I32(C1)
JC
GT_I32
JC
ENTER
MOD_I32
MOD_I32
GTC_I32(C1)
JC
RET_I32
51 Nesekvenční mezikód po přeznačeníint gcd( int x, int y)
{ int z;
if ( x > y )
{
z = y;
y = x;
x = z;
}
while ( x > 0 )
{
z = y % x;
y = x;
x = z;
}
return y;
}
CONST:(C1,I32,0)
PROC ”gcd”
PARAM:(Px,I32,”x”),(Py,I32,”y”)
RET_I32
GTC_I32(C1)
JC
GT_I32
JC
ENTER
MOD_I32
MOD_I32
GTC_I32(C1)
JC
RET_I32
52 Nesekvenční mezikód po přeznačení
int gcd( int x, int y)
{ if ( x > y )
goto L2;
L1:
if ( x <= 0 )
return y;
y = y % x;
L2:
if ( y <= 0 )
return x;
x = x % y;
goto L1;
}
RET_I32
GTC_I32(C1)
JC
GT_I32
JC
ENTER
MOD_I32
MOD_I32
GTC_I32(C1)
JC
RET_I32
53 Nesekvenční mezikód po optimalizaci skoků
int gcd( int x, int y)
{ if ( x > y )
goto L4;
if ( x <= 0 )
goto L3;
L1:
if ( (y = y % x) <= 0 )
goto L5;
L2:
if ( (x = x % y) > 0 )
goto L1;
L3:
return y;
L4:
if ( y > 0 )
goto L2;
L5:
return x;
}
GTC_I32(C1)
JC
MOD_I32
GTC_I32(C1)
JC
GTC_I32(C1)
JC
GTC_I32(C1)
JC
MOD_I32
RET_I32
GT_I32
JC
ENTER
RET_I32
L4
L3
L1
L2 L5
54 Architektura back-endu
Různé vnitřní reprezentaceMezikód střední úrovně
Nezávislá sada operací• ADD_I32 a,b,c
Forma• Nesekvenční
• Částečně sekvenční
Mezikód nízké úrovně Ekvivalenty strojových instrukcí
• add r1,r2
Forma• Nesekvenční
• Částečně sekvenční
• SekvenčníStrojově závislé optimalizace
Optimalizace
Generátor kódu
Strojově závislé optimalizace
Mezikód (střední úrovně)
Mezikód (střední úrovně)
Mezikód nízké úrovně
Cílový kód
Mezikód (střední úrovně)
55 Architektura back-endu
Sekvenční mezikód
Strojově závislé optimalizace
Alokace registrů
Sekvenční mezikódnízké úrovněs fyzickými registry
Strojově závislé optimalizace
Optimalizace
Instruction selection= Výběr instrukcí
Strojově závislé optimalizace
Sekvenční mezikód(střední úrovně)
Sekvenční mezikód(střední úrovně)
Sekvenční mezikódnízké úrovně s virtuálními registry
Sekvenčnímezikódnízké úrovněs virtuálními registry
Sekvenční mezikód(střední úrovně)
Finalizer
Sekvenční mezikód
Strojový kód
56 Architektura back-endu
Sekvenční mezikód
Alokace registrů
Optimalizace
Optimalizace
Instruction selection= Výběr instrukcí
Finalizer
Zjednodušená analýza rozsahů platnosti
Sekvenční mezikód (střední úrovně)
Sekvenční mezikód nízké úrovně s virtuálními registry
Sekvenční mezikód nízké úrovně s fyzickými registry
Strojový kód
Analýza aliasů
Optimalizace
57 Architektura back-endu
Částečně sekvenční mezikód bez schedulingu
Optimalizace
Alokace registrů
Optimalizace
Optimalizace
Instruction selection= Výběr instrukcí
Finalizer
Detekce základních bloků
Live-range analysis= Analýza rozsahů platnosti
Basic-block (re)ordering= Serializace control-flow
Sekvenční mezikód (střední úrovně)
Částečně sekvenční mezikód (střední úrovně)
Částečně sekvenční mezikód nízké úrovně s virtuálními registry
Částečně sekvenční mezikód nízké úrovně s fyzickými registry
Sekvenční mezikód nízké úrovně s fyzickými registry
Strojový kód
Analýza aliasů
Optimalizace
58 Architektura back-endu
Částečně sekvenční mezikód se schedulingem
Optimalizace
Alokace registrů
Optimalizace
Optimalizace
Instruction selection= Výběr instrukcí
Finalizer
Detekce základních bloků
Live-range analysis= Analýza rozsahů platnosti
Basic-block (re)ordering= Serializace control-flow
Sekvenční mezikód (střední úrovně)
Částečně sekvenční mezikód (střední úrovně)
Částečně sekvenční mezikód nízké úrovně s virtuálními registry
Částečně sekvenční mezikód nízké úrovně s fyzickými registry
Sekvenční mezikód nízké úrovně s fyzickými registry
Strojový kód
Analýza aliasů
Optimalizace
Instruction scheduling= Řazení instrukcí
Instruction scheduling= Řazení instrukcí
59 Architektura back-endu
Nesekvenční mezikód
Optimalizace
Alokace registrů
Optimalizace
Optimalizace
Instruction selection= Výběr instrukcí
Finalizer
Detekce základních bloků
Live-range analysis= Analýza rozsahů platnosti
Basic-block (re)ordering= Serializace control-flow
Sekvenční mezikód (střední úrovně)
Nesekvenční mezikód (střední úrovně)
Částečně sekvenční mezikód nízké úrovně s virtuálními registry
Částečně sekvenční mezikód nízké úrovně s fyzickými registry
Sekvenční mezikód nízké úrovně s fyzickými registry
Strojový kód
Analýza aliasů
Optimalizace
Instruction scheduling= Řazení instrukcí
Instruction scheduling= Řazení instrukcí
Nesekvenční mezikód nízké úrovně s virtuálními registry
60 Architektura back-endu
Instruction selection Výběr strojových instrukcí
• 1:n – přímočaré řešení
• m:n – stromové/grafové gramatiky apod.
Vliv na kvalitu kódu poklesl• RISC, load-store kód apod.
Instruction scheduling Řazení instrukcí pro lepší využití ILP (instruction-level parallelism)
• NP-úplná úloha
Lokální v BB• Speciální řešení smyček (software pipelining)
• Částečně globální varianty (trace scheduling)
Zrychluje kód o 30-150%
Register allocation Přidělování fyzických registrů
• NP-úplná úloha
• Standardní řešení: Barvení grafu
61 Architektura back-endu
ILP (instruction-level parallelism)Pipeline
Instrukce se zpracovává v několika fázích (stages)• fetch – read – execute – write
V jednom okamžiku se provádějí různé fáze různých instrukcí Závislosti po sobě jdoucích instrukcí způsobují:
• Pipeline stall – zdržení (i486)• Nekorektní provedení kódu (Sparc)
Superskalární procesory (MIMD) Několik výkonných jednotek (Pentium: 2) V jednom okamžiku se provádějí stejné fáze několika instrukcí
Vektorové procesory (SIMD) Mnoho výkonných jednotek (Cray: 64)
• Slabší varianty: Pentium MMX/SSE V jednom okamžiku se provádí tatáž instrukce mnohokrát Využití nepatří pod pojem scheduling
• Automatická vektorizace používá podobné algoritmy jako některé metody schedulingu
62 Alokace registrů
VstupČástečně sekvenční kód
Možnost přesně definovat rozsahy platnosti
Ekvivalenty strojových instrukcí Speciální zpracování přesunových instrukcí
Instrukce pracují s virtuálními registryOptimistický kód
Všechny jednoduché proměnné bez aliasu v registrech
Spočtené rozsahy platnosti proměnných Množina bodů v mezikódu, kde je proměnná živá
• Hranice základních bloků
• Hranice mezi instrukcemi
• Přesnější informace v místech, kde je proměnná čtena/zapisována
VýstupPřiřazení virtuálních registrů fyzickým
63 Alokace registrů
Optimalizace: Minimalizace přesunových instrukcíVytvoření matice kolizí
C : VAR VAR → Bool Matice je velká, ale potřebujeme rychlý přístup
Kolize = neprázný průnik oblastí platnosti Zvláštní posouzení okrajových doteků oblastí
Odhad ceny za spill-kódP : VAR → Integer
Odhad počtu použití proměnné v průměrném provedení procedury
Vlastní algoritmus alokaceBarvení grafu (VAR,C) n barvami
n je počet fyzických registrů NP-úplná úloha, dobré heuristické řešení
Doplnění spill-kódu
64 Alokace registrů
Barvení grafu (VAR,C) n barvamin je počet fyzických registrůNP-úplná úloha, dobré heuristické řešení
PrincipMá-li vrchol méně než n sousedů, lze jej vždy obarvit
Dvě fázePostupné odebírání vrcholů
Ve vhodném pořadí tak, aby později měly šanci na obarvení Odebrané vrcholy se ukládají na zásobník
Zpětná rekonstrukce grafu Vrcholy se odebírají ze zásobníku Pokud je lze obarvit, obarví se a přidají do grafu Neobarvitelné nebudou přiděleny do registru
65 Alokace registrů
Vstup: graf (VAR,C), ceny P, počet n(VAR2,C2) := (VAR,C)
while not empty(VAR2) do
if not exists v:VAR2 st deg(v,C2) < n then
select v st P(v) is minimal; // or deg(v,C2) is maximal
end if;
(VAR2,C2) := (VAR2-{v},C2-edges(v))
stack.push(v);
end while;
while not empty(stack) do
stack.pop(v)
M = {u VAR2; <v,u> C} if exists i {1..n} st not i color(M) then color(v) := i
(VAR2,C2) := (VAR2+{v},C2+)
else
spill(v) := true
end if
end while
Výstup: přidělení registrů color, nepřidělené registry spill
66 Alokace registrů
Optimalizace: Minimalizace přesunových instrukcíJednoduché řešení: Ztotožnit virtuální registry spojené
přesunovou instrukcí Nelze vždy – ztotožňované registry mohou spolu kolidovat Duplikace kódu může pomoci
Složitější řešení: Úprava algoritmu alokace Určení skupin uzlů svázaných přesunovými instrukcemi Při obarvování vybírat zároveň všechny obarvitelné uzly skupiny
67 Alokace registrů
Doplnění spill-kóduAlokovat neobarvené uzly na zásobníku
Podobný algoritmus barvení grafu s neomezeným n
Opatřit každou instrukci spill-kódem Prefix: Přesun neobarvených vstupních operandů do registrů Suffix: Přesun neobarvených výstupních operandů do paměti
Problém: kde vzít registry pro tyto operandy Jednoduché řešení: Rezervované nepřidělované registry Lepší řešení: Alokovat pomocné registry v rámci normální alokace
• Vstupy a výstupy každé instrukce označeny jako uzly grafu
• Nekolidují s virtuálními registry, na které se vážou
• Kolidují mezi sebou a s ostatními živými virtuálními registry
• Opatřeny nejvyšší cenou
Problém: spill-kód je často zbytečný Dodatečná optimalizace – eliminace redundantních přesunů
68 Alokace registrů
Množiny povolených registrůPro každý operand každé instrukce je určena množina
registrů, v nichž může být tento operandOrtogonální sada instrukcí
Každé dvě množiny povolených registrů jsou buď identické nebo disjunktní
Alokace registrů se spouští pro každou množinu zvlášťNeortogonální sada instrukcí
Množiny povolených registrů se simulují v grafu kolizí Přidat úplný podgraf uzlů vysoké priority - reprezentují fyzické
registry Spojit hranou všechny virtuální registry s těmi fyzickými, do kterých
nesmí být přiděleny
Problém: Nemusí existovat obarvení Odložení do paměti, přestože stačí přesun mezi registry
69 Alokace registrů
Další problémySubregistry
Intel IA-32: al-ax-eax-edx:eax Řešení:
• Povýšení na větší registr - neoptimální
• Různé triky při vytváření grafů kolizí
Registrové volací konvence Volání procedury se chová jako instrukce používající několik
registrů Neortogonální – volací konvence předepisuje, ve kterém registru má
být který operand• Často vede k neřešitelným kolizím – zbytečný spill-kód
Řešení: Rozsah platnosti proměnné se rozdělí na oblasti• Kolem každé instrukce, používající proměnnou, jedna oblast
• Oblasti se dotýkají v místě, kde by byla přesunová instrukce, pokud by byla zapotřebí
• Uzly reprezentující oblasti téže proměnné se přednostně obarvují toutéž barvou
70 Scheduling
Provádí se na jednom základním blokuTrace scheduling: Vybraná posloupnost BB slita do jednohoSoftware pipelining: Speciální řešení pro BB jako cyklus
VstupDag
Uzly = instrukce Hrany = závislosti
Model procesoru Latence – časování závislých dvojic instrukcí Rezervační tabulky – schopnosti paralelního zpracování
VýstupPřiřazení času každému uzlu dagu
Čas měřen cykly procesoru Instrukce trvá několik cyklů – zvolen referenční bod
• Obvykle začátek zpracování po načtení a dekódování instrukce
71 Scheduling
DagUzly = instrukceHrany = závislosti
Dependence vzniklé z předávání dat v registrech Dependence a antidependence z přístupů do paměti
• Opatrný přístup: Možná závislost => závislost
Antidependence vzniklé ze soupeření o registry• Při schedulingu po alokaci registrů
Další závislosti z technických příčin• Manipulace se zásobníkem, skoky apod.
Instrukce volání procedury „Nekonečně“ dlouhé časování Často považována za hranici mezi BB
• Omezená optimalizace přesunem přes volání
72 Scheduling
VýstupPřiřazení času každému uzlu dagu
Aplikace výstupu schedulinguBěžné procesory (Intel IA-32, včetně x86_64)
Seřazení instrukcí podle schedulovaného času Procesor nemusí dodržet předpokládaný čas
Procesory se sekvenčními body (Intel IA-64) V kódu jsou mezi instrukcemi označeny sekvenční body (stops) Procesor má právo přeházet pořadí instrukcí mezi sekvenčními
body• Ignorují se antidependence i některé dependence
Výstupem scheduleru jsou i sekvenční body
VLIW procesory Very Large Instruction Word
• Instrukce řídí paralelní činnost jednotek procesoru
Jeden schedulovaný čas = jedna instrukce
73 Scheduling
Scheduling pouze odhaduje skutečné časováníSkutečné časování je ovlivněno nepředvídatelnými jevy
Zbytky rozpracovaných instrukcí z předchozího BB• Řešení: Trace-scheduling, řízení profilem
Paměťová hierarchie• Doba přístupu k paměti závisí na přítomnosti v cache
• Obvykle se předpokládá nejlepší možný průběh
• Speciální problém: Multithreaded aplikace na multiprocesorech
Fetch bandwidth• Instrukce nemusí být načteny a dekódovány včas
• Zdržují skoky a soupeření o přístup do paměti
• Přesné simulování fetch jednotky by neúměrně komplikovalo scheduler
Scheduler nezná skutečné závislosti přístupů do paměti Musí postupovat opatrně a zohledňuje i nejisté závislosti Procesor zná skutečné adresy přístupů a detekuje pouze skutečné
závislosti• Agresivně optimalizující procesor může zvolit zcela jiné pořadí instrukcí
74 Scheduling
Model procesoruLatence – časování závislých dvojic instrukcí
Počet cyklů procesoru, který musí proběhnout mezi referenčními body závislých instrukcí
U antidependencí a ve speciálních případech může být nulová U procesorů se sekvenčními body může být záporná Latence se obvykle zapisuje ke hranám dagu
• Přiřazena na základě klasifikace závislosti podle tabulek latencí
75 Scheduling
Model procesoruRezervační tabulky – schopnosti paralelního zpracování
Procesor je rozdělen na funkční jednotky různých druhů Je určen počet jednotek každého druhu
• Limit: Kind -> N
Pro každou instrukci definována rezervační tabulka• Res(instr): Time × Kind → N
• Počet jednotek daného druhu, který instrukce potřebuje v daném čase (měřeno od referenčního bodu)
Rezervační tabulky jsou nutné i pro procesory, které nejsou super-skalární
• Mají Limit(k)=1, ale různé a tudíž konfliktní rezervační tabulky
76 Příklad – mezikód střední úrovně
char chksum( char * p, int i)
{
char s = 0;
while ( i > 0 )
{
s ^= *p++;
--i;
}
return s;
}
GTC_I32(C1)
JC
XLD_I8
RET_I32
GTC_I32(C1)
JC
ENTER
C_I8(C2)
ADDC_P(C3)
SUBC_I32(C4) XOR_I8
77 Příklad – mezikód nízké úrovně
char chksum( char * p, int i)
{
char s = 0;
while ( i > 0 )
{
s ^= *p++;
--i;
}
return s;
}
cmp ri,0
jgt
mov r1,[rp]
ret
cmp i,0
jgt
mov rs,0
inc rp
dec ri xor rs,r1
78 Příklad – latence Tabulka latencí
Instrukce-instrukce
Instrukce-konec BB• Pesimistická varianta
(instrukce musí být dokončena v tomto BB)
• Pesimistický přístup na konci BBumožňuje optimistiký přístup na začátku: Latence začátek BB-instrukce jsou považovány za nulové
• Instrukce jgt musí být poslední• Latence vůči konci BB se
normalizují odečtením latence jgt
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r1
4
2
1
z instrukce do instrukce čas
cmp ri,0 jgt 1
mov r1,[rp] xor rs,r1 4
dec ri cmp ri,c 2
mov r1,[rp] inc rp 0
z instrukce čas
inc rp 2
jgt 1
dec ri 2
xor rs,r1 2
1
11
0
79
Rezervační tabulky
Příklad – rezervační tabulky
Kapacita procesoru
inc r1dec r1xor r1,r2cmp r1,r2
R MEM ALU W
0 1
1 1
2 1
mov r1,[r2] R MEM ALU W
0 1
1 1
2 1
3 1
4 1
jgt R MEM ALU W
0 1
R MEM ALU W
1 1 2 1
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r1
4
2
1
1
11
0
80
Krok 1Připravené instrukce
inc rp dec ri mov r1,[rp]
Kritická cesta mov r1,[rp] – 5
Vybrána instrukce mov r1,[rp]
Umístěna do času 0
Příklad – scheduling
čas R MEM ALU W
0 mov
1 mov
2 mov
3 mov
4 mov
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r1
4
2
1
1
11
0
81
Krok 2Připravené instrukce
inc rp dec ri xor rs,r1
Kritická cesta xor rs,r1 – 5
Vybrána instrukce xor rs,r1
Čas 4 určen latencí
Příklad – scheduling
čas R MEM ALU W
0 mov
1 mov
2 mov
3 mov
4 xor mov
5 xor
6 xor
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r1
4
2
1
1
11
0
0
82
Krok 3Připravené instrukce
inc rp dec ri
Kritická cesta dec ri - 4
Vybrána instrukce dec ri
Čas 0 vyhovuje latenci Rezervační tabulky jsou
obsazeny
Zvolen čas 1
Příklad – scheduling
čas R MEM ALU W
0 mov
1 dec mov
2 mov dec
3 mov dec
4 xor mov
5 xor
6 xor
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r14
2
1
1
11
0
0
83
Krok 4Připravené instrukce
inc rp cmp ri,0
Kritická cesta cmp ri,0 – 4
Vybrána instrukce cmp ri,0 – 4
Čas 3 určen latencí
Příklad – scheduling
čas R MEM ALU W
0 mov
1 dec mov
2 mov dec
3 cmp mov dec
4 xor cmp mov
5 xor cmp
6 xor
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r1
4
2
1
1
11
0
1
0
84
Krok 5Připravené instrukce
inc rp (jgt) – musí být poslední
Vybrána instrukce inc rp
Čas 0 vyhovuje latenciRezervační tabulky pro
časy 0-4 obsazenyUmístěno v čase 5
Příklad – scheduling
čas R MEM ALU W
0 mov
1 dec mov
2 mov dec
3 cmp mov dec
4 xor cmp mov
5 inc xor cmp
6 inc xor
7 inc
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r1
4
3
1
1
11
0
1
0
85
Krok 6Připravené instrukce
jgt
Latenci vyhovuje čas 4 Instrukce však musí být
poslední
Vybrán čas 5
Příklad – scheduling
čas R MEM ALU W
0 mov
1 dec mov
2 mov dec
3 cmp mov dec
4 xor cmp mov
5 inc xor, jgt cmp
6 inc xor
7 inc
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r1
4
3
1
1
11
0
1
5
86
Čas 6Připravené instrukce
jgt
Příklad – scheduling
čas R MEM ALU W
0 mov
1 dec mov
2 mov dec
3 cmp mov dec
4 inc cmp mov
5 xor inc, jgt cmp
6 xor inc
7 xor
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r15
3
1
1
11
0
1
40
87
char chksum( char * p, int i)
{
char s = 0;
while ( i > 0 )
{
s ^= *p++;
--i;
}
return s;
}
Výsledný kód
mov r1,[rp]
dec ri
cmp ri,0
xor rs,r1
inc rp
jgt
Příklad – scheduling
čas R MEM ALU W
0 mov
1 dec mov
2 mov dec
3 cmp mov dec
4 xor cmp mov
5 inc xor, jgt cmp
6 inc xor
7 inc
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r14
3
5
1
11
0
1
5
88 Scheduling
Základní algoritmus: „List scheduling“V grafu závislostí s latencemi se pro každý uzel spočte
délka kritické, tj. nejdelší cesty ke konciV každém kroku se určí připravené instrukce a z nich se
vybere nejvhodnější Přednost mají instrukce s nejdelší kritickou cestou Mezi nimi se vybírá podle dalších heuristik
Při správné implementaci má tento postup složitost O(n2)Vylepšené algoritmy
Posun směrem k exhaustivnímu prohledávání všech možností
Branch-and-bound přístup: Zkouší se všechny možnosti v pořadí od nejnadějnější, nalezené list
schedulingem Beznadějné pokusy se včas zastaví porovnáváním odhadů
úspěšnosti výsledku pomocí kritických cest s doposud známým nejlepším řešením
89
Výsledný kód
mov r1,[rp]
dec ri
cmp ri,0
inc rp
xor rs,r1
jgt
Chování ve smyčce Za předpokladu správné
predikce skoku procesorem Výkon: 1/6 iterace/cyklus Využití jednotek:
• R: 5/6
• MEM: 3/6
• ALU: 5/12
• W: 5/6
Příklad – scheduling
čas R MEM ALU W
0 mov
1 dec mov
2 mov dec
3 cmp mov dec
4 inc cmp mov
5 xor inc, jgt cmp
6 mov xor inc
7 dec mov xor
8 mov dec
9 cmp mov dec
10 inc cmp mov
11 xor inc, jgt cmp
12 mov xor inc
13 dec mov xor
14 mov dec
15 cmp mov dec
90
Efekt kapacity procesoru
Stejné latence i res. tabulky
mov r1,[rp]
dec ri
inc rp
cmp ri,0
xor rs,r1
jgt
Výkon: 1/5 iterace/cyklus Využití jednotek:
• R: 5/10
• MEM: 3/5
• ALU: 5/10
• W: 5/10
Příklad – scheduling
čas R MEM ALU W
0 mov, dec
1 inc mov dec
2 cmp mov inc dec
3 mov cmp inc
4 xor jgt mov, cmp
5 mov, dec xor
6 inc mov dec xor
7 cmp mov inc dec
8 mov cmp inc
9 xor jgt mov, cmp
10 mov, dec xor
11 inc mov dec xor
12 cmp mov inc dec
13 mov cmp inc
14 xor jgt mov, cmp
R MEM ALU W
2 1 2 2
91
Závislosti uvnitř BB
Závislosti přes hranice BB(loop-carried dependences)
Příklad – software pipelining
z instrukce do instrukce čas
cmp ri,0 jgt 1
mov r1,[rp] xor rs,r1 4
dec ri cmp ri,c 2
mov r1,[rp] inc rp 0
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r1
4
2
1 0
2
2
2
1 0
z instrukce do instrukce čas
inc rp inc rp 2
inc rp mov r1,[rp] 2
dec ri dec ri 2
cmp ri,0 dec ri 0
xor rs,r1 xor rs,r1 2
xor rs,r1 mov r1,[rp] 0
jgt cmp ri,0 1
jgt mov r1,[rp] 1
1
0
2
92 Příklad – software pipelining
Jiná abstrakcelatence/iterace
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri
xor rs,r1
2/1
2/1
2/1
2/1 1/1
1/0
2/0
4/0
0/1
1/1
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri xor rs,r1
4
2
1 0
2
2
2
1 0
1
0
2
0/0
0/1
93 Příklad – software pipelining
čas R MEM ALU W
0 mov1, dec1
1 inc1 mov1 dec1
2 cmp1 mov1 inc1 dec1
3 dec2 mov1 cmp1, jgt1 inc1
4 xor1, mov2 dec2 mov1, cmp1
5 inc2, cmp2 mov2 xor1 dec2
6 dec3 mov2 inc2, cmp2 xor1
7 mov2 dec3, jgt2 inc2, cmp2
8 xor2, mov3 mov2, dec3
9 inc3, cmp3 mov3 xor2
10 dec4 mov3 inc3, cmp3 xor2
11 mov3 dec4, jgt3 inc3, cmp3
12 xor3, mov4 mov3, dec4
13 inc4, cmp4 mov4 xor3
14 dec5 mov4 inc4, cmp4 xor3
15 mov4 dec5, jgt4 inc4, cmp4
16 xor4, mov5 mov4, dec5
17 inc5, cmp5 mov5 xor4
18 dec6 mov5 inc5, cmp5 xor4
19 mov5 dec6, jgt5 inc5, cmp5
20 xor5 mov5, dec6
21 xor5
22 xor5
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri
xor rs,r1
2/1
2/1
2/1
2/1 1/1
1/0
2/0
4/0
0/1
1/1
0/0
0/1
94 Příklad – software pipelining
čas R MEM ALU W
0 mov1, dec1
1 inc1 mov1 dec1
2 cmp1 mov1 inc1 dec1
3 dec2 mov1 cmp1, jgt1 inc1
4 xor1, mov2 dec2 mov1, cmp1
5 inc2, cmp2 mov2 xor1 dec2
6 dec3 mov2 inc2, cmp2 xor1
7 mov2 dec3, jgt2 inc2, cmp2
8 xor2, mov3 mov2, dec3
9 inc3, cmp3 mov3 xor2
10 dec4 mov3 inc3, cmp3 xor2
11 mov3 dec4, jgt3 inc3, cmp3
12 xor3, mov4 mov3, dec4
13 inc4, cmp4 mov4 xor3
14 dec5 mov4 inc4, cmp4 xor3
15 mov4 dec5, jgt4 inc4, cmp4
16 xor4, mov5 mov4, dec5
17 inc5, cmp5 mov5 xor4
18 dec6 mov5 inc5, cmp5 xor4
19 mov5 dec6, jgt5 inc5, cmp5
20 xor5 mov5, dec6
21 xor5
22 xor5
Software pipelining“Unroll-and-compact”
Rozvrhuje se rozvinutý cyklus tak dlouho, dokud nevznikne opakující se vzorek
• Perioda opakování může odpovídat více iteracím
Problém: Není jasné, co je to kritická cesta
• Hledá se kritická smyčka
95 Software pipelining
„Modulo scheduling“ Analýzou grafu závislostí se
odhadne počet cyklů na iteraci
• Sčítají se ohodnocení hran ve smyčkách dvojicemi latence/iterace
• Rozhoduje nejvyšší podíl součtů na smyčce, např. 4/1
Hledá se rozvrh s daným počtem cyklů na iteraci
• Nemusí existovat – opakuje se pro větší počet
Složitější verze zvládají necelé počty cyklů na iteraci
• Pokud je v grafu závislostí kritická smyčka se součtem ohodnocení např. 5/2
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri
xor rs,r1
2/1
2/1
2/1
2/1 1/1
1/0
2/0
4/0
0/1
1/1
0/0
0/1
96 Modulo scheduling
Zvolená perioda M Rezervační tabulky jsou používány
modulo M: časy 0..(M-1) Instrukce jsou rozmisťovány do
dvojrozměrného prostoru čas/iterace
Rozvrh vyhovuje závislosti
pokud(TB-TA)-M*(IB-IA) ≥ L-M*D
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri
xor rs,r1
2/1
2/1
2/1
2/1 1/1
1/0
2/0
4/0
0/1
1/1
0/0
0/1
čas R MEM ALU W
T+0 xor[N], mov[N+1]
mov[N], dec[N+1]
T+1 inc[N+1], cmp[N+1]
mov[N+1] xor[N]
T+2 dec[N+2] mov[N+1] inc[N+1], cmp[N+1]
xor[N]
T+3 mov[N+1] dec[N+2], jgt[N+1]
inc[N+1], cmp[N+1]
1/11/1
2/2
3/1
0/1
0/0
BAL/D
TB/IBTA/IA
97 Modulo scheduling
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri
xor rs,r1
2/1
2/1
2/1
2/1 1/1
1/0
2/0
4/0
0/1
1/1
0/0
0/1
čas R MEM ALU W
0 xor2, mov3 mov2, dec3
1 inc3, cmp3 mov3 xor2
2 dec4 mov3 inc3, cmp3 xor2
3 mov3 dec4, jgt3 inc3, cmp3
4 xor3, mov4 mov3, dec4
5 inc4, cmp4 mov4 xor3
6 dec5 mov4 inc4, cmp4 xor3
7 mov4 dec5, jgt4 inc4, cmp4 1/11/1
2/2
3/1
0/1
0/0
98 Příklad – software pipelining
čas R MEM ALU W
0 mov1, dec1
1 inc1 mov1 dec1
2 cmp1 mov1 inc1 dec1
3 dec2 mov1 cmp1, jgt1 inc1
4 xor1, mov2 dec2 mov1, cmp1
5 inc2, cmp2 mov2 xor1 dec2
6 dec3 mov2 inc2, cmp2 xor1
7 mov2 dec3, jgt2 inc2, cmp2
8 xor2, mov3 mov2, dec3
9 inc3, cmp3 mov3 xor2
10 dec4 mov3 inc3, cmp3 xor2
11 mov3 dec4, jgt3 inc3, cmp3
12 xor3, mov4 mov3, dec4
13 inc4, cmp4 mov4 xor3
14 dec5 mov4 inc4, cmp4 xor3
15 mov4 dec5, jgt4 inc4, cmp4
16 xor4, mov5 mov4, dec5
17 inc5, cmp5 mov5 xor4
18 dec6 mov5 inc5, cmp5 xor4
19 mov5 dec6, jgt5 inc5, cmp5
20 xor5 mov5, dec6
21 xor5
22 xor5
Výsledek pro příklad Výkon: 1/4 iterace/cyklus
• Zlepšení o 25%
Využití jednotek:• R: 5/8
• MEM: 3/4
• ALU: 5/8
• W: 5/8
Poslední opakování vzorku provede zbytečně instrukci dec
• To není chyba
Vytvoření kódu z rozvrhuProlog-smyčka-epilogDokončení pro odbočky
99 Příklad – software pipelining
čas R MEM ALU W
0 mov1, dec1
1 inc1 mov1 dec1
2 cmp1 mov1 inc1 dec1
3 dec2 mov1 cmp1, jgt1 inc1
4 xor1, mov2 dec2 mov1, cmp1
5 inc2, cmp2 mov2 xor1 dec2
6 dec3 mov2 inc2, cmp2 xor1
7 mov2 dec3, jgt2 inc2, cmp2
8 xor2, mov3 mov2, dec3
9 inc3, cmp3 mov3 xor2
10 dec4 mov3 inc3, cmp3 xor2
11 mov3 dec4, jgt3 inc3, cmp3
12 xor3, mov4 mov3, dec4
13 inc4, cmp4 mov4 xor3
14 dec5 mov4 inc4, cmp4 xor3
15 mov4 dec5, jgt4 inc4, cmp4
16 xor4, mov5 mov4, dec5
17 inc5, cmp5 mov5 xor4
18 dec6 mov5 inc5, cmp5 xor4
19 mov5 dec6, jgt5 inc5, cmp5
20 xor5 mov5, dec6
21 xor5
22 xor5
mov r1,[rp]
dec ri
inc rp
cmp ri,0
jle l2
dec ri
l1:
xor rs,r1
mov r1,[rp]
inc rp
cmp ri,0
dec ri
jgt l1
l2:
xor rs,r1
100 Software pipelining
Duplikace proměnných (Variable expansion)
Duplikací proměnných lze odstranit některé antidependence
• Teoreticky všechny registrové, roste však počet použitých registrů i velikost kódu
Duplikace proměnných se provede duplikací kódu a vhodným přeznačením
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri
xor rs,r1
2/1
2/1
2/1
2/1 1/1
1/0
2/0
4/0
0/1
1/1
0/0
0/1
101 Variable expansion
Duplikace proměnných (Variable expansion)
Duplikací proměnných lze odstranit některé antidependence
• Teoreticky všechny registrové, roste však počet použitých registrů i velikost kódu
Duplikace proměnných se provede duplikací kódu a vhodným přeznačením
Příklad: Zdvojením proměnné r1 se kritický cyklus zkrátí z poměru 4/1 na 4/2
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri
xor rs,r1
2/1
2/1
2/1
2/11/1
1/0
2/0
4/0
0/2
1/1
0/0
0/1
cmp ri,0
jgt
mov r2,[rp]
inc rp
dec ri
xor rs,r2
2/1
2/1
2/1
2/1 1/1
1/0
2/0
4/0
0/2
1/1
0/0
0/1
102 Software pipelining
Duplikace proměnných (Variable expansion)
Duplikací proměnných lze odstranit některé antidependence
• Teoreticky všechny registrové, roste však počet použitých registrů i velikost kódu
Duplikace proměnných se provede duplikací kódu a vhodným přeznačením
• Duplikaci je možné provést až po schedulingu, který odhalí, která duplikace je užitečná
• Před schedulingem se odstraní antidependence odstranitelné duplikací
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri
xor rs,r1
2/1
2/1
2/1
2/1 1/1
1/0
2/0
4/0
1/1
103 Příklad – modulo scheduling s duplikací
čas R MEM ALU W
0 xor2, inc3 mov3 dec4, jgt3 mov2, cmp3
1 cmp4 mov3 xor2, inc3 dec4
2 mov4, dec5 mov3 cmp4 xor2, inc3
l1:
xor rs,r1 ; čas 0, iterace 2
inc rp ; čas 0, iterace 3
cmp ri,0 ; čas 1, iterace 4
mov r1,[rp] ; čas 2, iterace 4
dec ri ; čas 2, iterace 5
jle l2 ; čas 3, iterace 4
xor rs,r2 ; čas 3, iterace 3
inc rp ; čas 3, iterace 4
cmp ri,0 ; čas 4, iterace 5
mov r2,[rp] ; čas 5, iterace 5
dec ri ; čas 5, iterace 6
jgt l1 ; čas 6, iterace 5
l2:
cmp ri,0
jgt
mov r1,[rp]
inc rp
dec ri
xor rs,r1
2/1
2/1
2/1
2/1 1/1
1/0
2/0
4/0
1/1
0/0
0/1
0/11/2
2/3
0/1
2/2
0/0
0/2
104 Příklad – Intel compiler – x64
/*...*/
k = i >> 1;
j = 0;
do {
r8 = *p;
r9 = *(p+1);
s ^= r8;
s ^= r9;
p += 2;
j += 1;
} while ( j < k );
/* ... */
char chksum( char * p, int i)
{
char s = 0;
while ( i > 0 )
{
s ^= *p++;
--i;
}
return s;
}
..B1.4: movsbq (%rdi), %r8
movsbq 1(%rdi), %r9
xorl %r8d, %eax
xorl %r9d, %eax
addq $2, %rdi
addl $1, %ecx
cmpl %edx, %ecx
jb ..B1.4
Cray 1 105
Cray 1 106
Cray 1 107
Cray 1 108
109 Paralelizace
HardwareProč paralelizace?
Zrychlení stojí příliš mnoho energie•P = k f2
Místa je dost (108 tranzistorů/chip)
Jak paralelizovat?ve světě Intel (IA-32)
•Pipelining (1989: i486) – bez duplikace
•Superskalarita (1993: Pentium) – duplikace ALU, původní instrukce
•SIMD (1996: Pentium MMX) – duplikace ALU, nové instrukce
•Hyperthreading (1998: Xeon) – duplikace registrů
•Multi-core (2005: Core 2 Duo) – duplikace CPU
jinde•Vektorové instrukce (1974: Cray) – částečná duplikace
110 Paralelizace
Z pohledu softwareJemnozrnný paralelismus
ILP•Pipelining
•Superskalarita
SIMD•Mírně vektorové instrukce (2-8)
•Vektorové instrukce (64)
Hrubozrnný paralelismusSMP
•Hyperthreading
•Multi-core
•Multi-socket
NUMA•Multi-core a multi-socket (cc-NUMA)
•NUMA architektury
Cluster
111 Paralelizace
Z pohledu překladačeJemnozrnný paralelismus
ILP•Scheduling, software pipelining – změna pořadí instrukcí
Vektorizace - automatické použití SIMD instrukcí•Překladač vybírá speciální instrukce
•Překladač určuje pořadí provádění
Hrubozrnný paralelismusSMP – Multithreading
•Strip-Mining - Překladač dělí kód na nezávislé bloky
•Pořadí provádění je náhodné
112 Paralelizace
VektorizaceNízký stupeň (2-8)
Náhodné seskupovánía = b + c; d = e + f;
Vektorové seskupovánía[i] = b[i] + c[i]; a[i+1] = b[i+1] + c[i+1];
• Rozvíjení cyklů podle dostupného stupně vektorizace
Vysoký stupeň (64) Aplikovatelné na cykly s afinním chováním
• Numerické aplikace (FORTRAN 90)
• Nepoužitelné při nebezpečí aliasingu (objektové programování)
Řada afinních transformací cyklů• Loop Reversal
• Loop Skewing
Loop reversal
Výměna vzájemného zanoření cyklůPříklad: Učebnicový zápis násobení matic
for I := 1 to M do
for J := 1 to N do
for K := 1 to P do
C[I,J] := C[I,J]+A[I,K]*B[K,J]
Nelze paralelizovat - následující iterace závisí na předchozí
Po výměně zanoření cyklů K/Jfor I := 1 to M do
for K := 1 to P do
for J := 1 to N do
C[I,J] := C[I,J]+A[I,K]*B[K,J]
Překladač si musí být jistý zachováním semantiky• Je nutno vyloučit aliasing C=A resp. C=B
Tato úprava může zhoršit chování vzhledem k cache• Závisí na rozměrech P, N
V nenumerických aplikacích je užitečnost nejistá
113
Loop reversal
Původní průchod• Většina sousedů v průchodu je závislá
114
K
J
Loop reversal
Upravený průchod• Většina sousedů v průchodu je nezávislá
115
K
J
Loop skewing
Obecnější příklad
for J:=1 to N do
for K:=N-J to P do
A[J,K]:=A[J-1,K]+A[J,K-1]
116
K
J
Loop skewing
Obecnější příklad
for J:=1 to N do
for K:=N-J to P do
A[J,K]:=A[J-1,K]+A[J,K-1]
117
K
J
Loop skewing
Loop skewing
for J:=1 to N do
for K:=N-J to P do
A[J,K]:=A[J-1,K]+A[J,K-1]
Prostor iterací = prostor k-tic řídících proměnných• Hranice dány lineárními nerovnicemi (s konstantními koeficienty)
Detekce závislostí mezi iteracemi• Přístupy do paměti (indexy) určeny lineárními výrazy (s k. k.)
Směry (vektory) závislostí popisují zakázané směry iterací• Hledá se vektor ležící mimo konvexní obal vektorů závislostí
Výsledná smyčka pro jemnozrnnou paralelizaci• Vnější iterace: Vektor (vektory) v konvexním obalu závislostí• Vnitřní iterace: Vektor (vektory) mimo konvexní obal závislostí
Složitější případy: Prostor iterací se dělí na části řešené zvlášť• Zjednodušení mezí cyklů: dělení na části jednoduchých tvarů
118
Hrubozrnná paralelizace
Hrubozrnná paralelizace
Velká běhová režie• Vytváření vláken/úloh, plánování
Vyžaduje relativně velké na sobě nezávislé bloky Předvídatelně velké bloky: Počet bloků odpovídá počtu CPU Nepředvídatelně velké bloky: Počet bloků větší než počet CPU
• Bloky se přidělují na CPU dynamicky
Různé schopnosti běhového prostředí Vlákna bez vzájemné synchronizace
• Bloky na sobě nesmějí vůbec záviset
Pipeline parallelism, task parallelism• Plánovač respektuje vzájemné závislosti bloků
• Závislosti nesmějí být cyklické
119
Strip mining
Hledání zcela nezávislých bloků
120
K
J
Hrubozrnná paralelizace
Hrubozrnná paralelizace
Bloky k paralelizaci je třeba vybírat v horních patrech iterací Zajištění dostatečné velikosti bloků
Smyčku je vhodné upravit, aby vnější iterace nebyly závislé Stejné metody jako u jemnozrnné paralelizace, ale opačný cíl
Loop skewing pro hrubo- i jemnozrnnou paralelizaci Vnější iterace nezávislé (pro hrubozrnnou paralelizaci) Střední iterace závislé Vnitřní iterace nezávislé (pro jemnozrnnou paralelizaci)
Problém: Vrstev iterací je obvykle málo• Středních iterací musí být dost na pokrytí konvexního obalu závislostí
121
Hrubozrnná paralelizace
Problém: Vrstev iterací je obvykle málo
Řešení: BlockingProstor iterací se rozdělí na menší díly (bloky)
Tím vznikají další úrovně iterace
Iterace nad bloky se uspořádají pro hrubozrnný paralelismus
Vnější iterace řeší nezávislé skupiny bloků• Strip mining: Vlákna
Vnitřní iterace procházejí závislé bloky uvnitř skupin• Task parallelism: Tasky
Iterace uvnitř bloky se upraví pro jemnozrnný paralelismus Vnější iterace jsou závislé Vnitřní iterace jsou bez závislostí
• SIMD, ILP
122
Blocking
Vytvoření bloků
123
K
J
Blocking
Strip mining nad bloky
124
K
J
Blocking
Loop skewing uvnitř bloků
125
K
J
Blocking
Blocking Původní iterace rozděleny
na 2 patra• Vždy ekvivalentní
• Problémy se zbytky
Nové iterace promíchány• Pouze některé výměny
jsou možné
• Cílem je nezávislostv okrajových patrech
parallel for J1 := 0 to N-1 step SJ do
for K1 := 0 to P-1 step SK do
for K2 := 1 to SK do
parallel for J2 := 1 to SJ do
begin
J := J1 * SJ + J2;
K := K1 * SK + K2;
C[I,J] := C[I,J]+A[I,K]*B[K,J]
end
126
K
J
Blocking
Blocking Implementace vlákny
for J1 := 0 to N-1 step SJ do
create_thread( f, J1);
wait();
function f( J1)
begin
for K1 := 0 to P-1 step SK do
for K2 := 1 to SK do
parallel for J2 := 1 to SJ do
begin
J := J1 * SJ + J2;
K := K1 * SK + K2;
C[I,J] := C[I,J]+A[I,K]*B[K,J]
end
end
127
K
J
Blocking
Blocking Task parallelism
for J1 := 0 to N-1 step SJ do
for K1 := 0 to P-1 step SK do
begin
TN := new_task( f, J1, K1);
add_dep( TP, TN); TP := TN;
end;
run();
function f( J1, K1)
begin
for K2 := 1 to SK do
parallel for J2 := 1 to SJ do
begin
J := J1 * SJ + J2;
K := K1 * SK + K2;
C[I,J] := C[I,J]+A[I,K]*B[K,J]
end
end
128
K
J
Optimalizace pro cache
Podmínky dobrého využití cache Prostorová lokalita
• Jednotkou přístupu je cache line (typ. 64 B)
• Přístupy do sousedních míst mají být blízko, nejlépe najednou
• Zápisy také způsobují výpadky - antidependence se řeší také
Časová lokalita• Čím delší je doba mezi přístupy, tím větší je pravděpodobnost výpadku
• Přístupy k témuž paměťovému místu je výhodné v čase rozmístit nepravidelně
129
Další optimalizace
130
131 Architektura překladače
Detailní pohled akademika (pouze optimalizace)• Muchnick: Advanced Compiler Design and Implementation
Scalar replacement of array referencesData-cache optimizations
Procedure integrationTail-call optimizationScalar replacement of aggregatesSparse conditional constant propagationInterprocedural constant propagationProcedure specialization and cloningSparse conditional constant propagation
Global value numberingLocal and global copy propagationSparse conditional constant propagationDead-code eliminationLocal and global common-subexpression eliminationLoop-invariant code motionDead-code eliminationCode hoistingInduction-variable strength reductionLinear-function test replacementInduction-variable removalUnnecessary bounds-checking eliminationControl-flow optimizations
In-line expansionLeaf-routine optimizationShrink wrappingMachine idiomsTail mergingBranch optimizations and conditional movesDead-code eliminationSoftware pipelining, loop unrollingBasic-block and branch schedulingRegister allocationBasic-block and branch schedulingIntraprocedural I-cache optimizationInstruction prefetchingData prefetchingBranch prediction
Interprocedural register allocationAggregation of global referencesInterprocedural I-cache optimization
Constant foldingAlgebraic simplification and reassociation
132 Další optimalizace
Částečné vyhodnocení Část požadovaného výpočtu je vyhodnocována již překladačem
Výpočet konstantních výrazů Constant-expression evaluation (constant folding)
Výpočet podmíněně konstantních výrazů Sparse conditional constant propagation
Algebraické úpravy Využití algebraických identit ke zjednodušení kódu
Algebraické úpravy výrazůRedukce síly v cyklech
Strength reduction
Odstranění zbytečných kontrol mezí
133 Další optimalizace
Odstranění redundance Nahrazení opakovaných výpočtů uložením výsledku
Copy propagation Lokální/globální eliminace společných podvýrazů
Common-subexpression elimination Přesun invariantního kódu z cyklu
Loop-invariant code motion Partial-redundancy elimination
Lazy code motion
Odstranění neužitečného kódu Odstranění mrtvého kódu
Dead-code elimination Odstranění nedosažitelného kódu
Unreachable-code elimination Optimalizace skoků
Jump optimization
134 Částečné vyhodnocení
Výpočet (pod)výrazů obsahujících pouze konstanty
Constant-expression evaluation
Obvykle prováděn již front-endem
Určení proměnných s konstantním obsahem
Constant folding
Určení proměnných s podmíněně konstantním obsahem
Sparse conditional constant propagation
Upravuje control-flow!
a = b + (4 * 10);
c = 4 * 10;
d = c + 5;
e = f + (d * 2);
if ( g > h )
i = 1;
else
i = 0;
j = i + 1;
if ( j > 1 )
k = k + 1;
135 Částečné vyhodnocení
Výpočet (pod)výrazů obsahujících pouze konstanty
Constant-expression evaluation
Obvykle prováděn již front-endem
Určení proměnných s konstantním obsahem
Constant folding
Určení proměnných s podmíněně konstantním obsahem
Sparse conditional constant propagation
Upravuje control-flow!
Integrace procedur generuje nové příležitosti pro částečné vyhodnocení
void f( int i, bool f)
{
int j = i + 1;
if ( f )
g( j);
else
h( j);
}
f( k + 1, false);
136 Částečné vyhodnocení
a = b + 40;
c = 40;
d = 45;
e = f + 90;
if ( g > h )
{
i = 1;
j = 2;
k = k + 1;
}
else
{
i = 0;
j = 1;
}
a = b + (4 * 10);
c = 4 * 10;
d = c + 5;
e = f + (d * 2);
if ( g > h )
i = 1;
else
i = 0;
j = i + 1;
if ( j > 1 )
k = k + 1;
137 Algebraické úpravy
Algebraické úpravy výrazů Většinou v souvislosti s
přítomností konstant Důležité pro ukazatelovou
aritmetiku (přístup k polím) Úprava do kanonického
tvaru
Redukce síly v cyklech Důležité pro přístup k polím
Odstranění zbytečných kontrol mezí
Machine idioms Instrukce provádějící speciální
kombinace nebo varianty operací
a = ((b * 3) + 7) * 5
a = b * 15 + 35
for ( i = 1; i < 10; ++i )
a[ 4 * i] = 0;
for ( j = 4; j < 40; j += 40 )
a[ j] = 0;
int b[ 10];
for ( i = 0; i < 10; ++i )
b[ i] = 0;
138 Algebraické úpravy
Převedení control-flow na algebraické operace
Conditional move Ušetří podmíněné skoky Může přidat zbytečné operace
Užitečnost obtížně odhadnutelná
Cena podmíněných skoků závisí na úspěšnosti predikce
Překladač úspěšnost nedokáže odhadnout
Profilem řízené optimalizace
if ( a > b )
c = d + e;
CMP t,a,b
ADD u,d,e
CMOV t,c,u
139 Odstranění redundance
Copy propagationLokální/globální eliminace
společných podvýrazůPřesun invariantního kódu
z cyklu Častý výskyt u přístupu k
polím
Partial-redundancy elimination
Lazy code motion
Integrace procedur generuje nové redundance
b = a;
c = b; // c = a;
c = a + b;
d = a + b; // d = c;
for ( i = 0; i < 10; ++i)
a[ i] = k + l;
if ( a < b )
c = d + e;
f = d + e;
140 Odstranění neužitečného kódu
Odstranění mrtvého kódu Kód, jehož efekt nebude
využit• Přiřazení do proměnných,
které již nebudou čteny
Odstranění nedosažitelného kódu
Kód, ke kterému nevede cesta
Optimalizace skoků Skoky na skoky apod.
Řeší především chyby vyprodukované předchozími fázemi
Aplikuje se opakovaně
a = b + 40;
c = 40;
d = 45;
e = f + 90;
if ( g > h )
{
i = 1;
j = 2;
k = k + 1;
}
else
{
i = 0;
j = 1;
}
141 Přesouvání kódu
Code hoisting Provedení operace dříve,
než předepisoval původní program
Omezeno závislostmi „very busy“ expression =
operace, která bude provedena v každém pokračování
Algoritmus: Lazy code motion
Užitečnost úpravy je nejistá Paralelismus Omezený počet registrů
if ( g > h )
{
for ( i = 1; i < k; ++ i)
{ a[ i] = x + y;
}
u = x + y;
}
else
{
z = x + y;
}
142 Optimalizace režie volání
Integrace procedur a.k.a inline-expansion
Listové procedury Nevolají žádné další Není třeba kompletní prolog
a epilog procedury Užitečné zejména v
přítomnosti výjimek
Shrink wrapping Přesouvání prologu a
epilogu Ve větvích, které nevolají
další procedury, se prolog a epilog anihilují
• Tail merging• Ztotožnění identických konců
procedur• Poslední BB často
obsahuje pouze epilog a je tudíž shodný
• Šetří velikost kódu• Zlepšuje využití I-cache
143 Interprocedurální úpravy
Specializace procedur Procedury se naklonují Jednotlivé klony se
přizpůsobují okolnostem, které panují při jejich volání
Speciální tvary argumentů
Konstantní argumenty Aliasing
Interprocedurální alokace registrů
Volací konvence se upravuje podle místních podmínek
Efekt je obdobný jako u integrace procedur
Specializace vede k menší expanzi kódu
Specializace se obtížněji řídí
Integrace odstraňuje režii volání
Integrace umožňuje další optimalizace
144 Nápověda pro procesor
Intraprocedural I-cache optimization
Využití atomicity cache-line
Serializace BB tak, aby chování CPU vedlo k minimálnímu počtu výpadků I-cache
Instruction prefetchingData prefetching
Využití speciálních instrukcí pro nedestruktivní čtení
Branch predictionGenerování nápovědy
pro branch prediction
145 Architektura překladače
Detailní pohled akademika (pouze optimalizace)• Muchnick: Advanced Compiler Design and Implementation
Scalar replacement of array referencesData-cache optimizations
Procedure integrationTail-call optimizationScalar replacement of aggregatesSparse conditional constant propagationInterprocedural constant propagationProcedure specialization and cloningSparse conditional constant propagation
Global value numberingLocal and global copy propagationSparse conditional constant propagationDead-code eliminationLocal and global common-subexpression eliminationLoop-invariant code motionDead-code eliminationCode hoistingInduction-variable strength reductionLinear-function test replacementInduction-variable removalUnnecessary bounds-checking eliminationControl-flow optimizations
In-line expansionLeaf-routine optimizationShrink wrappingMachine idiomsTail mergingBranch optimizations and conditional movesDead-code eliminationSoftware pipelining, loop unrollingBasic-block and branch schedulingRegister allocationBasic-block and branch schedulingIntraprocedural I-cache optimizationInstruction prefetchingData prefetchingBranch prediction
Interprocedural register allocationAggregation of global referencesInterprocedural I-cache optimization
Constant foldingAlgebraic simplification and reassociation
146 Architektura překladače
Realita GNU
CompilerCollectionInternals
Remove useless statements Mudflap declaration registration Lower control flow Lower exception handling control flow Build the control flow graph Find all referenced variables
RTL generation Generate exception handling landing pads Cleanup control flow graph Common subexpression elimination Global common subexpression elimination. Loop optimization Jump bypassing If conversion Web construction Life analysis Instruction combination Register movement Optimize mode switching Modulo scheduling Instruction scheduling Register class preferencingLocal register allocationGlobal register allocationReloadingBasic block reordering Variable tracking Delayed branch scheduling Branch shortening Register-to-stack conversion Final Debugging information output
Enter static single assignment form Warn for uninitialized variables Dead code elimination Dominator optimizations Redundant phi elimination Forward propagation of single-use variables Copy renaming PHI node optimizations May-alias optimization Profiling Lower complex arithmetic Scalar replacement of aggregates Dead store elimination
Tail recursion elimination Forward store motion Partial redundancy elimination Loop invariant motionCanonical induction variable creationInduction variable optimizationsLoop unswitchingVectorizationTree level if-conversion for vectorizer Conditional constant propagation Folding builtin functions Split critical edges Partial redundancy elimination Control dependence dead code elimination Tail call elimination Warn for function return without value Mudflap statement annotation Leave static single assignment form
top related