Algoritmi epidemici - Dipartimento di Informatica

Università degli Studi di Bari
Laurea Magistrale in Informatica
Esame di
Sistemi Distribuiti
Implementazione e simulazione di un
algoritmo epidemico
Prof. S. Pizzutilo
Studenti:
Annamaria Cozzolongo
Fabio Pomes
Michele Tarantini
Anno Accademico 2013/2014
1
Introduzione
Un elemento importante della comunicazione nei sistemi distribuiti è il supporto per
l'invio di dati a molteplici destinatari, conosciuto anche come comunicazione
multicast. La comunicazione multicast può essere realizzata sia creando
communication path espliciti sia affidandosi a tecniche applicative che simulano i
comportamenti epidemici.
Esistono due approcci fondamentali per l'implementazione del multicast applicativo:
il primo utilizza l’organizzazione dei nodi “ad albero”, il che significa che c'è un
unico percorso tra una coppia di nodi; l’altro, invece, vede i nodi organizzati in una
rete a maglia in cui ogni nodo ha molti altri vicini, creando cosi molti percorsi diversi
per ogni coppia di nodi. La differenza principale tra i due approcci è che, di solito, il
secondo si presenta più solido. Infatti, se cadesse una connessione (dovuta ad
esempio alla disfunzione di un nodo), ci sarebbe ancora la possibilità di distribuire le
informazioni senza la necessità di riorganizzare immediatamente l'intera rete.
Algoritmi epidemici
Si parla di algoritmi epidemici in virtù della somiglianza con i processi di diffusione
di una malattia infettiva: proprio grazie a queste analogie è possibile sfruttare i
risultati ottenuti nelle ricerche mediche.
L’algoritmo epidemico consente, infatti, di poter determinare la politica di contagio
in quanto tali tecniche di comunicazione garantiscono la propagazione di tutte le
operazioni a tutti i nodi, anche quando la topologia della rete è sconosciuta e
variabile.
Questi algoritmi offrono una maggiore scalabilità del sistema in presenza di un
grande numero di punti proprio perché è molto minore il livello di sincronizzazione.
L'obiettivo principale di questi protocolli epidemici è la rapida propagazione delle
informazioni in un grande insieme di nodi usando solo informazioni locali; in altre
parole, non esiste un componente centrale che coordina la distribuzione delle
informazioni.
Volendo usare la terminologia delle epidemie, un nodo che fa parte di un sistema
distribuito è detto “infetto” se possiede dati che si desidera diffondere su altri nodi;
un nodo che non ha ancora visto questi dati si dice “suscettibile”; infine un nodo
aggiornato che non vuole o non può più diffondere i propri dati è detto “rimosso”.
Più precisamente, i protocolli di gossip godono delle seguenti proprietà:
2
• scalabilità: le loro performance non degradano rapidamente al crescere del numero
dei processi. Generalmente ogni processo invia un numero di messaggi indipendente
dal numero di processi e predeterminato. In queste condizioni, se la stabilità della rete
fisica non degrada con il numero dei processi, il protocollo di gossip è scalabile.
• adattabilità: non è difficile aggiungere o rimuovere processi nella rete. Il problema
risiede nella configurazione dei parametri utilizzati dai protocolli che spesso sono
configurati in modo statico in base alle dimensioni previste della rete. Un aumento
imprevisto e consistente del numero di processi di un gruppo può portare, in questi
casi, ad una degradazione delle prestazioni.
Modello di diffusione: Gossiping o "Diffusione del rumore"
In questo modello di diffusione, il nodo P nel momento in cui viene aggiornato con
un determinato dato prova a contattare un casuale nodo Q e prova ad inviargli
l'aggiornamento. Tuttavia, è possibile che Q sia già stato aggiornato da un altro nodo
e in questo caso P potrà perdere l'interesse a diffondere ulteriormente l'aggiornamento
entrando a far parte dei nodi “rimossi”.
Anche qui risulta evidente l'analogia con la vita reale, in quanto il nodo sembra
simulare il comportamento umano in caso di “pettegolezzo”, raggiungendo ottime
prestazioni soprattutto nella velocità di diffusione.
Nonostante tale tecnica sia molto efficiente nella propagazione del dato, va detto però
che la diffusione non garantisce che tutti i nodi siano raggiunti dall'aggiornamento.
In tale algoritmo, i nodi sono all'inizio ignoranti rispetto all’informazione, ma una
volta ricevuta, questa è considerata “HOT” e perciò da condividere; viene scelto,
quindi, periodicamente un altro nodo a caso e si verifica che anche l'altro ne sia a
conoscenza.
Quando un host ha contattato troppi altri nodi che già conoscevano l'aggiornamento,
l’host ne cambia la connotazione HOT, mantenendolo senza più cercare di
propagarlo. Questo meccanismo viene utilizzato ogni qual volta che un nodo ottiene
un nuovo dato o da un pari o da un utente: tale dato può essere, infatti, lanciato
frequentemente non necessitando di tante risorse.
Nella nostra implementazione, un nodo che tenta di diffondere l’informazione ad un
altro nodo, già in possesso dell’informazione, viene rimosso.
3
Simulazione dell’algoritmo
Per il nostro caso si è voluto simulare la diffusione dell’informazione attraverso una
rete composta da 100 nodi (come si può vedere in figura).
Creazione matrice della rete (diversa ad ogni lancio dell’algoritmo) :
m_punti=zeros(100,5);
%%popolamento
%1 colonna= id nodo
%2 colonna= coordinata x
%3 colonna= coordinata y
%4 colonna= infetto
%5 colonna= rimosso
for k=1:Rete
m_punti(k,1)=k; % 1 colonna
m_punti(k,2)=M(k); % 2 colonna
m_punti(k,3)=M1(k); % 3 colonna
end
4
Dichiariamo una nuova matrice (100 righe x 100 colonne) per salvare le distanze
spaziali dei nodi:
RankDistanze100 = zeros(100,100);
Distanza100 = zeros(100,100);
for i=1:100
[RankDistanze100(i,:),Distanza100(i,:)] =
knnsearch(m_punti(:,2:3),m_punti(i,2:3),'k',100);
end
Ultimiamo la matrice aggiungendo 99 colonne (100 colonne-1) che rappresentano la
precedente matrice privata della prima posizione (posizione occupata rispettivamente
dal nodo dal quale si calcolano le distanze):
%ultimiamo la matrice
%1 colonna
= id nodo
%2 colonna
= coordinata x
%3 colonna
= coordinata y
%4 colonna
= infetto
%5 colonna
= rimosso
%6 a 104 colonne = rank di distanza dal 2° al 100° ( poiche' il 1° e' il nodo
stesso )
matriceRete = [m_punti,RankDistanze100(:,2:100)];
disp(matriceRete);
Identifichiamo il paziente 0 attraverso una funzione casuale che sceglie un nodo tra i
100 presenti nella rete, dopodiché settiamo il flag (booleano 0/1) nella matrice del
paziente 0 a infetto (val = 1) :
%scelta casuale del paziente zero
disp('Paziente0 =');
paziente0=randi(100,1);
disp(paziente0);
%set del flag nella colonna infetto
matriceRete(paziente0,4)=1;
Avviamo l'algoritmo e settiamo il tempo massimo a 2000 cicli (tempo nel quale
l'epidemia e' attiva). A ogni ciclo un solo nodo infetto può contagiare un suo vicino:
in questo caso è quindi chiamata una seconda funzione denominata
"EpidemicSpread", che riceve in input la matrice della rete e il nodo infettante
nell'attuale ciclo; questa funzione restituisce come output la matrice aggiornata e ad
ogni ciclo salva le statistiche sui nodi infetti e rimossi:
while ( contatore ~= tempoMax )
i=randi(100,1);
if ( (matriceRete(i,4)==1)&&(matriceRete(i,5)~=1) )
5
nodo=i;
[ matriceRete] = EpidemicSpread(nodo,matriceRete);
%pause(2);
end
switch contatore
case fix(tempoMax/3)
infetti=sum(matriceRete, 1);
IPrimoTerzo=infetti(4);
RPrimoTerzo=infetti(5);
case fix(tempoMax/3)*2
infetti=sum(matriceRete, 1);
ISecondoTerzo=infetti(4);
RSecondoTerzo=infetti(5);
case tempoMax-1
infetti=sum(matriceRete, 1);
ITerzoTerzo=infetti(4);
RTerzoTerzo=infetti(5);
end
contatore = contatore+1;
end
Nel dettaglio, la funzione "EpidemicSpread” si comporta in questo modo: il primo
controllo serve a verificare che non si vada oltre i limiti della matrice e che non sia
stata effettuata nessuna infezione/rimozione nella corrente chiamata di funzione
(quest'ultima condizione viene verificata attraverso la variabile flagEseguito).
Il secondo controllo (primo if) verifica che il nodo infettante non tenti di infettare
nuovamente un nodo che ha già preso in considerazione nel rank, cioè che ha già
infettato; quindi, in caso positivo, si effettua un ulteriore controllo per stabilire se il
nodo preso in considerazione sia infetto o rimosso.
Se tutte le precedenti condizioni danno esito positivo, il nodo corrente viene infettato
dal nodo dato in input alla funzione “EpidemicSpread”: a questo punto viene
cancellato dal rank del nodo infettato l’identificativo del nodo infettante per evitare
che nei successivi cicli si prendano in considerazione coppie di nodi vicini tra loro.
while (i~=105) && (flagEseguito==0)
%identifico il nodo piu' vicino nel rank
if(matriceRete(nodo,i)~=0)
%controllo che il nodo da infettare non sia infetto o rimosso
if (matriceRete(matriceRete(nodo,i),4)~=1) &&
(matriceRete(matriceRete(nodo,i),5)~=1)
% cambio infettato
matriceRete(matriceRete(nodo,i),4)=1;
flagEseguito=1;
X = fprintf('(msg) Il nodo[%d] infetta il nodo[%d] ! \n',
matriceRete(nodo,1),matriceRete(nodo,i));
infettatoIdNodo = matriceRete(nodo,i);
k=1;
for k=6:104
if(matriceRete(infettatoIdNodo,k)==nodo)
matriceRete(matriceRete(nodo,i),k)=0;
end
k=k+1;
6
end
matriceRete(nodo,i)=0;
Se le condizioni di non infezione e non rimozione danno esito negativo si ricade nel
seguente caso : rimozione del nodo infettante con annesso messaggio di output.
%altrimenti viene rimosso il nodo infettante
else
X = fprintf('(msg) Il nodo[%d] tenta di infettare il
nodo[%d](precedentemente infettato), quindi il nodo[%d] viene rimosso! \n',
matriceRete(nodo,1), matriceRete(nodo,i), matriceRete(nodo,1));
matriceRete(nodo,5)=1;
%assegna 0 ai nodi rimossi
for j=1:100
for k=6:104
if( matriceRete(j,k)== matriceRete(nodo,1))
matriceRete(j,k)=0;
end
end
end
flagEseguito=1;
end
end
i=i+1;
end
end
Terminata l'esecuzione della funzione "EpidemicSpread" la funzione chiamante
(principale) continua con i suoi cicli fino al termine del tempo dato in input (come
detto nel nostro caso 2000 cicli).
Disp(‘Contatore = ‘);
disp(contatore);
%Stampa a video delle percentuali di rimossi e infettati
X = fprintf(‘(msg) Infetti(1° Sezione) = %d Rimossi(1° Sezione)= %d
\n(msg)
Infetti(2° Sezione) = %d Rimossi(2° Sezione)= %d
\n(msg) Infetti(3° Sezione)
= %d Rimossi(3° Sezione)= %d
\n’,
IprimoTerzo,RprimoTerzo,IsecondoTerzo,RsecondoTerzo,IterzoTerzo,RterzoTerzo);
out =
[IprimoTerzo,IsecondoTerzo,IterzoTerzo,RprimoTerzo,RsecondoTerzo,RterzoTerzo];
end
Insieme alle due funzioni precedentemente descritte, ve ne è una terza chiamata
“Run100”, la quale richiama la funzione principale "RandomRandomNodes100" e
salva gli output su un foglio elettronico nel quale i dati vengono elaborati per
ricavare:
7
 Media Infetti (nelle 3 trance che vanno a formare il tempo massimo)
 Media Rimossi (nelle 3 trance che vanno a formare il tempo massimo)
 Picchi (min/MAX) di infezione (nelle 3 trance che vanno a formare il tempo
massimo)
 Picchi (min/MAX) di rimozione (nelle 3 trance che vanno a formare il tempo
massimo)
function [ output ] = Run100( )
output= zeros(100,6);
for i=1:100
output(i,:)=RandomRandomNodes100;
end
xlswrite('OutputEpidemici.xls', output, 'OutputFabio', 'A2');
end
Ecco un esempio:
Una seconda versione del sistema è stata successivamente creata per simulare
graficamente la diffusione epidemica.
8
Guida alla simulazione attraverso l'ambiente MATLAB
Aprendo l'ambiente andremo in primo luogo a caricare il file
RandomRandomNodes100.m
presente nella directory “Algoritmi Epidemici
ParteGrafica” il quale oltre a simulare l’algoritmo precedentemente descritto,
produrrà un output grafico grazie al quale sarà possibile seguire ad ogni passo la
diffusione
dell’informazione
nella
rete
composta
dai
100
nodi.
Per rendere visibile l’avanzamento dell’epidemia si è deciso di interrompere per una
frazione di secondo l’esecuzione del programma ogni qual volta si verifica
un’infezione.
I nodi in verde rappresentano nodi non ancora raggiunti dall’informazione (sani); i
nodi gialli rappresentano i nodi infettati e infine i nodi rossi rappresentano i nodi
rimossi.
9
10
Sarà inoltre possibile consultare tutti i passi dell’epidemia grazie alla creazione di un
output visibile in MATLAB:
Paziente0 =
75
(msg) Il nodo[75] infetta il nodo[77] !
(msg) Il nodo[77] infetta il nodo[88] !
(msg) Il nodo[88] infetta il nodo[16] !
(msg) Il nodo[16] infetta il nodo[87] !
(msg) Il nodo[88] tenta di infettare il nodo[87](precedentemente infettato),
quindi il nodo[88] viene rimosso!
(msg) Il nodo[87] tenta di infettare il nodo[75](precedentemente infettato),
quindi il nodo[87] viene rimosso!
(msg) Il nodo[16] infetta il nodo[100] !
(msg) Il nodo[16] tenta di infettare il nodo[77](precedentemente infettato),
quindi il nodo[16] viene rimosso!
(msg) Il nodo[77] infetta il nodo[81] !
(msg) Il nodo[81] infetta il nodo[94] !
:
:
:
Contatore = 2000
(msg) Infetti(1a Sezione) = 15
Rimossi(1a Sezione)= 10
(msg) Infetti(2a Sezione) = 40
Rimossi(2a Sezione)= 33
(msg) Infetti(3a Sezione) = 85
Rimossi(3a Sezione)= 74
11
Riferimenti
-“ Simple, Fast and Deterministic Gossip and Rumor Spreading “ - B.Haeupler
-“ Progetto di sistemi distribuiti multiagente – Analisi di algoritmi epidemici ” –
Nunzio Gianfelice
-“ Randomized Gossip Algorithms “ - S. Boyd, A.Ghosh, B.Prabhakar, and D.Shah
-A. Tanenbaum e M. van Steen, Sistemi Distribuiti ed. Pearson-Prentice Hall,
seconda edizione 2007.
12