Breve introduzione al calcolo parallelo

Breve introduzione
al calcolo parallelo
Creative Commons 2013
Free Report
CC BY Mauro Ennas 1998-2013
Some Rights Reserved
CC 1998-2013 BY Mauro Ennas - Some Rights Reserved
Breve introduzione al calcolo parallelo
Se utilizzi queste note (testo, codici e figure) per produrre nuovo materiale, cita la fonte.
Indice
1 Introduzione al calcolo parallelo
1
2 Architetture parallele
8
2.1 La Connection Machine - TMC . . . . . . . . . . . . . . . . . . . . 13
2.2 L’IBM-SP2
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.2.1 Componenti del sistema . . . . . . . . . . . . . . . . . . . 17
2.2.2 I processori . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2.2.3 Il sottosistema di comunicazione . . . . . . . . . . . . . . 18
2.2.4 Ambiente parallelo . . . . . . . . . . . . . . . . . . . . . . . 20
3 Programmazione parallela
21
3.1 Modello message-passing . . . . . . . . . . . . . . . . . . . . . . 22
3.2 Modello shared-memory . . . . . . . . . . . . . . . . . . . . . . . 22
3.3 Modello data-parallel . . . . . . . . . . . . . . . . . . . . . . . . . 23
4 Programmazione data-parallel
25
4.1 L’High Performance Fortran . . . . . . . . . . . . . . . . . . . . . 26
4.2 Il FORTRAN 90
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.3 Caratteristiche del linguaggio HPF . . . . . . . . . . . . . . . . . 31
4.3.1 Il mapping dei dati
Mauro Ennas
. . . . . . . . . . . . . . . . . . . . . . 33
Creative Commons 2013
5 Compilatori per macchine parallele
36
5.1 PGHPF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.2 ADAPTOR
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
5.3 Prestazioni degli algoritmi paralleli . . . . . . . . . . . . . . . . . 39
5.3.1 Modello semplificato per i tempi di calcolo . . . . . . . . . 41
Bibliografia
43
CC 1998-2013 BY Mauro Ennas - Some Rights Reserved
Breve introduzione al calcolo parallelo
Se utilizzi queste note (testo, codici e figure) per produrre nuovo materiale, cita la fonte.
Capitolo 1
Introduzione al calcolo
parallelo
La costruzione del primo calcolatore elettronico moderno viene attribuita ai due ricercatori statunitensi Mauchly ed Eckert dell’Università della
Pennsylvania, che insieme ad oltre trenta studenti della stessa Università
riuscirono a progettare e portare a termine la costruzione del calcolatore
denominato ENIAC I
1
nel 1946.
L’importanza del calcolo automatico era emersa precocemente, rispetto alle tecnologie disponibili, nei secoli precedenti ad opera di Gottfried Wilhelm
von Leibnitz (1646-1716) che costruı̀ una macchina meccanica capace di
effettuare moltiplicazioni e divisioni e Charles Babbage (1792-1871) che
tentò di costruire un grosso calcolatore meccanico, costituito da ingranaggi e ruote dentate, che per complessità e caratteristiche di progetto stimolò,
nei decenni sucessivi, i progettisti dei moderni sistemi di calcolo.
Con l’ENIAC I viene fatta cominciare l’era moderna del progetto di calcolatori elettronici 2 in quanto dall’esperienza maturata nella costruzione di un
1
2
Elettronic Numeric Integrator And Calculator.
Anche se è noto che, in realtà, i primi tentativi risalgono a dieci anni prima, ne
è un esempio l’elaboratore Z1 di Konrad Zuse nella Germania hitleriana (1938) che
rappresenta il primo calcolatore a relè funzionante; seguirono lavori di John Atanasoff dello Iowa State College e di George Stibbits presso i Bell Labs che costruirono
Mauro Ennas
Creative Commons 2013
2
simile mostro, costituito da 18000 tubi a vuoto e 1500 relè, pesante ben 30
tonnellate e con consumi quantificati in 140 kilowatt, Mauchley ed Eckert
diedero vita, sei anni dopo, al primo calcolatore commerciale l’UNIVAC I
(1952).
Dai corsi tenuti da Mauchley ed Eckert nel dopoguerra si scatenò un interesse crescente per il progetto di calcolatori elettronici e vennero affinate
le tecniche di progetto finchè si giunse nel 1960 ad un modello generale
proposto da John von Neumann che costruı̀ la IAS machine (a transistori
3
) presso l’Istituto di Studi Avanzati dell’Università di Princeton. La cosidetta
MEMORIA
Unità
di Controllo
Accumulatore
Input
Figura 1.1:
Output
Macchina di von Neumann.
macchina di von Neumann (figura (1.1)) è alla base delle moderne architetture dei calcolatori elettronici.
Gli anni cinquanta e sessanta furono segnati dallo sviluppo di una piccola
azienda produttrice, originariamente, di perforatrici e ordinatori meccanici
per schede. Si tratta dell’IBM, che finanziò vari progetti e produsse per proprio conto macchine a valvole prima e a transistori poi, commercializzandoli su vasta scala sino a divenire leader mondiale del mercato dei calcolatori
elettronici negli anni sessanta e settanta con i processori INTEL. Da studi
effettuati al M.I.T. di Boston sotto la sigla TX project (Transistorized eXperimental) nasce la DEC di Kenneth Olsen con varie versioni dei sistemi PDP
calcolatori ad aritmetica binaria e con meccanismi di refresh della memoria del
tutto simili a quelli delle moderne RAM dinamiche.
3
Il primo transistore venne costruito nei laboratori Bell nel 1948 da John
Bardeen, Walter Bratten e William Shockeley che per questa invenzione furono
insigniti del Premio Nobel nel 1956.
Mauro Ennas
Creative Commons 2013
3
a partire dal PDP-1 che introdusse il controllo del video (CRT) e sul quale
vennero programmati i primi videogiochi, sino al più noto PDP-11.
La terza generazione di calcolatori viene fatta coincidere con l’avvento dei
circuiti integrati (1965-1980) che permisero all’IBM un’ulteriore espansione nel mercato commerciale, sviluppando una linea di sistemi (famiglia)
i cosidetti IBM-360 (dal 1964); vennero introdotte importanti innovazioni
quali la possibilità di gestire in memoria più programmi contemporaneamente tramite la multiprogrammazione, la possibilità di emulazione di altri
processori e l’estensione dello spazio di indirizzamento. La quarta genera-
Cray X-MP
Figura 1.2:
Evoluzione dei calcolatori paralleli. La continua crescita del numero di processori
per una singola macchina è strettamente correlato ai progressi nei settori delle tecnologie elettroniche e
microelettroniche e alla drastica riduzione dei costi di produzione su larga scala.
zione arriva sino ai giorni nostri ed è caratterizzata dall’avvento dei sistemi
integrati su larga scala VLSI e UVLSI; nasce il personal computer e vengono
sviluppate famiglie (quali INTEL e Motorola) di circuiti elettronici digitali integrati (IC). Migliorano notevolmente le prestazioni in termini di velocità di
calcolo e di precisione nei calcoli in virgola mobile, migliora la facilità d’uso
del calcolatore (grazie al potenziamento della programmazione e l’avvento dell’era del software) e si moltiplicano le interfacce esterne che possono
Mauro Ennas
Creative Commons 2013
4
essere controllate attraverso il calcolatore e che ne hanno potenziato le prestazioni e la diffusione sino ai giorni nostri.
Degno di nota il sistema VAX (1978) della DEC, il primo supermini a 32 bit
ancora in funzione in molti centri di calcolo.
Per avere nuovi sviluppi nel progetto delle architetture dei calcolatori si
devono attendere gli anni ottanta con il progetto delle macchine RISC
4
cosı̀ denominate in contrapposizione alle macchine CISC (Complex Instruction Set Computer) ossia le IBM-360, i DEC-VAX, INTEL-X86 e i Motorola68030.
Il nuovo paradigma di progettazione propone una revisione completa ed
una riduzione di complessità delle tecniche di progettazione in uso sino
agli anni ottanta. Il dibattito sulle strategie legate all’introduzione di tecnologie avanzate muove da ragioni dominate da inferenze di tipo ecomonico,
determinate dalla globalizzazione della competitizione industriale.
Col passare del tempo i microprocessori raggiungono complessità crescenti che appiattiscono, dal punto di vista delle prestazioni, le diverse classi
di calcolatori che avevano dominato il ventennio precedente a causa della
maturazione delle tecnologie, della diffusione sempre crescente dei calcolatori in tutti i settori produttivi e della conseguente riduzione dei loro costi
(figura (1.2)). Spesso si assume che in origine tutti i processori fossero
macchine RISC, con un piccolo numero di istruzioni gerarchiche che potevano essere eseguite in sequenza. Le esigenze sempre crescenti portarono
all’introduzione della microprogrammazione per il progetto di processori più
sofisticati. Il passo fondamentale per la semplificazione delle archittetture è, paradossalmente, il miglioramento del software, in particolare dei
sistemi operativi e dei compilatori [8]. La prima macchina RISC fu il minicalcolatore IBM-801 (1975), ma le più note macchine di questa categoria
restano la MIPS di John Hennessy (1984) e la SPARC
5
della Sun Micro-
system (1987). Già dagli anni sessanta si era pensato che più calcolatori
opportunamente programmati avrebbero potuto risolvere problemi di gran4
Acronimo coniato da gruppo di Berkeley guidato da D. Patterson e C. Séquin
che progettarono nel 1980 il VLSI-RISC (Reduced Instruction Set Computer) che
portò ai processori RISC I e II.
5
Scalable Processor ARChitecture.
Mauro Ennas
Creative Commons 2013
5
Cray X-MP
Figura 1.3:
Evoluzione delle prestazioni delle macchine parallele.
de complessità, più velocemente, se avessero potuto funzionare parallelamente cioè applicando gli stessi algoritmi su insiemi diversi di dati, oppure
applicando algoritmi differenti contemporaneamente sugli stessi dati. Nel
1964 nasce CDC-6600 a parallelismo interno estensivo, ben dieci volte più
veloce della IBM-7094 che dominò il calcolo scientifico negli anni ’60. Il
primo supercalcolatore parallelo fu il CRAY-1 del 1974.
I supercalcolatori sono stati concepiti per risolvere problemi di calcolo scientifico altamente estensivi ed intensivi; cioè in grado di lavorare su grosse
quantità di dati e di massimizzare il numero di operazioni in virgola mobile per secondo FLOPS (FLoating point Operations Per Second). Qualsiasi
macchina che non raggiunga prestazioni di 1 Giga-FLOPS non viene considerata un supercalcolatore (figura (1.3)).
Generalmente le archittetture parallele vengono progettate per applicazioni
molto particolari ma negli ultimi anni si stanno imponendo sempre più sistemi dalle caratteristiche flessibili, applicabili a più ambiti, grazie alle migliorate caratteristiche dei processori. Seymour Cray padre delle macchine
CDC, fondò la società che prende il suo nome e che attualmente produ-
Mauro Ennas
Creative Commons 2013
6
ce il T3D e T3E. Negli anni novanta le macchine a parallelismo massiccio
che hanno avuto maggiore successo commerciale sono, oltre alle macchine
Cray, la Connection Machine (Thinking Machine Corporation) e l’IBM-SP2.
In Italia l’Alenia Spazio ha progettato in collaborazione con il CNR, l’INFN e
l’ENEA le macchine denominate QUADRICS, in due modelli QH16 6 e QDeSC 7 , variamente configurabili.
In questo primo capitolo verranno introdotte le nozioni base del calcolo
parallelo, relativamente ad architetture, linguaggi e compilatori. Verrà data particolare enfasi ai concetti legati al modello di programmazione data
parallel ed al linguaggio High Performance FORTRAN, indicando le caratteristiche in base alle quali è stato scelto per il progetto di software scientifico ad alte prestazioni (High Performance Computing). Verranno indicate
le caratteristiche salienti del calcolatore parallelo IBM-SP2/30 del CRS4,
utilizzata per lo sviluppo e il testing dei codici che verranno descritti dettagliatamente nei capitoli successivi. Nella parte conclusiva del capitolo
vengono definiti alcuni importanti indicatori di prestazioni.
6
7
Sino a 200 GFLOPS.
Sino ad 1 GFLOPS.
Mauro Ennas
Creative Commons 2013
Mauro Ennas
Nome
Costruttore
Note
1934
Analytical Engine
Babbage
Primo calcolatore numerico (non riuscito).
1936
Z1
Zuse
Prima macchina a relè funzionante.
1943
COLOSSUS
Regno Unito
Primo calcolatore completamente elettronico.
1944
Mark I
Aiken
Primo calcolatore general purpose.
1946
ENIAC I
Mauchley/Eckert
Primo calcolatore moderno (post bellico).
1949
EDSAC
Wilkes
Primo calcolatore con programmi in memoria.
1951
Whirlwind
M.I.T.
Primo calcolatore real time.
1952
UNIVAC I
Mauchley/Eckert
Primo calcolatore commercializzato.
1960
IAS
von Neumann
Riferimento per calcolatori di II generazione.
1960
CEP
1960
ELEA 9.300
Olivetti
Primo calcolatore commerciale italiano.
1961
PDP-1
DEC
Primo minicalcolatore (50 esemplari venduti).
1962
1401
IBM
PC record di vendite negli anni ’60.
1963
7094
IBM
Calcolatore scientifico dominante negli anni ’60.
1964
B5000
Burroughs
Prima macchina con linguaggio di alto livello (Algol-60).
1964
360
IBM
Prima famiglia di calcolatori.
1965
6600
CDC
Prima macchina a parallelismo interno estensivo.
1970
PDP-8
DEC
Primo minicalcolatore di massa (50000 venduti).
1970
PDP-11
DEC
Minicalcolatore dominante negli anni ’70.
1974
8080
Intel
Prima CPU general purpose integrata.
1974
CRAY-1
Cray
primo supercalcolatore.
1978
VAX
DEC
Primo supermini a 32 bit.
Univ.
di Pisa
Più potente sistema costruito in Europa.
7
Creative Commons 2013
Anno
Capitolo 2
Architetture parallele
Un calcolatore tradizionale ha una sola CPU che emette richieste sequenziali del bus dati per leggere o scrivere in memoria o nello spazio di InputOutput, ricevendo una risposta per volta. Questa modalità di funzionamento è nota come collo di bottiglia di von Neumann. Ad essa si è pensato
di ovviare progettando calcolatori che avessero più unità di controllo, più
unità logico aritmetiche (ALU), più memorie in grado di operare in parallelo
nella esecuzione di uno o più programmi.
Sono numerosi i progetti che aggregano CPU potenti debolmente connesse
o numerose ALU e FPU (Floating Point Unit) fortemente interagenti e sincronizzate e tutta una varietà di progetti intermedi che hanno come finalità il
progetto di efficaci sistemi di calcolo parallelo.
La descrizione dei sistemi di calcolo parallelo richiede la conoscenza della
natura, della dimensione e del numero degli elementi di elaborazione e dei
moduli di memoria interagenti, nonchè delle strategie per connettere tra loro processori e memorie. In genere gli elementi di elaborazione sono CPU
complete oppure ALU minime, con dimensioni largamente variabili, da un
chip a varie decine di schede sulle quali sono montati migliaia di elementi
1.
Nel caso di CPU complete le tecnologie attuali permettono connessioni
di poco più di 1000 elementi.
1
Esistono sistemi con 65536 (CM-2) elementi di elaborazione (ALU) [8] ed
esistono progetti con oltre un milione di elementi.
Mauro Ennas
Creative Commons 2013
9
Gli elementi di memoria sono suddivisi in moduli che operano indipendentemente gli uni da gli altri. Tra gli svariati sistemi esistenti vi sono da un
lato quelli con migliaia di elementi di elaborazione e memorie della dimensione di qualche Kbyte (1 Kbyte = 210 byte = 1024 byte), dall’altra vi sono
sistemi con poche potenti unità di elaborazione con decine di Mbyte di memoria (220 > un milione di byte). Il problema cruciale è quello della velocità
relativa tra sistemi di elaborazione e memoria.
Figura 2.1:
Topologie di connessione dei processori.
Topologia. I sistemi di elaborazione parallela si diversificano, oltre che
per il progetto delle CPU e della memoria, soprattutto per le modalità con
le quali si mettono insieme i componenti [8][12].
Abbiamo due grosse
categorie per gli schemi di interconnessione:
• schemi statici: cosidetti perchè cablano tutti i componenti in un grafo
fissato (stella, griglia o anello);
• schemi dinamici: quando unità di elaborazione e memorie sono agganciati ad una rete di commutazione che guida i messaggi dinamicamente tra processori differenti e memorie.
Questa prima classificazione strutturale è tipica di un approccio top-down.
Se vogliamo evidenziare quale sia il processo di calcolo che effettivamente deve essere parallelizzato possiamo pensare che esistono problemi che
hanno bisogno di svolgere la stessa funzione su un insieme di dati di volta
in volta differente (ad esempio l’applicazione di uno stesso operatore locale
su diverse sezioni di uno stesso volume) oppure diverse funzioni su uno
stesso dataset (interrogazione di uno stesso archivio da parte di più utenti), con la stessa finalità di riduzione del tempo di elaborazione. Un sistema
Mauro Ennas
Creative Commons 2013
10
parallelo in questo senso può essere visto come un sistema time sharing,
ossia relativo ad un parallelismo delle funzioni in esecuzione in un sistema
distribito (in rete) tra processori e memoria.
Un altro modo di vedere le cose è quello di considerare un calcolatore
Figura 2.2:
Ipercubo di processori e codice di Gray. Un efficiente meccanismo di comunicazione è il
cosidetto modello dei primi vicini ed è basato su una particolare allocazione della memoria dei processori
su una matrice, attraverso una codifica binaria (codice Gray) che garantisce la vicinanza dei dati; il
codice è tale che due numeri interi consecutivi differiscono per una sola cifra binaria, in questo modo è
possibile distribuire i dati in modo tale da mantenere una relazione di stretto vicinato, minimizzando le
comunicazioni.
parallelo utilizzato per eseguire un unico lavoro costituito da più processi
paralleli parzialmente disgiunti che concorrono ad un risultato finale unitario.
Ancora, possiamo pensare a sistemi che agiscono sul flusso delle istruzioni
smistando le operazioni su più ALU operanti contemporaneamente oppure ad un alevato livello di pipeline (differenti stadi della stessa istruzione
vengono eseguiti in modo concorrente); i calcolatori vettoriali ricadono in
quest’ultima categoria.
Granulatità ed Accoppiamento. Un’altra caratteristica che ci permette
di classificare i sistemi paralleli è la cosidetta granularità (grain size). Nei
sistemi time sharing e in quelli con più CPU abbiamo una cosidetta unità
di parallelismo elevata che coincide col programma eseguibile nella sua
interezza. L’esecuzione di grosse porzioni di codice con poca o senza comu-
Mauro Ennas
Creative Commons 2013
11
nicazione tra unità di elaborazione distinte prende il nome di parallelismo a
grana grossa in contrapposizione al parallelismo a grana fine caratterizzato
dall’elaborazione di piccole porzioni di codice con una discreta comunicazione tra processori, come avviene nei calcolatori vettoriali. In genere la
granularità è un concetto che si riferisce al software ma ha un’analogia
immediata nell’hardware [8]. In questo caso si parla più propriamente di
accoppiamento
2
stretto oppure di accoppiamento debole, in relazione alla
quantità di dati che vengono scambiati in un secondo (banda di accoppiamento). In genere, i problemi con parallelismo a grana grossa lavorano
meglio su sistemi ad accoppiamento debole mentre quelli con parallelismo
a grana fine su architetture ad accoppiamento stretto, ma gli algoritmi e
le architetture esistenti sono talmente varie che una indicazione di questo
tipo può risultare fuorviante in molti casi.
Tassonomia. Si cerca di mettere ordine in una situazione di questo tipo
cercando di costruire delle vere e proprie tassonomie dei sistemi di elaborazione parallela (figura (2.3)). Tra le più note vi è certamente la tassonomia
di Flynn
3
(1972), mostrata in figura (2.3). La tassonomia di Flynn è basata
su due concetti:
• il flusso delle istruzioni, che corrisponde ad un contatore di programma; un sistema con n CPU ha n contatori di programma, quindi n
flussi d’istruzione;
• il flusso dei dati è costituito da un insieme di operandi; un programma
che calcola una funzione su un elenco di dati ha un flusso di dati,
quello che calcola la stessa funzione su più elenchi diversi di dati ha
più flussi di dati.
Poichè il flusso di istruzioni e quello di dati sono indipendenti esistono
quattro categorie di macchine parallele:
2
I sistemi con un piccolo numero di potenti CPU indipendenti che hanno una
banda di accoppiamento stretta sono dette ad accoppiamento debole, viceversa
sistemi con molti processori meno potenti ma con banda di accoppiamento più
larga sono detti ad accoppiamenti stretto.
3
Altre sono attribuite a Gayski e Pier e a Treleaven (entrambe nel 1985).
Mauro Ennas
Creative Commons 2013
12
SISD
von Neumann
MISD
SIMD
MIMD
?
Vettoriali
Cray
Cyber 205
NEC SX
Paralleli
A memoria
condivisa
Switched
ILLIAC IV
CM-2, CM-200
Ultracomputer
RP3
Butterfly
Figura 2.3:
A memoria
privata
Bus
Sequent
Encore
Firefly
Switched
Bus
Workstation
su LAN
Hypercube
Transputer
SP2
Tassonomia di Flynn.
• SISD (Single Istruction Single Data), come la tipica macchina di von
Neumann;
• SIMD (Single Istruction Multiple Data), nella quale vi è una sola unità
di controllo che esegue una sola istruzione alla volta e più ALU per
eseguire simultaneamente la stessa istruzione su diversi data-set;
• MISD è una categoria anomala in quanto dovrebbero esserci più istruzioni che operano sugli stessi dati; molti annoverano in questa categoria le macchine a pipeline;
• MIMD, cioè macchine costituite da più CPU distinte e indipendenti
che operano come parte di un sistema più grande. Molti processori o
sistemi paralleli appartengono a questa categoria.
La tassonomia di Flynn si ferma qui ma può essere estesa considerando le macchine SIMD divise in due sottogruppi, i supercalcolatori numerici
e le macchine vettoriali, inoltre anche la grande categoria delle macchine MIMD (figura (2.4)) può essere suddivisa in macchine che hanno una
memoria primaria condivisa (multiprocessori) da quelle che non ce l’hanno
(multicalcolatori, o calcolatori a memoria privata o disgiunta).
Mauro Ennas
Creative Commons 2013
2.1 La Connection Machine - TMC
Figura 2.4:
13
Schemi tipici per le archittetture parallele MIMD. [ a] Interconnessione a rete tipica
delle macchine MIMD a memoria distribuita; [ b] Interconnessione a BUS per multiprocessori a memoria
condivisa (shared-memory).
2.1 La Connection Machine - TMC
Un esempio di calcolatore SIMD è la Connection Machine (CM) progettata
da W. Daniel Hillis
4
che in seguito fondò la Thinking Machines Corporation
per costruire e commercializzare le CM, sin dal 1986.
Nel seguito ci riferiremo per semplicità alla CM-2 (figura (2.5)), precursore della più moderna CM-200 5 , allo scopo di evidenziare la complessità e
le eccezionali capacità di calcolo messe a disposizione dalle architetture a
parallelismo massiccio. La CM-2 è costituita da quattro parti (quadranti),
ciascuna delle quali è divisa in due sezioni di 8192 processori (PE-8K) ciascuna. Ogni quadrante contiene un’unità di controllo (sequenziatore) che è
in grado di eseguire un programma completo non appena è stato caricato in
memoria. Il sistema è caratterizzato dall’assenza di memoria di programma
(ovvero è una macchina di back-end), per cui dovrà appoggiarsi ad uno o
più host (sino a quattro host, ad esempio DEC-VAX). I programmi vengono
editati, compilati e collegati sull’host e quindi caricati sulla CM attraverso
4
Il progetto originario era parte della sua tesi di Ph.D. sull’intelligenza artificiale
(M.I.T. 1985).
5
Attualmente la Thinking Machines Corporation progetta e costruisce macchine
MIMD a parallelismo massiccio (CM-5)
Mauro Ennas
Creative Commons 2013
2.1 La Connection Machine - TMC
14
Nome
Costruttore
Tipo
Memoria
CM-200
TMC
SIMD Distribuita
CM-5
TMC
MIMD Distribuita
T3D (T3E)
Cray
MIMD Distribuita
Paragon
Intel
MIMD Distribuita
CS-2
Meiko
MIMD Distribuita
SP2
IBM
MIMD Distribuita
C-90
Cray
SIMD
Condivisa
PowerChallenge
SGI
MIMD
Condivisa
Tabella 2.1: Calcolatori paralleli moderni.
una griglia di interruttori 4 × 4 e quindi eseguiti.
I quattro quadranti possono operare separatamente eseguendo quattro
programmi diversi contemporaneamente; è possibile raggruppare più quadranti per formare un unico sistema di 65536 processori operanti all’unisono nella soluzione di un problema di grosse dimensioni.
Ogni processore è costituito da un’unità logico aritmetica (ALU) e da 8 Kbyte di memoria privata oltre a 4 bit di flag; le ALU sono riunite in gruppi di 16
(VLSI) e per ogni gruppo è presente un istradatore che si occupa della spedizione dei messaggi tra i processori. L’insieme di 32 gruppi viene riunito
in una piastra costituita da 160 chip ed altri circuiti integrati d’interfaccia (figura (2.6)). Sedici piastre costituiscono un sottocubo per un totale di
8196 processori, due sottocubi formano un quadrante e quattro quadranti
un cubo di 1.5 metri di lato, costituito complessivamente da 25000 circuiti
integrati.
La topologia di comunicazione e di tipo ipercubo (figura (2.2)). Un sistema
di questo tipo è in grado di effettuare 4 miliardi di operazioni in virgola
mobile al secondo.
Ogni sottocubo ha il proprio canale di I/O al quale si può collegare un sistema di memorie di massa detto data vault, oltre ad un display grafico
ed altre periferiche. Ogni data vault è costituito da ben 39 disk drive e su
Mauro Ennas
Creative Commons 2013
2.1 La Connection Machine - TMC
Figura 2.5:
15
Struttura della CM-2. L’interrutore a griglia permette la configurabilità dell’accesso alle
unità di calcolo (quadranti).
ALU
Figura 2.6:
Unità di elaborazione nella CM-2.
ognuno di essi puo essere scritto un bit, di una parola di 39, in parallelo.
Questo permette di raggiungere velocità di 40 Mbyte/sec per ognuno degli
otto sistemi data vault per un totale di 320 Mbyte/sec. La capacità totale
dei dischi è compresa tra 40 Gbyte e 80 Gbyte a seconda che si utilizzino
unità di 150 o 300 Mbyte.
Mauro Ennas
Creative Commons 2013
2.2 L’IBM-SP2
16
Caratteristiche
Numero di processori
65536
Memoria
512 Mbyte
Banda della Memoria
300 Gbyte/sec
Banda I/O
320 Mbyte/sec
Banda interprocessore
250 milioni di parole/sec
Addizione di interi (32 bit)
2500 MIPS
Addizione in virgola mobile (32 bit)
4 GFLOPS
Dissipazione di energia
28 kW
Peso
1200 kg
Tabella 2.2: Caratteristiche principali della CM-2.
2.2 L’IBM-SP2
Il sistema parallelo scalabile 6 IBM-SP2 possiede la principale caratteristica
della macchine moderne a parallelismo massiccio: la flessibilità.
Tradizionalmente il progetto di calcolatori paralleli era orientato ad usi specifici con nicchie di mercato estremamente strette. Attualmente, grazie alla
potenza delle prestazioni delle singole unità di elaborazione, vengono progettati calcolatori paralleli general pourpose, capaci di assolvere ad una
grande varietà di utilizzi.
Il sistema SP2 è un sistema basato su un’architettura message passing a
memoria distribuita. Generalmente sono disponibili sistemi con un numero di unità di elaborazione che variano tra 2 e 128 nodi (unità di processo);
sono stati sviluppati sistemi con 512 nodi ed oltre per applicazioni particolari. I singoli nodi della SP2 sono processori RISC System/6000 in tecnologia POWER2, interconnessi da una rete a commutazione di pacchetto
(packet-switched network) ad alte prestazioni, multistadio, per le comunicazioni interprocessore. Ciascuno dei nodi è dotato di memoria propria e di
una copia del sistama operativo standard AIX e di altro software di sistema
6
Configurabile con un numero variabile di processori interagenti.
Mauro Ennas
Creative Commons 2013
2.2 L’IBM-SP2
17
specifico.
Caratteristiche
Numero di processori
30 (Thin Node2)
Clock
66.7 MHz
Memoria
128 Mbyte
Bus della memoria
64 bit
Cache L1
128 Kbyte (dati) e 32 Kbyte (istruzioni)
Velocità del Bus
160 Mbyte/sec
Velocità dello Switch
150 Mbyte/sec
Peso
340-635 Kg
Tabella 2.3: Caratteristiche principali dei processori RS/6000 della SP2/30
del CRS4.
2.2.1 Componenti del sistema
Nel seguito verranno descritte con maggiore dettaglio le principali caratteristiche dei componeti del sistema parallelo IBM-SP2 (figura (2.7)). Le
caratteristiche dei singoli componenti si riflettono in modo diretto sulle essenziali caratteristiche di scalabilità, di flessibilità e sulla natura general
purpose di un sistema di questo tipo.
2.2.2 I processori
Il fattore che determina le prestazioni del sistema, in prima analisi, è l’efficienza di ogni singolo processore. Per il sistema SP2 l’IBM [9] ha utilizzato
il processore più veloce e robusto che aveva a disposizione, permettendo in
questo modo la possibilità di utilizzare il sistema multiprocessore anche in
modalità multipla monoprocessore con la stessa affidabilità.
I processori RISC System/6000 in tecnologia POWER2 sono processori superscalari (ognuno dei quali è in grado di eseguire più istruzioni concor-
Mauro Ennas
Creative Commons 2013
Figura 2.7:
{
18
{
2.2 L’IBM-SP2
La struttura dell’IBM-SP2/30.
rentemente per ogni ciclo) e funzionanti in pipeline spinto (cioè funzionanti
con frequenze molto elevate). Vi sono tre diversi tipi di nodo (wide, thin e
thin2). Ciascuno dei nodi del primo e secondo tipo hanno due unità in virgola mobile (FPU) ed un’unità di controllo d’istruzione. Il clock di 66.7 M Hz
permette ai processori di raggiungere performance di 267 MFLOPS. L’unità
di controllo d’istruzione opera sulla decodifica delle istruzioni multiple ottimizzando la loro gestione. Tutto ciò unito ad una memoria gerarchica di
grande capacità (da un minimo di 2 Gbyte) e di elevate prestazioni (banda
passante di 2.1 Gbyte/sec). La memoria cache è di 256 Kbyte a 4 vie set
associative, trasferisce quattro operandi di 64 bit (due linee) per ogni ciclo
alla FPU. I nodi dei tre tipi differiscono per la memoria (quantità e tipo) e
per la configurabilità.
2.2.3 Il sottosistema di comunicazione
Viste le elevate prestazioni del processore [9], le richieste di velocità di comunicazione sono molto elevate, le parole chiave sono larga banda e piccola
latenza. I nodi della SP2 sono interconnessi attraverso uno switch ad alte
prestazioni (HPS) progettato con caratteristiche di scalabilità, bassa latenza, larga banda, basso overhead, affidabile e flessibile. La sua topologia è
del tipo any-to-any packetswitch, multistadio e a rete indiretta (Omega network like) (figura (2.8)), ciò consente di adeguare linearmente la bisezione
della banda alla dimensione scalare del sistema (altrettanto non avviene
Mauro Ennas
Creative Commons 2013
2.2 L’IBM-SP2
19
nelle reti ad anello o in quelle reticolari). La topologia HPS permette di ave-
Figura 2.8:
Esempio di rete Omega a tre stadi per la comunicazione tra processori e memoria.
Sono presemti 12 interruttori a due ingressi (alto (0)) e due uscite per collegare 8 processori a 8 elementi
di memoria (in generale sono necessari log2 (n) stadi con n/2 interruttori per stadio).
re banda costante tra ogni coppia di nodi indipendente dalla loro posizione
reciproca. In generale la banda disponibile in un nodo è pari a:
Blink ·
Nlink
N hops
nella quale:
• Blink è la banda coinvolta nella comunicazione (link band);
• Nlink rappresenta il numero di comunicazioni per nodo nello switch;
• N hops il numero medio di stadi attraverso lo switch richiesti per l’operazione di comunicazione.
In uno switch multistadio come l’HPS sia N hops che Nlink scalano logaritmicamente col numero di nodi e viene resa costante la banda disponibile.
Nelle reti dirette il numero di stadi, per una configurazione di comunicazione casuale, cresce col numero di nodi mentre il numero di link per nodo
resta costante e quindi la banda media per coppia di nodi comunicanti
decresce. Questo punto risulta determinante in quanto evita al programmatore di dover ottimizzare il software per minimizzare N hops .
Mauro Ennas
Creative Commons 2013
2.2 L’IBM-SP2
20
Ogni nodo della SP2 è connesso alla scheda HPS tramite un adattatore intelligente Micro Channel. Questo adattatore (con microprocessore onboard)
è in grado di gestire le transazioni di messaggi direttamente sulla memoria
del processore o a partire da essa (tramite Direct Memory Access) e decrementa sensibilmente il tempo di elaborazione dei messaggi con effetti
benefici sulla gestione della banda di comunicazione.
2.2.4 Ambiente parallelo
L’ambiente parallelo viene denominato SP2-AIX [9] integrato in un insieme
di componenti permette lo sviluppo, il debugging ed il parallel tuning di
programmi in FORTRAN
7
e C, inoltre permette di inizializzare, controllare
e monitorare la loro esecuzione.
Le componenti principali dell’ambiente parallelo sono:
• la libreria Message-Passing (MPL)
libreria avanzata di comunicazione per programmi FORTRAN e C, che
utilizza protocollo TCP/IP su una connessione LAN o attraverso lo
switch.
• l’ambiente operativo parallelo (POE)
permette di compilare e di effettuare il collegamento delle librerie disponibili; permette di creare partizioni dei nodi disponibili; carica gli
eseguibili sui nodi e permette il controllo dell’esecuzione.
• i tool di visualizzazione (VT)
permettono il monitoraggio post mortem.
• il debugger parallelo (PD)
è una versione del sistema UNIX dbx - debugging tool specializzata per
il debugging parallelo.
Il file system è stato progettato ad hoc e denominato PIOFS (Parallel I/O
File System).
7
FORmula TRANslation.
Mauro Ennas
Creative Commons 2013
Capitolo 3
Programmazione parallela
Il programma parallelo è un insieme di processi per i quali esiste un ordine,
seppure parziale, non fissato rigorosamente a priori come per i programmi
sequenziali.
L’obiettivi principale della programmazione parallela è la distribuzione ottimizzata dei carichi di lavoro (load balancing) sui diversi processori con la
finalità di ottenere velocità di calcolo più elevate possibile.
La disponibilità di programmi applicativi è uno degli elementi più importanti nel successo commerciale di un sistema di calcolo. Nel caso delle
piattaforme parallele vengono richiesti applicativi per lo sviluppo di software principalmente nei linguaggi FORTRAN e C.
Vi sono esenzialmente tre modelli di programmazione parallela utilizzati
nella maggior parte dei sistemi scalabili:
• il modello di programmazione message passing;
• il modello di programmazione shared memory;
• il modello di programmazione data parallel.
Mauro Ennas
Creative Commons 2013
3.1 Modello message-passing
22
3.1 Modello message-passing
Nel modello basato sul passaggio esplicito di messaggi, i processi di un’applicazione parallela hanno ciascuno il proprio spazio d’indirizzamento privato e condividono i dati attraverso l’uso esplicito di messaggi; il processo
sorgente esplicitamente manda (primitiva SEND) un messaggio ed il processo target esplicitamente lo riceve (primitiva RECEIVE). I processi evolvono
nel senso che seguono il flusso di condivisione dei dati esplicitato direttamente nel programma attraverso le primitive SEND e RECEIVE.
I programmi generalmente hanno una struttura SPMD (Single Program Multiple Data), ossia lo stesso programma agisce su porzioni parzialmente disgiunte dei dati. Il programma in esecuzione evolve secondo la modalità
non perfettamente sincrona (loosely synchronous style) nella quale si alternano una fase di calcolo con una di comunicazione. Durante la fase
di calcolo, ciascuno dei processi effettua i calcoli sulla porzione di dati
assegnatagli e nella fase di comunicazione i processi scambiano dati utilizzando le librerie message-passing. Un esempio di linguaggio che supporta la programmazione message passing è l’OCCAM, inoltre attraverso il
FORTRAN possono essere costruite librerie, quali MPI e PVM, di supporto al modello di programmazione. Generalmente, tra i maggiori vantaggi
espressi dalla programmazione message passing vi è la concreta possibilità
di creare implementazioni estremamente veloci degli algoritmi, dipendente
strettamente dalla natura del problema e dall’abilità del programmatore.
Tra i difetti riconosciuti bisogna ricordare che la portabilità non è garantita e che la programmazione presenta delle difficoltà da non sottovalutare
nell’implementazione di codici complessi.
3.2 Modello shared-memory
Nel modello a memoria condivisa i processi facenti capo ad una applicazione parallela condividono uno spazio d’indirizzamento ed in esso effettuano
le operazioni di ingresso/uscita in modo asincrono; i dati, in questo modo,
sono condivisi rispetto allo spazio direttamente referenziato senza bisogno
Mauro Ennas
Creative Commons 2013
3.3 Modello data-parallel
23
di azioni esplicite per individuare i dati da condividere. La sincronizzazione
dei processi deve essere esplicitata utilizzando dei costrutti particolari.
Il modello di programmazione shared memory viene spesso associato al
controllo dinamico del parallelismo, nel quale porzioni logicamente indipendenti dello stesso flusso di programma possono essere considerati come
blocchi funzionali o come cicli di iterazione indipendenti.
3.3 Modello data-parallel
Con il nome modello data-parallel s’intende individuare quella classe di linguaggi che permettono di realizzare il parallelismo eseguendo una stessa
operazione, ovvero una serie di istruzioni, in modo concorrente su insiemi
di dati parzialmente disgiunti, facenti parte di una stessa struttura dati
complessiva. In questo modo ciascuna delle operazioni su ciascuno degli
elementi del dataset può vedersi come un processo indipendente dagli altri,
ciò porta a dire che la naturale granularità di un linguaggio data parallel è
una granularità fine.
Il modello di programmazione con parallelismo nei dati viene supportato
da linguaggi quali l’High Performance FORTRAN (HPF). I programmi sono
scritti utilizzando il FORTRAN 90 sequenziale per specificare le operazioni
sui dati, attraverso l’uso di costrutti particolari per le operazioni su vettori
e matrici oltrechè direttive intrinseche dell’HPF per mappare i dati in modo
che possano essere distribuiti sui vari processori.
Il preprocessore o il compilatore HPF traducono il codice sorgente scritto
utilizzando FORTRAN 90 più le direttive del linguaggio HPF in un codice
equivalente SPMD con chiamate message passing (se il sistema supporta un’architettura message passing come nel caso dell’SP2) oppure con le
appropriate sincronizzazioni (se il sistema supporta un’architettura time
sharing). Il carico di calcolo viene distribuito ai processi paralleli secondo
le specificazioni fornite attraverso le direttive di distribuzione HPF. Questo
approccio ha il grande vantaggio di liberare il programmatore dal compito
di distribuire matrici globali su matrici locali, sostituendo indici e rinominandoli oltre che indicare esplicitamente le chiamate per la trasmissione e
Mauro Ennas
Creative Commons 2013
3.3 Modello data-parallel
24
la ricezione dei dati o la loro sincronizzazione. Un’altro vantaggio notevole
dello scrivere codici in HPF è la compatibilitá con il FORTRAN standard,
agevolando il porting e la manutenzione dei codici, oltre che lo sviluppo su
workstation monoprocessore.
Esempi di linguaggi che supportano la programmazione data parallel sono
CM FORTRAN, CRAFT, C ∗ , FORTRAN D e VIENNA FORTRAN.
Mauro Ennas
Creative Commons 2013
Capitolo 4
Programmazione data-parallel
I linguaggi data-parallel forniscono un modello astratto di parallelismo, indipendente dalla macchina.
Linguaggi di questa categoria hanno la caratteristica di permettere operazioni parallele a grana fine, devono permettere la condivisione dei dati
attraverso operazioni di mapping dei dati ed inoltre la sincronizzazione implicita delle operazioni su di essi.
Ciò permette di rendere le operazioni globali, su matrici anche di grandi
dimensioni, concettualmente semplici e di semplificare la programmazione
scientifica degli algoritmi. Lo svantaggio più rilevante sta nella complicazione dei compilatori. Un approccio di questo tipo distribuisce il lavoro tra
programmatore e compilatore:
• Il programmatore dovrà concentrare la sua attenzione sui concetti e le
strutture di alto livello, aggregando le operazioni operanti su strutture
dati di grosse dimensioni e fornendo le informazioni per la mappatura
dei dati su matrici globali (array sintax).
• I compiti del compilatore sono quelli di tradurre il mapping concettuale in una distribuzione fisica, su un numero finito di processori, permettendo l’efficacia del parallelismo mediante la cura dei dettagli, fornendo all’utilizzatore indicazioni per attuare le direttive di
distribuzione dei dati e ottimizzando le comunicazioni.
Mauro Ennas
Creative Commons 2013
4.1 L’High Performance Fortran
26
4.1 L’High Performance Fortran
La necessità di creazione di uno standard per la programmazione dataparallel dei supercalcolatori ha trovato una prima adeguata risposta con
la costituzione di un comitato operativo nel Novembre 1991, denominato
High Performance FORTRAN Forum (HPFF), che portò all’uscita delle prime
note HPF Specification v1.0, nel Maggio 1993.
Nel 1994 compaiono i primi compilatori commerciali e nel corso dei due
anni successivi molte compagnie, non solo negli ambiti tecnologici affini
ma anche importanti società industriali interessate allo spin-off tecnologico
promosso da un’iniziativa di questo tipo, aderiscono all’HPF Forum.
Attualmente il consorzio di ricerca è costituito da circa 40 tra industrie,
università e laboratori di tutto il mondo non ancora legati formalmente con
gli organi internazionali per la standardizzazione ma in contato con l’ANSI
1
X3J3 [1].
Gli obiettivi dell’HPF Forum sono quelli di definire un linguaggio con le
seguenti caratteristiche:
• basato sul modello data parallel;
• tale da permettere elevate prestazioni su architetture SIMD e MIMD;
• tale da permettere la portabilità dei codici su varie piattaforme architetturali.
Questi obiettivi possono essere raggiunti tramite la definizione di nuove
caratteristiche del linguaggio, quali:
• funzioni intrinseche per il mapping dei dati;
• costrutti che operano in parallelo sui dati;
• direttive per il compilatore.
Il linguaggio HPF poggia sui costrutti propri del FORTRAN 90 [6], al quale
unisce direttive per l’allineamento e la distribuzione dei dati estendendo le
librerie ed offrendo la possibilità di creare interfacce con altri linguaggi.
1
American National Standards Institute.
Mauro Ennas
Creative Commons 2013
4.2 Il FORTRAN 90
27
4.2 Il FORTRAN 90
Il FORTRAN 90 è significativamente migliore del FORTRAN 77 [7], in quanto contiene direttive e costrutti che ne semplificano l’uso e migliorano la
leggibilità dei codici, carattteristica questa, di grande rilievo nei progetti di
grosse dimensioni. I miglioramenti più importanti riguardano le operazioni
sulle matrici e sui vettori, la possibilità di definizione dei tipi (come avviene
in altri linguaggi di alto livello come il C) e nuovi costrutti di controllo e di
allocazione dinamica, l’introduzione dei puntatori e di nuove funzionalità
intrinseche.
Il FORTRAN 90 (F90) può essere visto come un sottoinsieme del linguaggio
HPF, anche se alcune sue funzionalità come i puntatori, le definizioni di
tipo e i moduli non sono ancora presenti nei compilatori in commercio; il
lavoro di adeguamento è tutt’ora in corso.
Le caratteristiche più rilevanti del linguaggio riguardano le operazioni sulle
matrici. La sintassi del F90 è molto sintetica e minimizza l’uso degli indici,
come puó notarsi dall’esempio seguente:
F77
F90
REAL
A(100,100)
.......
DO i=1, 100
REAL, DIMENSION(100,100)
:: A
.......
A = 4.0
DO j=1, 100
A(i,j) = 4.0
ENDDO
ENDDO
Un’altra caratteristica importante è il costrutto di controllo WHERE che
equivale ad un IF su ciascuno degli elementi della matrice:
REAL, DIMENSION(3,3) :: A
.......
WHERE(A < 5.0)
A = 5.0
Mauro Ennas
Creative Commons 2013
4.2 Il FORTRAN 90
28
ELSE WHERE
A = 2*A + 1.0
ENDWHERE
che produce il risultato mostrato in figura (4.1).
Gli indici possono essere gestiti in modo semplice per individuare insiemi
5
Figura 4.1:
Il costrutto WHERE permette di effettuare un IF su ogni elemento della matrice globale
(A nell’esempio).
all’interno di vettori e matrici nella forma:
indice − iniziale : indice − finale : passo
come nell’esempio seguente
REAL, DIMENSION(100) :: A
.......
c A(1) = A(2) = ...= A(100) = 0.0
A(1:100)
=
0.0
c A(50) = A(51) = ... = A(100) = 1.0
A(50:100) =
1.0
c A(1) = A(3) = .... = A(49) = 2.0
A(1:50:2)
=
2.0
Le operazioni sulle matrici possono essere effettuate se c’è congruenza
dimensionale, ovvero:
INTEGER :: A(50), B(10)
Mauro Ennas
Creative Commons 2013
4.2 Il FORTRAN 90
29
.......
c B(1) = A(5), B(2) = A(10), ... ,B(10) = A(50).
B = A(1:50:5)
c B(1) = B(1)*A(21), B(2) = B(2)*A(22), ... , B(10) = B(10)*A(30).
B = B*A(21:30)
Vi sono direttive per l’allocazione e la deallocazione dinamica della memoria 2 :
REAL, DIMENSION(:,:), ALLOCATABLE :: A
INTEGER
:: nx
.......
nx = 100
ALLOCATE ( A(0,nx-1) )
.......
A = SQRT( A )
.......
DEALLOCATE( A )
La forma delle matrici può, in questo modo, non essere dichiarata esplicitamente. Sono disponibili funzioni per determinare le caratteristiche delle
matrici (SIZE, LBOUND), per costruire matrici (SPREAD, PACK, RESHAPE),
funzioni per calcolare il prodotto tra matrici (DOT PRODUCT, MATMUL),
funzioni di riduzione che a partire da una matrice determinano il massimo o la somma degli elementi (MAXVAL, SUM) oppure applicano operatori
logici ad insiemi particolari di dati (ANY, ALL), funzioni che determinano
la locazione indiciale di massimi e minimi relativi (MAXLOC, MINLOC) e
funzioni per manipolare le matrici come oggetti globali (CSHIFT, EOSHIFT,
TRANSPOSE).
Un esempio di funzione per costruire matrici è la funzione SPREAD che
agisce come mostrato in figura (4.2). Per manipolare le matrici (ad esempio
le immagini) si fa largo uso della funzione di traslazione ciclica CSHIFT (figura (4.3)). La varietà delle funzioni e delle direttive rendono il linguaggio
2
Contrariamente a quanto avviene in FORTRAN 77.
Mauro Ennas
Creative Commons 2013
4.2 Il FORTRAN 90
30
Figura 4.2:
La direttiva SPREAD.
di facile utilizzo e la sua efficacia viene dimostrata dalla facilità d’implementazione di algoritmi complicati.
Inoltre, non devono essere trascurate tutte quelle caratteristiche che già
appartenevano al F77 e che sono patrimonio comune, almeno nella semantica (non certo nella sintassi), dei linguaggi moderni di alto livello. Questo
Figura 4.3:
La direttiva CSHIFT.
breve paragrafo non ha la pretesa di essere esaustivo
3
ma solo quella di
indicare le principali caratteristiche di un linguaggio che a detta di molti
dominerà lo scenario della programmazione scientifica avanzata dei prossimi anni, grazie ad altre sue importanti caratteristiche quali la gestione dei
puntatori e delle stutture come i più moderni linguaggi di programmazione.
3
Per una completa descrizione del linguaggio si rimanda a testi specifici quali
[6].
Mauro Ennas
Creative Commons 2013
4.3 Caratteristiche del linguaggio HPF
31
4.3 Caratteristiche del linguaggio HPF
La programmazione data-parallel si pone gli ambiziosi obiettivi di ridurre la
complessità della programmazione parallela e nel contempo di permettere
operazioni a grana fine efficienti nel senso del costo computazionale.
L’HPF ha diverse possibilità per muoversi in questa direzione. La prima
è senza dubbio quella offerta dal supporto del F90 con le operazioni sulle
matrici; un’altra è rappresentata dalla procedura FORALL che permette di
utilizzare cicli basati sulla struttura dello spazio degli indici, generalizzando
il concetto di assegnamento dei valori ad una matrice tipico delle istruzioni
di controllo quali il WHERE.
Il FORALL viene eseguito in quattro passi:
• calcolo degli indici validi
• definizione degli indici attivi
• valutazione delle espressioni al secondo membro
• valutazione delle espressioni al primo membro
Gli elementi di ciascuno stadio vengono valutati in parallelo ed ogni stadio
del ciclo deve essere portato a termine prima che inizi il sucessivo; un
comportamento non conforme si evidenzia nell’assegnare valori diversi alle
stesse locazioni di memoria, per lo stesso stadio del ciclo.
Il FORALL risulta utile in diverse situazioni:
• negli assegnamenti in funzione degli indici
FORALL (i=1:N, j=1:M) A(i,j) = SQRT( 1.0/ REAL(i+j) )
• nella distribuzione di dati a partire da geometrie irregolari:
FORALL (i=1:N) B(i) = A(i,i)
• nelle operazioni che utilizzano funzioni definite dall’utente:
FORALL (i=1:N, j=1:M) A(i,j) = FUNZIONE(DATO1(1,j), DATO2(i,j))
Mauro Ennas
Creative Commons 2013
4.3 Caratteristiche del linguaggio HPF
32
begin
begin
b[1]
b[2]
b[3]
b[1]
b[2]
b[3]
a[1]
a[2]
a[3]
a[1]
a[2]
a[3]
d[1]
d[2]
d[3]
d[1]
d[2]
d[3]
c[1]
c[2]
c[3]
c[1]
c[2]
c[3]
end
end
Figura 4.4:
FORALL e ciclo DO a confronto.
Possiamo confrontare un esempio di FORALL con un’esempio di ciclo DO,
come mostrato in figura (4.4). Se un’iterazione scrive su una locazione appartenente ad una variabile riutilizzata nel ciclo e vogliamo che ciò non
accada, dobbiamo fare uso della direttiva INDIPENDENT (figura (4.5)). Le
librerie HPF possiedono un grande numero di funzioni, per la descrizione
delle quali si rimanda alla lettura dei manuali dell’attuale versione dello
standard del linguaggio (HPF Specifications v x.0) [1].
Un’inportante categoria di funzionalità intrinseche del linguaggio sono quelle per la distribuzione dei dati all’interno dei singoli processori.
begin
b[1]
b[2]
b[3]
a[1]
a[2]
a[3]
d[1]
d[2]
d[3]
c[1]
c[2]
c[3]
end
Figura 4.5:
Mauro Ennas
La direttiva INDIPENDENT.
Creative Commons 2013
4.3 Caratteristiche del linguaggio HPF
33
4.3.1 Il mapping dei dati
Il cosidetto mapping consiste nella distribuzione dei dati all’interno dei processori per ottenere un agevole accesso parallelo agli stessi [3][2]. L’HPF
utilizza due modalità per il mapping dei dati:
• la distribuzione vera e propria viene attuata attraverso la direttiva al
compilatore DISTRIBUTE che divide gli elementi di un oggetto tra i
vari processori a disposizione, secondo modalità prestabilite;
• l’allineamento dei dati ottenuto attraverso la direttiva al compilatore
ALIGN che crea una relazione tra gli oggetti utilizzati nel calcolo.
Il linguaggio prevede un’ulteriore livello di mapping che può essere proposto
a cura dei progettisti delle varie versioni dei compilatori. Altre direttive sono
Figura 4.6:
Mapping dei dati dal modello astratto ai processori fisici.
PROCESSORS che determina la forma della griglia di processori astratti e
TEMPLATE che permette di agire sullo spazio degli indici per permettere
allineamenti anche complicati [3]. Vi sono anche funzioni d’interrogazione
che permettono di conoscere run-time alcune informazioni quali il numero
di processori utilizzati e la forma della griglia fisica dei processori.
La direttiva di distribuzione si esprime nel modo seguente:
!HPF$
Mauro Ennas
DISTRIBUTE
A(tipo.distribuzione)
Creative Commons 2013
4.3 Caratteristiche del linguaggio HPF
34
oppure
!HPF$
DISTRIBUTE
(tipo.distribuzione) ::
A
Il tipo.distribuzione può essere BLOCK, CYCLIC oppure * (leggi star).
La dichiarazione seguente
INTEGER, DIMENSION(100)
:: A
.......
!HPF$
DISTRIBUTE
A(*)
significa che tutti i 100 elementi del vettore A devono essere ricopiati
(collassati) su ogni processore. Altri esempi di distribuzione sono ripor(BLOCK, *)
(BLOCK,BLOCK)
(*, CYCLIC)
(CYCLIC(2), CYCLIC(4))
Figura 4.7:
La direttiva di distribuzione dei dati DISTRIBUTE.
tati in figura (4.7). Dalla distribuzione dei dati, oltre che dall’algoritmo,
dipendono i tempi di comunicazione tra i processori, questo implica una
dipendenza stretta tra la natura del problema che si vuole risolvere e l’implementazione data parallel che si è in grado di realizzare. Ci viene in aiuto
la direttiva di allineamento ALIGN che permette di distribuire gli elementi
Mauro Ennas
Creative Commons 2013
4.3 Caratteristiche del linguaggio HPF
35
di un nuovo oggetto concordemente ad uno già distribuito e col quale si
vuole che interagisca nelle varie fasi del calcolo. Per modificare gli assetti
gia fissati durante l’esecuzione del programma si utilizzano direttive quali REDISTRIBUTE e REALIGN che, com’è facile supporre, utilizzano grossi
intervalli temporali per la comunicazione tra i processori che si scambiano
i dati da ridistribuire.
Mauro Ennas
Creative Commons 2013
Capitolo 5
Compilatori per macchine
parallele
5.1 PGHPF
Il compilatore utilizzato su IBM-SP2/30 è il compilatore commerciale HPF
della Portland Group Inc. (PGI).
Esso è implementato per funzionare su una grande varietà di architetture parallele (Intel-Paragon, Cray T3D e T3E, SGI-PowerChallenge) e risulta
compatibile con ambienti distribuiti come i cluster di workstation.
Il comando principale è pghpf (definito compilation driver); esso controlla le
varie fasi della compilazione: la compilazione del linguaggio HPF vera e propria, la pre-elaborazione e la compilazione FORTRAN 77, l’assemblaggio e il
collegamento (che include le routine del run time system PGI HPF). L’esecuzione di pghpf può essere effettuata su sistemi differenti e produce output
per sistemi differenti, con comandi disponibili variabili da sistema a sistema. In generale, utilizzando pghpf, il processo di sviluppo e compilazione è
costituito di tre fasi:
• La prima fase è caratterizzata dalla produzione di un programma HPF
(con estensione .hpf, .f90, .for, .F o .f) scritto per essere eseguito in
parallelo.
Mauro Ennas
Creative Commons 2013
5.1 PGHPF
37
• La compilazione del programma HPF utilizzando il comando pghpf
con le varie opzioni disponibili. Ciò permette di ottenere un file oggetto che include le librerie messe a disposizione dal run time system
HPF.
• L’esecuzione del modulo oggetto su un sistema target rappresenta la
terza ed ultima fase. Il comportamento dell’ esecuzione può essere
controllato sulla linea di comando o con variabili d’ambiente.
Sono comunque possibile variazioni rispetto a questa sequenza generale
di sviluppo che permettono, ad esempio, di fermare la compilazione nelle varie fasi intermedie per esaminare i risultati prodotti. Esistono tutta
una serie di opzioni che possono essere abilitate o meno a seconda delle
esigenze, queste caratteristiche non verranno evidenziate anche se hanno
una grande importanza pratica nel processo di produzione del software.
Il modello di riferimento è un modello SPMD (Single Program Multiple Data), ciò significa che ciascuno dei processori esegue lo stesso programma,
ma su dati differenti (in pratica l’immagine dello stesso programma viene
caricata su ogni processore). Ne consegue una allocazione della porzione di
dati assegnata a ciascuno dei processori, in accordo con le direttive di distribuzione, con la dimensione delle matrici da distribuire e col numero di
processori, determinata a run-time dal compilatore o utilizzando argomenti
attraverso comandi in linea.
Le librerie messe a disposizione attraverso pghpf tengono conto delle comunicazioni che devono essere attuate procedendo all’ottimizzazione a due
livelli. Un primo livello che tiene conto della dimensione e geometria dei
dati e dei processori coinvolti nel processo di calcolo (trasport indipendent
level) ed un secondo livello (trasport dipendent level) nel quale si fa riferimento ad un protocollo standard di comunicazione oppure a particolari
meccanismi di trasferimento dei dati.
Mauro Ennas
Creative Commons 2013
5.2 ADAPTOR
38
5.2 ADAPTOR
Il traduttore ADAPTOR 1 (Automatic Data Parallelism TranslatOR) è un software applicativo public domain in grado di trasformare programmi scritti
secondo il modello data parallel in FORTRAN 77 + estensioni (utilizzando
le matrici generalizzate, cicli paralleli e direttive di distribuzione ed allineamento dei dati) in un programma parallelo con passaggio esplicito di
messaggi (message passing) [10] [11]. Il linguaggio utilizzato nel programma d’ingresso può essere il CM FORTRAN o l’High Performance FORTRAN
2.
Il codice che viene generato è un codice message passing che può esse-
re eseguito su differenti sistemi multiprocessore a memoria distribuita ma
anche a memoria condivisa o su architetture a memoria virtuale condivisa.
ADAPTOR è costituito essenzialmente di due elementi, un nucleo di trasformazione da sorgente a sorgente denominato fadapt e la libreria del run time
system DALIB (Distribuited Array LIBrary) [4]. Per compilare e collegare il
Figura 5.1:
La struttura di ADAPTOR.
programma generato, viene utilizzato il compilatore FORTRAN disponibile
1
Progettato e realizzato da Thomas Brandes del GMD (German National Center
of Mathematics and Computer Science) di Bonn.
2
Allo stadio attuale dello sviluppo del compilatore non tutte le direttive di questi
linguaggi sono supportate.
Mauro Ennas
Creative Commons 2013
5.3 Prestazioni degli algoritmi paralleli
39
sulla macchina parallela utilizzata; fadapt genera due programmi, un programma host.f che gestisce le operazioni di I/O che devono essere eseguite dal nodo scelto come front-end del sistema e un programma node.f che
verrà eseguito su ogni nodo disponibile della macchina. Vi sono anche altre
due modalità di funzionamento, una delle quali genera solo il programma
node.f utilizzando il primo nodo per le operazioni di I/O, l’altra è la modalità UNIPROC ossia il funzionamento sul nodo singolo, in quest’ultimo caso
la traduzione produrrà un codice F77 sequenziale.
5.3 Prestazioni degli algoritmi paralleli
Gli algoritmi sequenziali vengono valutati in termini di tempo di esecuzione
in funzione della quantità di dati in ingresso. Nelle architetture parallele il
tempo di esecuzione non dipende solo dalla mole di dati da elaborare ma
soprattutto dal numero di processori e dal modo in cui tali processori interagiscono.
La valutazione delle prestazioni degli algoritmi paralleli risulta strettamente
legata all’architettura cui si fa riferimento. Un primo importante concetto
è la cosidetta scalabilità di un algoritmo eseguito su una certa architettura, che rappresenta una misura della proporzionalità delle prestazioni in
funzione del numero di processori che vengono utilizzati. Le prestazioni
possono essere valutate in vari modi, attraverso degli indicatori dell’efficienza computazionale; i più usati sono il run-time, lo speed-up, l’efficienza
e il costo [12] [5].
Run-Time. Per un programma seriale il run-time rappresenta il tempo
totale di esecuzione Ts su un calcolatore sequenziale, mentre il run-time
parallelo Tp rappresenta il tempo intercorrente tra l’avvio dell’esecuzione e
l’istante in cui l’ultimo dei processori attivi termina l’esecuzione.
Speed-up. Può essere indicativo sapere quali vantaggi possono aversi nel
parallelizzare un codice implementati in modo sequenziale. Lo speed-up
misura il guadagno che si realizza risolvendo il problema in parallelo e viene definito come il rapporto tra il tempo richiesto per risolvere il problema
Mauro Ennas
Creative Commons 2013
5.3 Prestazioni degli algoritmi paralleli
40
su un singolo processore e quello necessario per risolvere lo stesso problema su un calcolatore parallelo costituito da n processori identici .
Dato un problema, possono esistere più soluzioni sequenziali dello stesso
algoritmo, non tutte parallelizzabili allo stesso modo. In genere viene preso
come riferimento, se esiste, l’algoritmo sequenziale più veloce e lo speed-up
viene definito con riferimento ad esso e alla sua parallelizzazione:
S(p) =
|Ts |min
Tp (n)
ossia lo speed-up viene definito come il rapporto tra il run-time minimo (cioè
relativo all’algoritmo seriale più veloce) ed il run-time parallelo dello stesso
algoritmo su p processori identici al singolo processore utilizzato per il test
sequenziale.
Come esempio consideriamo un algoritmo che somma n numeri con n = 2k
e k ∈ N ; consideriamo n processori che operano parallelamente in modo
da effettura la somma totale per sucessive somme parziali di 2, 4, 8, ..2k elementi. Il tempo di calcolo seriale sarà una certa funzione di n, diciamo Y (n)
mentre per l’algoritmo parallelo in questione sarà Y (log(n)). Lo speed-up lo
indicheremo come:
S(n) =
Y (n)
Y (log(n))
Efficienza. Un calcolatore parallelo ideale potrà eseguire un algoritmo
operante su N dati con n processori in un tempo
t∝
N
,
n
ma ciò significherabbe considerare le comunicazioni istantanee e ciò nella
realtà non è realizzabile. L’efficienza viene introdotta come indicatore della
quantita di tempo nella quale il processore viene effettivamente utilizzato,
definita come il rapporto tra speed-up e numero di processori:
E=
S
.
n
Dall’esempio precedente risulta E = 1/Y (log(n)).
Costo. Il costo necessario per risolvere un problema su un sistema parallelo viene definito come il prodotto tra il run-time ed il numero di processori
utilizzati:
C = Tp · n;
Mauro Ennas
Creative Commons 2013
5.3 Prestazioni degli algoritmi paralleli
41
viene anche indicato come lavoro o prodotto tempo-elaborazione.
Overhead. La funzione di overhead tiene conto di quella parte del costo che
non è dovuta all’elaborazione ma ad altri fenomeni come le comunicazioni.
In pratica si considera qualla porzione di tempo in più rispetto al tempo
necessario al più veloce algoritmo sequenziale per completare le elaborazioni. Se indichiamo con Tw il tempo del migliore algoritmo sequenziale,
l’overhead risulta:
To = n · Tp − Tw .
Tipo
Numero di Processori Velocità di calcolo tipiche
Hitachi SR 2201
1024
1 TFLOPS
Intel XP/S
3680
700 GFLOPS
Cray T3D
1024
500 GFLOPS
IBM SP2
512
440 GFLOPS
SGI Power Challange
288
110 GFLOPS
Cray2
4
1.6 GFLOPS
Tabella 5.1: Prestazioni tipiche dei moderni calcolatori paralleli.
5.3.1 Modello semplificato per i tempi di calcolo
Per un modello semplificato di programma parallelo avremo un tempo totale di esecuzione dato dall’espressione seguente:
Ttot = Tseq +
Tpar
+ Tcom
p
(5.1)
nella quale Tseq tiene conto dell’eventuale presenza di parti esclusivamente
sequenziali all’interno del codice (come accade generalmente per l’input e
l’output dei dati), Tpar è il tempo impiegato da ciascuno degli n processori
utilizzati nell’azione di calcolo, mentre il tempo Tcom tiene conto del tempo
impiegato nella comunicazione tra processori e nella sincronizzazione dei
processi e dei dispositivi.
Mauro Ennas
Creative Commons 2013
5.3 Prestazioni degli algoritmi paralleli
Figura 5.2:
42
A
B
C
D
Comunicazioni: esempio di distribuzione (BLOCK,BLOCK).
Le richieste di parallelismo e di minimizzazione del tempo Tcom possono ottenersi in modo spontaneo in certi problemi (embarrassingly parallel
problems) come nel caso degli algoritmi di basso livello per l’elaborazione
delle immagini o per i metodi di decomposizione (domain decomposition),
ma nella maggioranza dei casi sono in conflitto tra loro in quanto il parallelismo estremo richiederebbe un processore per ogni stadio consistente di
elaborazione mentre la minimizzazione delle comunicazioni richiederebbe
di avere tutti i dati necessari ad una elaborazione distribuiti su un unico
processore [3]. Soddisfare entrambe le condizioni significa rendere l’algoritmo sequenziale. I problemi di conflitto hanno la loro causa nella natura del
problema, nell’architettura della macchina cui si fa riferimento e nel compilatore (soprattutto se in continua evoluzione, come nel caso dei compilatori
HPF).
Mauro Ennas
Creative Commons 2013
Bibliografia
[1] A.A.V.V. HPF - language specifications. Rice University, Huston Texas,
1993.
[2] Erwing A.K., Richiardson H., Simpson A.D., and Kulkarni R. Writing Data Parallel Program with HPF. Edinburgh Parallel Computing
Center, University of Edinburgh, 1995.
[3] Koelbel C. HPF in Pratice. Rice University, 1996.
[4] Greco D. and Cabitza G. HPParLib++ : a Run-Time System for High
Performance Fortran. CRS4 TECH-REP-95/3, 1995.
[5] Baiardi F., Tomasi A., and Vanneschi M. Architetture dei sistemi di
elaborazione. Franco Angeli, 1991.
[6] Kerrigan J. F. Migrating to Fortran 90. O’Reilly and Associates, Inc.,
1993.
[7] Hellis T. M. R. Fortran 77. Zanichelli, 1989.
[8] Tanenbaum A. S. Architettura del computer - un approccio strutturale.
Prentice Hall International - Jackson libri, 1991.
[9] Agerwala T., Martin J.L., Mirza J.L., Sadler D.C., Dias D.M., and Snir
M. SP2 system architecture. IBM Corporation, Vol. 34, No. 2 - Scalable
Parallel Computing, 1995.
[10] Brandes T. Compiling Data Parallel Programs to Message Passing, Programs for Massively Parallel MIMD Systems. German National Center
of Mathematics and Computer Science, 1993.
Mauro Ennas
Creative Commons 2013
BIBLIOGRAFIA
44
[11] Brandes T. ADAPTOR - Users Guide - Version 2.0. German National
Center of Mathematics and Computer Science, 1994.
[12] Kumar V., Grama A., Gupta A., and Karypis G. Introduction to Parallel Computing. University of Minnesota, The Benjamin/Cummings
publishing Company - Inc., 1994.
Mauro Ennas
Finito di stampare il 6 luglio 2013 utilizzando LATEX 2ε
Creative Commons 2013