Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Facoltà di Ingegneria
Corso di Laurea MAGISTRALE in Ingegneria Informatica
Progetto:
Implementazione parallela della
FFT su IBM RS/6000 SP con
librerie MPI.
Studenti: Professore:
Giuseppe Cassano 602102 Prof. Gianfranco Bilardi
Mirco Furlan 601050
Nicolo Paganin 607267 Assistente:
Ing. Michele Scquizzato
Indice
1 Introduzione 3
1.1 Fast Fourier Transform . . . . . . . . . . . . . . . . . . . . . . 3
2 Descrizione dell’algortimo 3
3 Implementazione Parallela 5
3.1 Descrizione dell’implementazione . . . . . . . . . . . . . . . . 5
3.2 Funzionamento e scelte implementative . . . . . . . . . . . . . 6
5 Conclusioni 15
3
1 Introduzione
1.1 Fast Fourier Transform
Sia x = (x0 , x1 , ..., xn−1 ), x ∈ Cn un vettore di numeri complessi. Si definisce
DF T (x), trasformata discreta di Fourier del vettore x, il vettore X =
(X0 , X2 , ..., Xn−1 ), X ∈ Cn tale che
N −1
2πi
X
Xk = xn e− n
kj
k = 0, ..., N − 1
j=0
2 Descrizione dell’algortimo
L’algoritmo di Cooley Tukey con n = p· q e p, q > 1 prevede di:
2πi/n
dove ωn è la n − esima radice dell’unità complessa e k un intero che
dipende dalla trasformata eseguita (k è scritto nell’immagine per la trasfor-
mata di ordine 8). In letteratura questo fattore moltiplicativo viene chiamato
twiddle factor.
3 Implementazione Parallela
3.1 Descrizione dell’implementazione
L’implementazione dell’algoritmo è stata progettata nel seguente modo: con-
siderando una sequenza di ingresso di lunghezza N e con a disposizione P pro-
cessori, abbiamo pensato di dividere la sequenza in P sottovettori di lunghez-
za N/P .
Ogni processore i − esimo avrà a dispozione la sequenza i − esima. Ora,
dato che ogni processore ha a dispozione N/P valori, le prime log2 (N/P )
dimensioni possono essere eseguite in locale dato che ogni processore ha a
disposizione tutti i dati neccessari per le operazioni butterfly. Queste dimen-
sioni nel seguito del progetto verranno chiamate “interne”. Per le restanti
log2 (N )−log2 (N/P ) dimensioni (chiamate dimensioni “esterne”), invece, de-
vono essere instaurate delle comunicazioni fra processori in modo da poter
scambiarsi reciprocamente il valore neccessario alle operazioni butterfly. In
particolare il processore Pi dovrà comunicare con il processore Clog2 (N/P ) Pi ,
Clog2 (N/P )+1 Pi ,...,Clog2 (N )−1 Pi 1 . In generale nella j − esima fase si avrà lo
scambio dei valori fra i processori Pj ←→ Cj Pj per log2 (N/P ) ≤ j ≤
log2 (N ) − 1.
1
Notazione vista a lezione
3.2 Funzionamento e scelte implementative 6
N = 2n n∈N N = |x|;
P = 2p p∈N P = # processori;
P < N => N/P ≥ 2. Questo vincolo garantisce che ci siano sempre
almeno due valori disponibili ad ogni processore, e che quindi non ci
siano processori che non eseguono nulla.
Util/ComplexGenerator n m
3.2 Funzionamento e scelte implementative 7
Per il calcolo delle dimensioni interne (nel punto 3) è stato utilizzato l’al-
gortirmo iterativo “in-place” di calcolo della F F T 2 tramite lo pseudocodice
riportato in Algorithm 1.
Come specificato nelle slide presentate a lezione, si sono utizzate le due
modalità di esecuzione. Per la modalità diretta (per debugging) bisogna
inserire il comando:
Algorithm 1 Iterative-FFT(x)
BIT-REVERSE(x,x̃)
n = x.lenght
for s = 1 to log(n) do
m = ss
ωm = e2πi/m
for k = 0 to n − 1 by m do
ω=1
for j = 0 to m/2 − 1 do
t = ωx̃[k + j + m/2]
u = x̃[k + j]
x̃[k + j] = u + t
x̃[k + j + m/2] = u − t
ω = ωωn
end for
end for
end for
return x̃
e successivamente
di N = 222 , pari al massimo gestibile dalla memoria dei processori. Per ogni
file di complessi in input sono stati fatti test con 1, 2, 4, 8, 16 processori. Per
ogni coppia “dimensione file di ingresso - numero processori” sono state fatte
tre misurazioni e alla fine si è preso la media dei tre tempi. Per la stima dei
tempi si sono usate le librerie “HPM Toolkit”. Si sono calcolati i tempi per
rispettivamente:
BitReversal: Tempo impiegato dal processore P0 per l’ordinamento
in bit-reversal dell’input;
Scattering: Tempo di comunicazione impiegato per trasferire a tutti i
processori il sottovettore (di lunghezza N/P ) del vettore di input;
InnerFFT: Tempo impiegato dal processore Pi per il calcolo delle di-
mensioni interne nel suo sottovettore. Sia Ti il tempo impiegato dall’i−
esimo processore per il calcolo delle dimensioni interne, TinnerF F T =
max{Ti , 0 ≤ i ≤ P };
ExternFFT: Tempo impiegato dal processore Pi per il calcolo delle
Operazioni Butterfly;
Sendrcv: Tempo di comunicazione impiegato dai processori i e j per
scambiarsi i complessi di cui hanno bisogno;
Gathering: Tempo di comunicazione impiegato dal processore P0 per
la raccolta dei sottovettori di ogni processore.
Il tempo totale delle comunicazioni è dato dalla somma dei tempi di Scatter-
ing, SendRcv e Gathering. Si precisa oltretutto che tutte le prove sono state
fatte impostando la comunicazione attraverso lo switch ad alte prestazioni e
quindi impostando nel file “.job” #@ network.mpi = switch,shared,US.
Nel caso, invece, venisse impostata la rete ethernet i tempi erano esponenzial-
mente più alti e in certi casi le comunicazioni si bloccavano, di conseguenza
non siamo riusciti a fare test in questa modalità. Tutti i test sono stati
fatti impostando nel file “.job” la direttiva #@ blocking = unlimited in
modo da allocare per ciascun nodo il massimo numero di processori possibili
e ridurre quindi al minimo il tempo di comunicazione dovuto allo scambio
di messaggi tra processori in nodi differenti. Si sono oltrettutto fatte delle
prove aggiungendo: in compilazione le ottimizzazioni standard (-O3) fornite
dal compilatore gnu gcc, nel file “.job” il buffering intermedio usando la di-
rettiva MP EAGER LIMIT con diverse capacità, senza però ottenere nessun
4.1 Prestazioni con Shared Memory 10
Figura 3: Grafico del tempo delle comunicazioni con Shared Memory abilitata
4.1 Prestazioni con Shared Memory 12
memoria. Con queste opzioni siamo riusciti a fare dei test parziali con N = 223
(in alcune occasioni si finiva lo stesso in crash) confermando il fatto che anche
con tali dimensioni di input lo speed-up cresceva di quasi il doppio.
Anche in questo caso, come nel caso precedente, ciò che si può concludere è
che l’algoritmo scala molto bene. Dal confronto dei grafici relativi a “shared
memory abilitata” e “shared memori disabilitata” è possibile vedere come il
tempo di comunicazione sia leggermente superiore nel caso di “shared memo-
ry disabilitata”. Questo si traduce in uno speed-up minore nel caso di “shared
memory disabilitata”. Infatti, il tempo di comunicazione maggiore va ad in-
cidere sul tempo totale di esecuzione dell’algoritmo che, al raddoppiare dei
processori, diminuirà meno rispetto al caso con “shared memoey abilitata”.
5 Conclusioni
In conclusione possiamo dire che il progetto è stato molto interessante e i dati
che abbiamo ottenuto sono apprezzabili. In effetti, non avendo mai fatto es-
perimenti di questo tipo, non ci aspettavamo dei risultati cosı̀ incorraggianti.
Il fatto che i tempi di comunicazione siano maggiori nel caso della memo-
ria condivisa abilitata è abbastanza ragionevole, ed è dovuto al fatto che i
processori in questa modalità sono obbligati a scambiarsi i valori tramite lo
switch. Nel caso di memoria condivisa abilitata, invece, la lettura da memoria
è sicuramente più veloce e i dati scambiati tramite switch sono in quantità
minore.
In media, il 90% del tempo viene speso totalmente per il calcolo. I risultati,
in termini di prestazione, sono molto evidenti dato che (per il caso N = 222
e P = 16) uno speed-up pari a 9 ci permette il calcolo della DF T222 in 9 sec.
invece che 1 minuto “perdendo” solo 0.6 sec. per le comunicazioni.