Architetture Parallele e Distribuite, 2008-09
Note sul supporto alle comunicazioni con processore di comunicazione
contributo di Massimiliano Meneghin
Queste note riportano una versione alternativa (più semplice) del supporto alla comunicazione tra
processi rispetto a quella presente nella Dispensa nel Cap. VI (multiprocessor) e nel Cap. VII
(multicomputer)
1. Architettura a memoria condivisa
Quanto segue vale sia per architetture SMP che NUMA.
Nelle sez. 3.2 e 3.3 del Cap. VI è riportata una versione basata sul seguente principio: il processo
mittente su IP delega completamente l’esecuzione della send a KP e si mette in condizione di
ricevere l’esito dell’esecuzione stessa (conoscere se è stato riempito completamente il buffer o
meno). A questo scopo, viene modificato l’algoritmo di scheduling a basso livello e vengono posti
dei vincoli sul numero di primitive che possono essere lanciate contemporaneamente a KP prima di
ricevere un esito; nella versione presentata è mostrato il caso più semplice in cui il processo si
blocca se, dopo aver delegato una send a KP e non aver ricevuto ancora l’esito, incontra un’altra
primitiva di comunicazione.
Questa versione ha il vantaggio di non impegnare IP nelle fasi dell’algoritmo della send, ma ha lo
svantaggio di non permettere di sovrapporre più di una comunicazione al calcolo.
È possibile pensare ad una soluzione che abbia caratteristiche complementari: impegnare
maggiormente IP nel supporto della send, e quindi ridurre un po’ il tempo di comunicazione
sovrapposto al calcolo, ma, al tempo stesso, poter delegare a KP un numero qualsiasi di primitive
contemporaneamente, sullo stesso canale o su canali diversi. In altre parole, se il programma
parallelo ha la possibilità di sovrapporre più comunicazioni al calcolo, questo viene reso possibile,
ma al prezzo di una minore sovrapposizione di ogni singola comunicazione al calcolo.
La seconda soluzione è più semplice dal punto di vista algoritmico, con poche varianti rispetto al
caso senza KP: non fa uso di un esito esplicitamente trasmesso da KP e non ha implicazioni sullo
scheduling a basso livello.
Incontrando una send con grado di asincronia k, IP accede al descrittore di canale per controllare se
il buffer (di messaggi o di capability a variabili targa) contiene attualmente k elementi. Se sì, viene
messa la variabile sender_wait a true, viene delegato il proseguimento della send a KP, e il processo
mittente si sospende. Altrimenti (meno di k elementi presenti) viene delegato il proseguimento della
send a KP e IP prosegue in esecuzione. Le azioni sul descrittore di canale sono eseguite in stato di
lock.
Ovviamente la latenza di questa fase eseguita su IP non va a sovrapporsi al calcolo e, specie se il
calcolo è di grana fine, va considerata esplicitamente nel tempo calcolo (Tcalc).
La delega a KP viene effettuata (vedi sez. 3.2) passandogli la capability da una struttura dati
contenente i parametri della send. KP esegue la send “normalmente” (eventualmente svegliando il
processo destinatario), salvo non controllare se ha riempito il buffer. Nessun esito è restituito al
mittente.
La receive è interamente seguita su IP senza modifiche rispetto all’algoritmo senza KP.
2
Per ridurre la latenza della fase della send eseguita su IP è possibile pensare di memorizzare nello
stesso blocco di cache tutte le informazioni utilizzate in tale fase. Inoltre, in una architettura
NUMA, nel caso che il descrittore di canale sia remoto, può convenire introdurre una struttura dati,
in memoria locale del mittente, contenente le informazioni usate nella fase IP e mantenute
aggiornate.
Nota: come in ogni soluzione, la sovrapposizione della comunicazione al calcolo deve essere
implementata garantendo, a programma (a compilazione), la consistenza del valore del messaggio
durante l’esecuzione della send su KP.
2. Architettura a memoria distribuita
Una soluzione analoga è utilizzabile anche per architetture a memoria distribuita, in alternativa a
quella studiata nel Cap. VII, sez. 3, senza usare esiti espliciti e senza modificare lo scheduling a
basso livello.
La struttura dati CHmitt sul nodo mittente (che non contiene l’informazione canale_in_uso)
contiene anche l’informazione sul numero di elementi attualmente nel buffer (buffer_size) e la
varabile booleana sender_wait.
All’atto dello send, su IP vengono effettuate, su CHmitt, le stesse azioni del caso multiprocessor.
KPmitt a sua volta delega KPdest all’esecuzione della send, che si conclude senza verificare lo stato
del buffer e senza inviare un esito.
Ad ogni esecuzione della receive da parte di IP del nodo destinatario, deve essere aggiornato il
valore di buffer_size nella struttura CHmitt del processo mittente. Questo viene fatto con una
comunicazione da KPdest a KPmitt; quest’ultimo aggiorna buffer_size in CHmitt (in stato di lock)
e, se trova sender_wait uguale a true, sveglia il processo mittente (resettando sender_wait).
Nell’algoritmo della sez. 3 del cap. VII vanno eliminate tutte le azioni che riguardano l’esito e lo
stato di attesa speciale.
Si noti che KPmitt può realmente lanciare più primitive contemporaneamente su uno o più KPdest,
il loro numero dipendendo dal fattore di utilizzazione della rete e dall’architettura dei nodi. Questa
possibilità esiste anche nelle architetture a memoria condivisa, progettando l’algoritmo di KP in
modo da sfruttare le latenze di accesso in memoria remota per eseguire istruzioni del supporto di
altre comunicazioni delegategli da IP (KP con architettura multithreading o, più semplicemente,
emulando tale comportamento su una architettura qualsiasi).
Scarica

Note sul supporto alle comunicazioni con processore di