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