Architetture per il calcolo parallelo Moreno Marzolla Dip. di Informatica—Scienza e Ingegneria (DISI) Università di Bologna http://www.moreno.marzolla.name/ Architetture parallele 2 Una architettura parallela astratta Processore Processore Processore Processore Rete di interconnessione Memoria ● ● ● Memoria Memoria Come è gestito il parallelismo? Dove si trova fisicamente la memoria? Quale è la topologia della rete di comunicazione? Architetture parallele 3 Perché studiare le architetture parallele? ● Non esiste il “calcolatore parallelo tipico”: diversi produttori adottano soluzioni diverse – ● ● ● Non esiste un singolo paradigma di programmazione parallela valido per tutte le architetture Il tipo di architettura parallela ha un enorme impatto sulle prestazioni dei programmi Sarebbe bello riuscire a descrivere algoritmi paralleli in modo generico e indipendente dall'architettura... ...La triste verità è che, in generale, è necessario utilizzare algoritmi ad-hoc in base all'architettura del sistema su cui verranno implementati Architetture parallele 4 Architettura di Von Neumann e sue estensioni Architetture parallele 5 Architettura di Von Neumann Processore (CPU) Memoria Sottosistema di interfaccia (I/O) Bus di sistema Architetture parallele 6 Un po' più in dettaglio Dati Indirizzi Controllo Bus R0 R1 ALU Memoria Memoria Rn-1 PC IR PSW Controllo Architetture parallele 7 Ciclo Fetch-Decode-Execute ● ● Eseguito in continuazione dalla CPU Fetch – – ● Decode – ● Preleva dalla memoria, all'indirizzo specificato in PC, l'istruzione da eseguire Il codice dell'istruzione viene posto in IR Esamina l'istruzione in IR per decidere cosa fare Execute – Esegue l'istruzione memorizzata in IR, inclusa l'eventuale lettura dalla memoria dei parametri e la scrittura del risultato Architetture parallele 8 Limitare i colli di bottiglia dell'architettura di Von Neumann ● Ridurre la latenza degli accessi alla memoria – – ● “Nascondere” la latenza degli accessi alla memoria – ● Sfruttare i registri della CPU Sfruttare le cache Multithreading e context-switch durante gli accessi alla memoria Eseguire istruzioni in parallelo – – – – – Pipelining Multiple issue Branch prediction Speculative execution SIMD extensions Architetture parallele 9 I tempi in gioco 1 CPU cycle Level 1 cache access Main memory access Solid-state disk I/O Rotational disk I/O Internet: SF to NYC Internet: SF to UK Internet: SF to Australia Physical system reboot 0.3 ns 0.9 ns 120 ns 50-150 μs 1-10 ms 40 ms 81 ms 183 ms 5m 1s 3s 6 min 2-6 days 1-12 months 4 years 8 years 19 years 32 millenia Source: https://blog.codinghorror.com/the-infinite-space-between-words/ Caching Architetture parallele 11 Località e parallelismo ● Le memorie capienti sono lente; le memorie veloci sono poco capienti CPU L1 Cache L2 Cache L3 Cache (possibile) bus di interconnessione Memoria Architetture parallele 12 Gerarchia di cache dell'architettura AMD Bulldozer Fonte: http://en.wikipedia.org/wiki/Bulldozer_%28microarchitecture%29 Architetture parallele 13 Gerarchia di memoria CUDA Block Block Shared Memory Registers Thread Local Memory Registers Shared Memory Registers Thread Local Memory Thread Local Memory Registers Thread Local Memory Global Memory Constant Memory Texture Memory Architetture parallele 14 Richiami sul funzionamento delle cache ● La memoria cache è un tipo di memoria molto veloce – – ● ● Spesso presente all'interno dello stesso chip del processore Costosa da realizzare, di dimensioni molto minore della RAM di sistema La memoria cache contiene una copia dei valori presenti in alcune locazioni della RAM accedute "più di recente" Se si accede ad una locazione di memoria il cui valore è presente in cache, il valore viene letto dalla cache e non dalla RAM – con tempi di accesso molto ridotti Architetture parallele 15 Richiami sul funzionamento delle cache ● Se si accede ad una locazione di memoria NON presente in cache – – ● Il contenuto della locazione acceduta e di quelle adiacenti viene copiato in cache Se la cache era già piena, occorre "fare spazio" ai nuovi dati L'unità minima di trasferimento da/verso la cache è la cache line – Es, nei recenti processori intel 1 cache line = 64B contigui Architetture parallele 16 Esempio CPU Cache RAM a b c d e f g h i j k l Ampiezza cache line Architetture parallele 17 Esempio CPU Cache RAM a b c d e f g h i j k l Cache line Architetture parallele 18 Esempio CPU a b c d e f g h i j k l Cache RAM a b c d e f g h i j k l Architetture parallele 19 Esempio CPU a b c d e f g h i j k l Cache RAM a b c d e f g h i j k l Architetture parallele 20 Esempio CPU a b c d e f g h i j k l Cache RAM a b c d e f g h i j k l Architetture parallele 21 Esempio CPU a b c d e f g h i j k l Cache RAM a b c d e f g h i j k l Architetture parallele 22 Concetto base ● Località spaziale – ● Accedere a locazioni di memoria contigue è OK Località temporale – Accessi ripetuti a breve distanza di tempo alla stessa area di memoria sono OK Architetture parallele 23 Esempio degli effetti della cache Prodotto matrice-matrice ● Date due matrici quadrate p, q, calcolare r = p q j j i i p q r void matmul( double *p, double* q, double *r, int n) { int i, j, k; for (i=0; i<n; i++) { for (j=0; j<n; j++) { r[i*n + j] = 0.0; for (k=0; k<n; k++) { r[i*n + j] += p[i*n + k] * q[k*n + j]; } } } Architetture parallele } 24 Rappresentazione delle matrici ● In C sono memorizzate per riga (row-major order) – – Gli elementi in ciascuna riga sono contigui in memoria Righe successive sono contigue in memoria p[0][0] p[1][0] p[4][4] p[2][0] p[3][0] p[0][0] p[1][0] p[2][0] Architetture parallele p[3][0] 25 Accesso per riga vs accesso per colonna Accesso per riga OK: si accede a elementi contigui in memoria (la cache aiuta) Accesso per colonna NON ok: si accede a elementi “sparpagliati” in memoria (accesso strided; la cache NON aiuta) Architetture parallele 26 Prodotto matrice-matrice ● Date due matrici quadrate p, q, calcolare r = p q j j i i p OK; accesso per righe q r NON ok; accesso per colonne Architetture parallele 27 Ottimizzare l'uso della cache p00 p01 p02 p03 p10 p11 p12 p13 p20 p21 p22 p23 p30 p31 p32 p33 p q00 q10 q02 q03 q10 q11 q12 q13 q20 q21 q22 q23 q30 q31 q32 q33 q Architetture parallele r00 r01 r02 r03 r10 r11 r12 r13 r20 r21 r22 r23 r30 r31 r32 r33 r 28 Ottimizzare l'uso della cache p00 p01 p02 p03 p10 p11 p12 p13 p20 p21 p22 p23 q00 q10 q02 q03 p30 p31 p32 p33 q10 q11 q12 q13 q20 q21 q22 q23 r00 r01 r02 r03 q30 q31 q32 q33 p r10 r11 r12 r13 r20 r21 r22 r23 r30 r31 r32 r33 q r Trasposizione della matrice q p00 p01 p02 p03 p10 p11 p12 p13 p20 p21 p22 p23 p30 p31 p32 p33 p q00 q10 q20 q30 q01 q11 q21 q31 q02 q12 q22 q32 q03 q13 q23 q33 qT Architetture parallele r00 r01 r02 r03 r10 r11 r12 r13 r20 r21 r22 r23 r30 r31 r32 r33 r 29 Però... ● ● Trasporre la matrice q costa! Siamo sicuri che alla fine riusciamo a guadagnare qualcosa in termini di prestazioni? Vedi cache.c Architetture parallele 30 Instruction-Level Parallelism (ILP) Architetture parallele 31 Instruction Level Parallelism ● Aumenta le prestazioni del processore mediante più unità funzionali che operano contemporaneamente – – Pipelining: le unità funzionali sono organizzate in “fasi”, come una catena di montaggio Multiple issue: le unità funzionali possono essere utilizzate in qualsiasi ordine ● ● Static multiple issue: l'uso delle unità funzionali è stabilito a tempo di compilazione (esempio: Intel IA64) Dynamic multiple issue (superscalar): l'uso delle unità funzionali è deciso dal processore durante l'esecuzione del programma Architetture parallele 32 Instruction Level Parallelism IF ID IF ID EX MEM WB EX Integer WB Pipelining Instruction Fetch Instruction Decode Execute Memory Access Write Back Instruction Fetch and Decode Unit Integer MEM Floating Point Commit Unit Multiple Issue In-order issue Floating Point In-order commit Architetture parallele Load Store Out of order execute 33 Pipelining Instr1 IF ID EX MEM WB Instr2 Instr1 IF ID EX MEM WB Instr3 Instr2 Instr1 IF ID EX MEM WB Instr4 Instr3 Instr2 Instr1 IF ID EX MEM WB Instr5 Instr4 Instr3 Instr2 Instr1 IF ID EX MEM WB Architetture parallele 34 Flusso di istruzioni Control Dependency ● z = x + y; if ( z w } else w } > 0 ) { = x ; { = y ; ● Le istruzioni “w = x” e “w = y” hanno una dipendenza di controllo (control dependency) su “z > 0” Queste dipendenze possono limitare le prestazioni di architetture pipeline z = x + y; c = z > 0; w = x*c + y*(1-c);Architetture parallele 36 Nel mondo reale... ● Dalla documentazione di GCC http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html — Built-in Function: long __builtin_expect(long exp, long c) You may use __builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (-fprofile-arcs), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect. The return value is the value of exp, which should be an integral expression. The semantics of the built-in are that it is expected that exp == c. For example: if (__builtin_expect (x, 0)) foo (); Architetture parallele 37 Branch Hint: Esempio #include <stdlib.h> int main( void ) { int A[1000000]; int i; const size_t n = sizeof(A) / sizeof(A[0]); for ( i=0; __builtin_expect( i<n, 1 ); i++ ) { A[i] = i; } return 0; } Evitate queste micro-ottimizzazioni, a meno che non sappiate esattamente cosa state facendo. Architetture parallele 38 Hardware multithreading ● Consente al processore di eseguire istruzioni anche quando il task corrente è in stallo – ● Fine-grained: il context switch tra thread ha costo pressoché nullo e può quindi avvenire istruzione per istruzione – ● ad esempio, perché sta aspettando dati dalla memoria Richiede CPU con supporto specifico,e.g., Cray XMT Coarse-grained: il context switch avviene solo per i thread bloccati per periodi più lunghi (es., su I/O) – Context switch solitamente più oneroso, minore efficienza dell'utilizzo della CPU in presenza di stalli di breve durata Architetture parallele 39 Source: https://www.slideshare.net/jasonriedy/sting-a-framework-for-analyzing-spaciotemporal-interaction-networks-and-graphs Hardware multithreading ● Simultaneous multithreading (SMT) è una variante del multithreading "a grana fine" (fine-grained multithreading) in cui thread diversi possono usare contemporaneamente unità funzionali diverse Instruction Fetch and Decode Unit Integer Integer Floating Point Floating Point Load Store Commit Unit Architetture parallele 41 HyperThreading ● ● ● Implementazione della tecnologia SMT da parte di Intel Ogni core fisico viene visto e gestito dal Sistema Operativo come due core “logici” distinti HT sfrutta l'architettura superscalare del processore – – – Cioè il fatto che alcune unità—ad esclusione dell'unità principale di esecuzione—sono replicate e possono operare in parallelo Vedi output di lscpu (in particolare, "Thread(s) per core") oppure lstopo (pacchetto hwloc Ubuntu/Debian) Intel afferma che HT fornisce un incremento di prestazioni del 15—30% rispetto ad un analogo processore non HT Architetture parallele 42 HyperThreading ● Esempio di output di lstopo Processore senza HT Processore con HT Architetture parallele 43 Architetture Parallele Architetture parallele 44 Architettura di Von Neumann Tassonomia di Flynn Single Multiple Instruction Streams Data Streams Single Multiple SISD SIMD Single Instruction Stream Single Data Stream Single Instruction Stream Multiple Data Streams MISD MIMD Multiple Instruction Streams Single Data Stream Multiple Instruction Streams Multiple Data Streams Architetture parallele 45 SIMD Le architetture SIMD consentono di applicare la stessa istruzione (tipicamente aritmetica/logica, e.g., somma, prodotto, …) a più dati contemporaneamente (tipicamente 4 oppure 8) – Tempo ● Questo implica che la ALU debba essere replicata 4/8/... volte LOAD A[0] LOAD A[1] LOAD A[2] LOAD A[3] LOAD B[0] LOAD B[1] LOAD B[2] LOAD B[3] C[0] = A[0] + B[0] C[1] = A[1] + B[1] C[2] = A[2] + B[2] C[3] = A[3] + B[3] STORE C[0] STORE C[1] STORE C[2] STORE C[3] Architetture parallele 46 SSE Streaming SIMD Extensions ● ● ● Estensione al set di istruzioni x86 Nuove istruzioni in grado di operare prevalentemente su numeri floating point in precisione singola 8 nuovi registri a 128 bit (XMM0—XMM7) – ● rappresentano 4 float a 32 bit in precisione singola SSE2 consente di rappresentare – – – – – 2 double a 64 bit, oppure 2 int a 64 bit, oppure 4 int a 32 bit, oppure 8 short int a 16 bit, oppure 16 char a 8 bit 32 128 bit 32 32 32 XMM0 XMM1 Architetture parallele XMM7 47 SSE (Streaming SIMD Extensions) 32 bit 32 bit 32 bit 32 bit X3 X2 X1 X0 Y3 Y2 Y1 Y0 Op Op Op Op X3 op Y3 X2 op Y2 X1 op Y1 X0 op Y0 Architetture parallele 48 Esempio __m128 a = _mm_set_ps( 1.0, 2.0, 3.0, 4.0 ); __m128 b = _mm_set_ps( 2.0, 4.0, 6.0, 8.0 ); __m128 ab = _mm_mul_ps(a, b); 32 bit 32 bit 32 bit 32 bit a 1.0 2.0 3.0 4.0 b 2.0 4.0 6.0 8.0 _mm_mul_ps(a, b) ab 2.0 8.0 Architetture parallele 18.0 32.0 49 GPU ● Le moderne GPU (Graphics Processing Units) includono un elevato numero di core e hanno caratteristiche simili a sistemi SIMD Chip GPU Fermi (fonte: 50 http://www.legitreviews.com/article/1100/1/) Architetture parallele CPU vs GPU ● Le differenze sono evidenti se consideriamo come vengono utilizzati i transistor presenti sul chip ALU ALU ALU ALU Control Cache DRAM DRAM CPU GPU Architetture parallele 51 GPU core ● Un singolo core contiene una unità fetch/decode condivisa tra più ALU – ● ALU ALU ALU ALU ALU ALU ALU ALU Ctx Ctx Ctx Ctx Ctx Ctx Ctx Ctx Ctx Ctx Ctx Ctx 8 ALU = ciascuna istruzione può operare su 8 dati simultaneamente Ogni core mantiene più contesti di esecuzione ed è in grado di passare dall'uno all'altro a costo ~zero – Fetch / Decode Fine-grained parallelism Architetture parallele 52 GPU ● 12 stream di istruzioni x 8 ALU = 96 operazioni in parallelo Architetture parallele 53 MIMD ● Nelle architetture MIMD sono presenti più unità di esecuzione che eseguono sequenze di istruzioni indipendenti – Ogni unità di esecuzione può operare su dati differenti dalle altre – Tempo ● Multiple Instruction Streams Multiple Data Streams LOAD A[0] CALL F() a = 18 w=7 LOAD B[0] z=8 b=9 t = 13 C[0] = A[0] + B[0] y = 1.7 if ( a>b ) c = 7 k = G(w,t) STORE C[0] z=x+y a=a-1 k=k+1 Architetture parallele 54 Architetture MIMD ● Shared Memory – – ● CPU Un insieme di processori che condividono una memoria comune Ogni processore puo' accedere direttamente ad una qualsiasi locazione della memoria CPU CPU CPU Interconnect Memoria Distributed Memory – – – Un insieme di sistemi autonomi connessi tramite una rete di comunicazione Nodi diversi devono comunicare tramite la rete per condividere dati Esempio più comune: cluster di PC connessi tramite Ethernet, programmati usando MPI CPU CPU CPU CPU Mem Mem Mem Mem Architetture parallele Interconnect 55 Architetture ibride ● In pratica, i principali sistemi HPC presenti sul mercato sono basati su architetture ibride, in cui ogni nodo di calcolo è un sistema multiprocessore a memoria condivisa, e più nodi sono collegati da una rete di interconnessione GPU GPU GPU GPU GPU GPU GPU GPU CPU CPU CPU CPU CPU CPU CPU CPU CPU CPU CPU CPU CPU CPU CPU CPU Mem Mem Mem Mem Interconnect Architetture parallele 56 Esempio shared memory Intel core i7 AMD “Istanbul” Architetture parallele 57 Esempio distributed memory IBM BlueGene / Q @ CINECA Architecture 10 BGQ Frame Model IBM-BG/Q Processor Type IBM PowerA2, 1.6 GHz Computing Cores 163840 Computing Nodes 10240 RAM 1GByte / core Internal Network 5D Torus Disk Space 2PByte scratch space Peak Performance 2PFlop/s Architetture parallele 58 Architetture parallele 59 Architetture parallele 60 Regole empiriche ● Quando si scrivono applicazioni parallele (specialmente su architetture a memoria distribuita) è utile considerare che – – – La pura computazione è “veloce” Le comunicazioni sono “lente” L'input/output è “incredibilmente lento” Architetture parallele 61 www.top500.org (june 2016) 62 www.top500.org (june 2016) Architetture parallele 63 SANDIA ASCI RED Data: 1996 Prestazioni di picco: 1.8Teraflops Ingombro: 150m2 Consumo energetico: 800.000 Watt Architetture parallele 64 SANDIA ASCI RED Data: 1996 Prestazioni di picco: 1.8Teraflops Ingombro: 150m2 Consumo energetico: 800.000 Watt Sony PLAYSTATION 3 Data: 2006 Prestazioni di picco: >1.8Teraflops Ingombro: 0.08m2 Consumo energetico: <200 Watt Architetture parallele 65 Dentro la PS3 Cell Broadband Engine Architetture parallele 66 Riassunto ● ● Memoria condivisa Vantaggi: – – ● ● ● In generale, più “facile” da programmare Vantaggioso per applicazioni che prevedono un accesso “irregolare” ai dati (esempio, algoritmi di esplorazione di grafi) Svantaggi: – – – – ● Problemi di concorrenza/mutua esclusione Banda di memoria limitata Memoria distribuita Vantaggi: Accesso a potenze di calcolo molto elevate Vantaggioso per applicazioni che esibiscono forte località di accesso ai dati, con elevato rapporto computazione / comunicazione Svantaggi: – – Architetture parallele Latenza della rete di comunicazione In generale, più complesso da programmare 67