• Keine Ergebnisse gefunden

Architektur und Programmierung von Grafik- und Koprozessoren

N/A
N/A
Protected

Academic year: 2022

Aktie "Architektur und Programmierung von Grafik- und Koprozessoren"

Copied!
39
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Koprozessoren

Performanz von Computerprogrammen

Stefan Zellmann

Lehrstuhl f¨ur Informatik, Universit¨at zu K¨oln

SS2019

(2)

Einfache BUS Topologie

CPU1

Core0

Core0

CPU0

DDR1 DDR0

BUS

Core1

Core1

L1 L1

L1 L1

(3)

Einfache BUS Topologie

I Kommt bei vielen Multi-Core Architekturen vor (vereinfachte Darstellung, es gibt nur L1 Caches).

I Speicherzugriffe in den eigenen RAM m¨ussen zwischen Core0 und Core1 synchronisiert werden. Ggf. ver¨andert Core0 ein Datum, dass Core1 im lokalen L1 Cache auch bereits ge¨andert hat.

I Synchronisation zwischen Cores von CPU0 und CPU1

erfordert Kommunikation ¨uber den BUS⇒ h¨orere Latenz.

Dadurch ergeben sich i. Allg. nichtuniforme Speicherzugriffe.

(4)

Kompliziertere Topologien (z. B. Ring-BUS)

Core1 L1

Core0 L1

Core3 L1

Core2 L1

Core4

Coren-1 L1

L1

...

DDR

DDR DDR

DDR

DDR

...

...

(5)

Memory Controller

Northbridge Northbridge

CPU CPU

PCIe/AGP

Southbridge Southbridge

PCI Front Side Bus

Abbildung:Memory Controller war Teil derNorthbridge(separater Chip auf Mainboard). Sp¨ater: Northbridge (und MC!) Teil der CPU.

(6)

Core0Core1Core2Core3Core4Core5Core6Core7

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

256kb L2

256kb L2

256kb L2

256kb L2

256kb L2

256kb L2

256kb L2

256kb L2

L3 20MB Ring Bus

2x QPI 2.0 16 GB/s Memory

Controller

I/O Controller

Core0Core1Core2Core3Core4Core5Core6Core7

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

32kb 32kb L1i/d

256kb L2

256kb L2

256kb L2

256kb L2

256kb L2

256kb L2

256kb L2

256kb L2

L3 20MB Ring Bus

2x QPI 2.0 16 GB/s

Memory Controller I/O Controller

Abbildung:2×Intel “Sandy Bridge” Xeon E5-2670 Konfiguration, zwei QPI Links zwischen Prozessoren (8 GT/s bei 2 byte pro Transfer, bidirektional, jeder Link in jede Richtung 16 GB/stotal 32 GB/s.).

Vgl.: Performance Evaluation of the Intel Sandy Bridge Based NASA Pleiades Using Scientific and Engineering Applications, Saini et al. 2013.

(7)

I Problem bei Architekturen mit Caches: was passiert, wenn beide Prozessoren das gleiche geteilte Datum im Cache speichern, und ein Prozessor ¨andert das Datum lokal?

I Die meisten Infrastrukturen (Hardware + OS) implementieren cache-koh¨aherentes NUMA(ccNUMA).

I Cache-Koh¨arenz Protokolle lassen es f¨ur Entwickler so

aussehen, als g¨abe es keine lokalen Caches, sondern als w¨aren alle Caches geteilt.

(8)

umgesetzt – z. B. (“Snooping Protokolle):

I write-invalidate: der schreibende Prozessor sendet ein Token

¨uber den Interconnect, das den gerade beschriebenen Cache Block identifiziert und invalidiert. Dann kann die lokale Kopie angepasst werden.

I write-update: der schreibende Prozessor verteilt viaBroadcast das neue Datum, und alle Prozessoren aktualisieren die Kopie im lokalen Cache.

(9)

I Jeder Prozessor verwaltet seinen lokalen Cache.

I Protokoll modelliert Zustandsautomat. Cache Line in einem der Zust¨ande

I Modified - kein anderer Cache speichert die Cache Line, sie wurde außerdem bereits modifiziert.

I Exclusive - kein anderer Cache speichert die Cache Line, sie kann modifiziert werden, wurde aber noch nicht modifiziert.

I Shared - andere lokale Caches haben eine Kopie der Cache Line mit identischem Inhalt.

I Invalid - Cache Line wird derzeit nicht benutzt.

I Die Prozessoren tauschen untereinander Nachrichten aus, um ihre lokalen Caches abzugleichen.

I Wichtig: modifizierte Cache Lines sind auch exklusive Cache Lines.

(10)

ModifiedM E

Exclusive

InvalidI S

Shared LW

RW RR

RW

LW LW

RR LR

RW

LR LR LR

LW

LR|RR RR

I M¨ogliche

Zustands¨uberg¨ange aufgrund von local read (LR),local write (LW), snooped remote read (RR) odersnooped remote write (RW).

(11)

ModifiedM E

Exclusive

InvalidI S

Shared LW

RW RR

RW

LW LW

RR LR

RW

LR LR LR

LW

LR|RR RR

I LRZustands¨ubergang von Invalid (Prozessor liest Cache Line): pr¨ufe (¨uber Bus), ob Cache Line geteilt.

Falls ja: Shared, sonst:

Exclusive.

(12)

ModifiedM E

Exclusive

InvalidI S

Shared LW

RW RR

RW

LW LW

RR LR

RW

LR LR LR

LW

LR|RR RR

I LRAlle anderen Zust¨ande:

Keine Ver¨anderung.

(13)

ModifiedM E

Exclusive

InvalidI S

Shared LW

RW RR

RW

LW LW

RR LR

RW

LR LR LR

LW

LR|RR RR

I LWAlle lokalen Schreiboperationen

¨uberf¨uhren Cache Line in Modified State.

I Falls vorher Invalid oder Shared, sende Broadcast Nachricht an alle anderen Prozessoren, diese

invalidieren ihre lokale Kopie.

(14)

ModifiedM E

Exclusive

InvalidI S

Shared LW

RW RR

RW

LW LW

RR LR

RW

LR LR LR

LW

LR|RR RR

I RREntdeckt Prozessor eine Leseanforderung ¨uber Bus, wird Cache Line Shared.

I Im Fall, dass vorher Invalid, lese Cache Line aus Speicher und teile ¨uber Bus.

(15)

ModifiedM E

Exclusive

InvalidI S

Shared LW

RW RR

RW

LW LW

RR LR

RW

LR LR LR

LW

LR|RR RR

I RWSchreiboperationen

¨

uber Bus (also von einem anderen Prozessor!) f¨uhren dazu, dass Cache Line invalidiert und in den Speicher zur¨uckgeschrieben wird.

(16)

I Es kann nur in Cache Lines geschrieben werden, die im Modified oder Exclusive Zustand sind.

I Remote Writes werden mit sog.read for ownership

implementiert: Core m¨ochte in Cache Line schreiben, die im Shared Zustand ist. Dazu schickt er zuerst per Broadcast eine Nachricht ¨uber den Bus, dass alle anderen Cores ihre Kopie der Cache Line invalidieren. Dannliest der Core die Cache Line und versetzt sie lokal in den ExclusiveZustand. Danach kann geschrieben werden (modify).

I H¨alt ein Core eine Cache Line imModifiedZustand, muss er den Bus ¨uberwachen (snooping, ob andere Cores auf die Cache Line zugreifen wollen. Dann erst muss der Core das ge¨anderte Datum erst in den Hauptspeicher zur¨uckschreiben.

Die entfernte Leseoperation kann bspw. direkt aus dem Cache bedient, oder zur¨uckgehalten werden.

(17)

I Prinzip: opportunistisch – Kommunikation ¨uber Bus nur falls n¨otig, modifiziere Speicher nur falls n¨otig.

I Lesen aus lokalem Cache ist billig.

I Lokale Schreiboperationen f¨uhren nur zu Datenkommunikation, falls Cache Line geteilt.

I Schreiben ¨uber Bus ineffizient.

I Andere Protokolle: MSI, MESIF, MOSI, etc.

(18)

I Spezialisierte APIs, z. B. libnuma unter Linux, Funktionen wie numa alloc local(),numa bind().

I Tools wie numactl: “pinne” Prozess an bestimmten Core, etc.

I APIs und Tools exponieren Funktionalit¨at desBetriebssystems.

(19)

atomic <int> c o u n t e r ( 0 ) ; // s h a r e d v a r i a b l e v o i d p a r a l l e l _ f u n c () {

c o u n t e r ++;

}

I Atomare Operationen gehen durch die Cache Hierachie.

I Was passiert, wenn Cores geteilte Variable atomar modifizieren?

(20)

Sections!):

1. SendeLOCKauf Bus (broadcast).

2. Cores empfangenLOCKund schließen alle Speicheroperationen ab. Core, derLOCK initiiert hat, wartet darauf.

3. WhenACK(“acknowledge”) von allen Cores empfangen, f¨uhre atomare Operation aus. Sende dann broadcast Nachricht an alle Cores, dass sie weiterarbeiten k¨onnen.

4. Dies ist ausgesprochen langsam.

I Besser: MESI Protokoll - read for ownership⇒ Cache Line, die Datum beinhaltet ist in Exclusive Zustand und kann atomar modifiziert werden.

(21)

I Problem: Alignment

1. MESI Protokoll implementiert diese Art von “Locking” auf Cache Line Level. Funktioniert nicht, wenn das geteilte, zu modifizierende Datum zwei Cache Lines “¨uberlappt”.

2. x86 bspw. implementiert den langsamerenLOCK basierten Modus f¨urunaligned atomic Instruktionen.

x

0 CLi CLi+1

x

1

x

2

x

3

(22)

I char: 1-byte.

I short: 2-byte.

I int: 4-byte.

I Zum Vergleich: Cache Line Alignment (x86): 64-byte.

I Zusammengesetzte Typen (struct) “erben” das Alignment vom ersten Member. Typen wiestd::atomic<>unterst¨utzen atomare Operationen auf zusammengesetzten Typen.

I Daher: stelle sicher, dass atomar genutzte Typen aligniert (z. B. attribute ((align(64))).

(23)

s t r u c t P1 { c h a r c ; int i [ 3 ] ; s h o r t s ; };

s t r u c t P2 { int i [ 3 ] ; s h o r t s ; c h a r c ; };

int m a i n () { s t r u c t P1 p1 ; s t r u c t P2 p2 ;

p r i n t f (" % d , ", (int)s i z e o f( p1 ));

p r i n t f (" % d \ n ", (int)s i z e o f( p2 ));

}

Output (Apple Clang ANSI-C Compiler, 7.0.2):20,16 (!)

(24)

Bemerkungen

I Auf Architekturen mit Caches sollten inner loop Typen cache-effizientes Alignment und Packing haben.

I Da atomare Operationen mit Cache Line Granularit¨at

durchgef¨uhrt werden, ist auf NUMA Systemen Alignment und Packing noch viel wichtiger!

I Mehrkernprozessoren wie Core i7 etc. sind heutzutage immer NUMA Systeme und implementieren MESI oder Varianten davon (⇒Relevanz).

(25)

I Multi-Core und Many-Core Architekturen ⇒ kompliziertere Speicherarchitekturen.

I NUMA hilft, Skalierungsprobleme zu vermeiden, da weniger Kommunikation auf dem Bus.

I Dadurch ist es schwieriger, Latenz von Speicherzugriffen einzusch¨atzen, viele entfernte Speicherzugriffe werden zu Bottlenecks.

I Caches nicht direkt addressierbar ⇒ zus¨atzliche Chipfl¨ache und Software Cycles f¨ur Cache-Koh¨arenz Protokolle.

I NUMA Komplexit¨at wird zwar von den meisten Architekturen durch Cache-Koh¨arenz versteckt, Entwickler von

Multithreading Applikationen sollten jedoch ¨uber nichtuniforme Speicherzugriffe wissen.

(26)

Abgrenzung

I Symmetric Multi-Processing - ein Speicher, viele Prozessoren, die mit gleicher Latenz auf den Speicher zugreifen.

I Non-Uniform Memory Access - Kerne greifen mit niedriger Latenz auf lokalen Speicher zu.

I Distributed Memory - Prozessoren verf¨ugen ¨uber lokalen Speicher und sind ¨uber Interconnect (Netzwerk) miteinander verbunden. Zugriff auf entfernten Speicher ist nicht direkt m¨oglich. Vielmehr muss der dem entfernten Speicher zugeordnete Prozessorbenachrichtigt werden, dass von entfernt auf Speicher zugegriffen werden soll.

(27)

Abgrenzung

I Abgrenzung zwischen Architekturen teils schwierig. NUMA Systeme haben bspw. Charakteristiken von Distributed Memory Systemen, jedoch werden diese durch die Implementierung (z. B. Cache-Koh¨arenz) versteckt.

I Distributed Memory Systeme zeichnen sich ¨ublicherweise durch r¨aumliche Trennung derRechenknotenaus.

(28)

Hybride Systeme

Distributed Memory Systeme sind in Wirklichkeit oft hybride Systeme: Rechenknoten sind per Interconnect verbunden und sind selbst SMP oder NUMA Systeme.

CPU1

Core0

Core0 CPU0

DDR1 DDR0

BUS

Core1

Core1

L1 L1

L1 L1

CPU1

Core0

Core0 CPU0

DDR1 DDR0

BUS

Core1

Core1

L1 L1

L1 L1

CPU1

Core0

Core0 CPU0

DDR1 DDR0

BUS

Core1

Core1

L1 L1

L1 L1

CPU1

Core0

Core0 CPU0

DDR1 DDR0

BUS

Core1

Core1

L1 L1

L1 L1

CPU1

Core0

Core0 CPU0

DDR1 DDR0

BUS

Core1

Core1

L1 L1

L1 L1

CPU1

Core0

Core0 CPU0

DDR1 DDR0

BUS

Core1

Core1

L1 L1

L1 L1

Interconnect

(29)

Programmiermodelle

I Es gibt verschiedene Programmiermodelle f¨ur Distributed Memory Systeme, z. B. aus dem Umfeld

Netzwerkprogrammierung mit Protokollen wie TCP/IP.

I Programmierung mit Sockets.

I Programmierung ¨uber Web Protokolle wie HTTP.

I Im High-Performance Computing (HPC) Umfeld spielt jedoch der Message Passing Interface(MPI) Standard eine wichtige Rolle.

(30)

Message Passing Interface

I Sockets erlauben Zugriff auf Netzwerkschnittstelle auf sehr niedrigem Level und per direkter Kommunikation mit dem Betriebssystem.

I Im HPC Umfeld kommen jedoch h¨aufig schnelle Interconnects (z. B. InfiniBand) zum Einsatz, die nicht IP basiert sind.

I Solche Netzwerke kann man teils plattformspezifisch

programmieren, MPI ist jedoch ein standardisierter Ansatz um HPC Interconnect Architekturen plattformunabh¨angig zu nutzen.

I InfiniBand bspw. kann man auch mit Sockets programmieren (sog.IP over IB), das vermeidet man aber, da IP Stack und OSI Schichtenmodell stark latenzbehaftet sind.

(31)

P1

P2

P3

P4

P6 P5

P8 P7

P9

Unicast Messages Broadcast Message

(32)

Scatterverteilt Daten,Gathersammelt Daten. Bemerkungen bzgl.

Koh¨arenz und Lokalit¨at gelten auch hier.

(33)

Message Typen

I Unicast: MPI send(),MPI recv() I Broadcast: MPI Bcast()

I Scatter/Gather:MPI Scatter(),MPI Gather() I Reduktion:MPI Reduce()

I ...

Kollective Aufrufe wie Broadcasting m¨ussen synchronisiert werden (MPI Barrier()).

(34)

# d e f i n e M A S T E R 0

# d e f i n e S L A V E 1

int m a i n (int argc , c h a r** a r g v ) { M P I _ I n i t (& argc , & a r g v );

int r a n k ;

M P I _ C o m m _ r a n k ( M P I _ C O M M _ W O R L D , & r a n k );

if ( r a n k == M A S T E R ) {

c h a r c o n s t* msg = " MSG ";

M P I _ S e n d ( msg , 4 , M P I _ B Y T E , SLAVE , 1 , M P I _ C O M M _ W O R L D );

} e l s e {

c h a r str [ 3 2 ] ; M P I _ S t a t u s s ;

M P I _ R e c v ( str , 32 , M P I _ B Y T E , MASTER , 1 , M P I _ C O M M _ W O R L D , & s );

}

M P I _ F i n a l i z e ();

}

(35)

Ubersetzung mit speziellem MPI Compiler, z. B.¨

mpicc hello mpi.c -o hello mpi

F¨uhre MPI Programm auf daf¨ur konfiguriertem Cluster aus, z. B.

mpirun -n 256 hello mpioder

mpiexec -n 256 hello mpi

(36)

I insb. MPICH und OpenMPI I Urspr¨unglich Fortran und C.

I Adaptionen f¨ur verschiedene Sprachen, z. B. C++ Interface.

(37)

# i n c l u d e < mpi . h >

int m a i n (int argc , c h a r** a r g v ) { M P I _ I n i t ( argc , a r g v );

int c o m m _ s i z e , r a n k ;

M P I _ C o m m _ s i z e ( M P I _ C O M M _ W O R L D , & c o m m _ s i z e );

M P I _ C o m m _ r a n k ( M P I _ C O M M _ W O R L D , & r a n k );

int N = a t o i ( a r g v [ 1 ] ) ; f l o a t a , y [ N ] , x [ N ];

if ( r a n k == 0)

i n i t ( a , y , x , N );

int N _ l o c a l = N / c o m m _ s i z e ;

f l o a t al , yl [ N _ l o c a l ] , xl [ N _ l o c a l ];

// c o n t . on n e x t s l i d e

(38)

M P I _ S c a t t e r ( a , 1 , M P I _ F L O A T , al , 1 , M P I _ F L O A T , 0 , M P I _ C O M M _ W O R L D );

M P I _ S c a t t e r ( y , N_local , M P I _ F L O A T , yl , N_local , M P I _ F L O A T , 0 , M P I _ C O M M _ W O R L D );

M P I _ S c a t t e r ( x , N_local , M P I _ F L O A T , xl , N_local , M P I _ F L O A T , 0 , M P I _ C O M M _ W O R L D );

s a x p y ( yl , al , xl , N _ l o c a l );

M P I _ G a t h e r ( yl , N_local , M P I _ F L O A T , y , N_local , M P I _ F L O A T , 0 , M P I _ C O M M _ W O R L D );

M P I _ F i n a l i z e ();

}

(39)

I NUMA Systeme (auch wenn sie in einerCPU verbaut sind) sind verteilte Systeme. Sie versenden untereinander

Nachrichten.

I Cache-Koh¨arenz Protokolle (z. B. MESI) verstecken Message Passing. Cache-Koh¨arenz ist fehlertolerant, bringt jedoch Overhead mit. Alternative: nicht-cache-koh¨arente NUMA Systeme mit Message Passing.

I Mehrere MPI Prozesse k¨onnen auf einer CPU ausgef¨uhrt werden!

I Fabrique (z. B.QuickPath Interconnect(QPI)) ist dann das Netzwerk.

Referenzen

ÄHNLICHE DOKUMENTE

“Sampling” bestimmt. Dies ist eine in den Prozessor eingebaute Funktionalit¨ at, die, falls aktiviert, die Instruktionspipeline zu definierten Zeitpunkten anh¨ alt und

C++ spezifiziert keine Garbage Collection (der Standard schließt sie nicht explizit aus, aber es gibt keine Implementierungen, die mir bekannt sind). Daher m¨ ussen alle Ressourcen,

I Vulkan / Modernes OpenGL: minimaler Vertex Shader verpflichtend (außer Compute). Ohne minimalen Fragment Shader kein Bild (manchmal Ergebnis

GPU Readback (d. Rendering in einen Offscreen Buffer und dann Transfer der Farb- und/oder Tiefeninformation in Host Speicher der Applikation) ist mit diesem asynchronen Modell

Die Template Klasse sync queue in der beigef¨ ugten Datei queue.cpp wird von mehreren Threads gleichzeitig als Schlange zum Austauschen von Nachrichten genutzt. Intern verwaltet

(2) Die Bin¨ arrepr¨ asentation der sich ergebenden nat¨ urlichen Zahl k setzt sich immer abwechselnd aus den Bin¨ arziffern der Zahlpaare (i, j) zusammen. Tragen Sie das Ergebnis

Trifft man die vereinfachende Annahme, dass geometrische, aus Dreiecken zusammengesetzte Objekte geschlossen sind und immer nur von außen betrachtet werden, kann man vor dem

Der Ray Tracer geht im Weiteren davon aus, dass totale interne Reflektion aufgetreten ist, wenn refract() einen 0-Vektor zurückgegeben hat und ruft in dem Fall die Funktion