SlideShare une entreprise Scribd logo
1  sur  19
Télécharger pour lire hors ligne
U NIVERSITÁ DEGLI S TUDI DI P ERUGIA
         Facoltá di Scienze Matematiche, Fisiche e Naturali


           Corso di laurea specialistica in I NFORMATICA




           Progetto di applicazione e calcolo in rete:
                        corso avanzato


                      Database
                   Data Aggregator
Relatori:                                          Professore:
Andrea Manfucci                                    Antonio Laganá
Davide Ciambelli



                       Anno Accademico 2008/2009
Indice

1 Presentazione del problema                                                                         2
  1.1 Da sqlite3 a MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     2
  1.2 I contesti di comunicazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    3
  1.3 Grana fine o grana grossa? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      4

2 Struttura del database                                                                            5

3 Ambiente di sviluppo e testing                                                                     7

4 Algoritmo sequenziale                                                                             8

5 Algoritmo parallelo                                                                               10

6 Analisi di complessità e scalabilità                                                              14

7 Valutazione e misurazione delle prestazioni                                                       15




                                                                                                    1
Capitolo 1

Presentazione del problema

Il presente lavoro ha portato alla realizzazione di un database data aggregator. In parti-
colare è stato implementato un programma parallelo che ha permesso la raccolta e l’aggre-
gazione in un’unica base di dati (che per comodità chiameremo db_master) di informazioni
disperse in vari database (che per comodità chiameremo aggregators). Il problema è stato
affrontato seguendo una strategia bottom up per cui l’implementazione finale è il risultato di
miglioramenti incrementali del codice che hanno permesso il raggiungimento dell’obiettivo.
   Tutti i database utilizzati sono stati definiti con la stessa struttura ma con nomi diversi.
Le tabelle che compongono le varie basi di dati sono del tipo:

      principale(id_operazione, protocollo, id_citta, id_stato)

      secondaria(cod_controllo, part_iva, quantita)

Per comodità i campi delle tabelle sono stati definiti con tipi di dato numerici per sfruttare
algoritmi che generassero numeri progressivi che hanno permesso di caricare ciascuna base
di dati fino ad un massimo di 18000 occorrenze.
    I dati, diversi per ogni database aggregators, sono recuperati dai singoli processi slave me-
diante operazioni di select per essere poi inseriti nel db_master. Gli unici vincoli del problema
sono le eventuali duplicazioni dei dati già presenti nel db_master che quindi vanno evitate
e l’accesso da parte dei processi dispari a porzioni di dati diverse da quelle a cui hanno ac-
cesso i processi pari e viceversa. I programmi sono stati realizzati facendo uso di derived
datatypes, due diversi contesti di comunicazione ed accesso remoto alla memoria.
    Per capire meglio il problema analizziamolo in dettaglio.


1.1    Da sqlite3 a MySQL
Innanzi tutto è stato scelto il database da utilizzare. I requisiti fondamentali dovevano essere
semplicità di gestione e facilità di utilizzo. La preferenza è quindi ricaduta sul DBMS SQ-
LITE . SQlite è una libreria software scritta in linguaggio C che implementa un DBMS SQL
incorporabile all’interno di applicazioni. Il suo creatore è D. Richard Hipp, che lo ha rilasciato
come software Open Source di pubblico dominio, privo di qualsiasi licenza. Permette di otte-
nere una base di dati (comprese tabelle, query, form, report) incorporate in un unico file, come
il modulo Access di Microsoft Office o il modulo Base di OpenOffice.org.


                                                                                                2
1.2 I contesti di comunicazione


    Essendo una libreria, non è un processo standalone utilizzabile di per sè, ma può essere
linkato all’interno di un altro programma. È utilizzabile con linguaggio C/C++ ed esiste anche
per altri linguaggi. Il pacchetto ha molte interessanti caratteristiche ma presenta anche dei
svantaggi che inizialmente non erano stati presi in considerazione come la gestione della
concorrenza (le applicazioni che lo utilizzano, se necessario, devono implementarla) e l’assenza
di una cache per le query (non esistendo un processo server centrale). Queste imperfezioni
non permettevano l’esecuzione di query parallele che causavano il bloccaggio del database
(SQLITE _ BUSY) ogni volta che venivano effettuate operazioni di lettura e scrittura concorrente
(eseguite da più processi contemporaneamente). Queste limitazioni hanno reso necessario
l’utilizzo del DBMS MySQL.
    MySQL è un database management system relazionale, composto da un client con inter-
faccia a caratteri e un server, entrambi disponibili sia per sistemi Unix come GNU/Linux che
per Windows. Dal 1996 supporta la maggior parte della sintassi SQL e si prevede in futuro il
pieno rispetto dello standard ANSI. Il codice di MySQL è di proprietà dell’omonima società,
viene però distribuito con la licenza GNU GPL oltre che con una licenza commerciale. Fino
alla versione 4.0, una buona parte del codice del client era licenziato con la GNU LGPL e
poteva dunque essere utilizzato per applicazioni commerciali. Dalla versione 4.1 in poi, anche
il codice dei client è distribuito sotto GNU GPL. Esiste peraltro una clausola estensiva che
consente l’utilizzo di MySQL con una vasta gamma di licenze libere. In MySQL una tabella
può essere di diversi tipi (o storage engine).
    Ogni tipo di tabella presenta proprietà e caratteristiche differenti (transazionale o meno,
migliori prestazioni, diverse strategie di locking, funzioni particolari, ecc). Esiste poi un’API
che si può utilizzare per creare in modo relativamente facile un nuovo tipo di tabella, che
poi si può installare senza dover ricompilare o riavviare il server. Il tipo di tabella utiliz-
zata nel programma parallelo è lo storage engine InnoDB (di tipo transazionale, sviluppato
da InnoBase Oy, società ora comprata da Oracle). InnoDB è un motore per il salvataggio di
dati per MySQL, fornito in tutte le sue distribuzioni. La sua caratteristica principale è quel-
la di supportare le transazioni di tipo ACID. ACID deriva dall’acronimo inglese Atomicity,
Consistency, Isolation, e Durability (Atomicità, Coerenza, Isolamento e Durabilità). Perché le
transazioni parallele operino in modo corretto sui dati è necessario che i meccanismi che le
implementano soddisfino le quattro proprietà citate sopra. In particolare deve essere garanti-
to l’isolamento in quanto ogni transazione deve essere eseguita in modo isolato e indipendente
dalle altre transazioni e l’eventuale fallimento di una transazione non deve interferire con le
altre transazioni in esecuzione simultaneamente.


1.2    I contesti di comunicazione
Inizialmente è stata valutata la possibilità di utilizzare due contesti di comunicazione. L’idea
era quella di formare due gruppi di processi suddivisi in base al rango pari e dispari. Avan-
zando nella progettazione però è stato ritenuto inutile suddividere i processi in due gruppi
distinti in quanto le comunicazioni che avvenivano erano essenzialmente point-to-point. In-
fatti i processi slave devono comunicare solamente con il processo master e non hanno bisogno
di scambiarsi informazioni tra di loro; inoltre non c’era la necessità di inviare collettive da
parte del master verso i due gruppi di processi (broadcast messagges). Compiere una sud-
divisione tra i processi slave avrebbe solo aumentato la complessità del programma senza
portare sostanziali miglioramenti. Alla fine quindi è stato deciso di utilizzare un solo contesto
di comunicazione.

                                                                                               3
1.3 Grana fine o grana grossa?


1.3    Grana fine o grana grossa?
La scelta della grana è stata vincolata dall’utilizzo dei database. Le basi di dati sono strut-
ture statiche quindi poco compatibili con un programma parallelo. Rendono molto difficoltoso
il mantenimento della scalabilità del programma riducendo di parecchio la dinamicità. In
principio è stata valutata la possibilità di effettuare più query in parallelo permettendo a più
processi di lavorare sulla stessa base di dati simultaneamente. L’idea in pratica era quella
di limitare (SELECT * FROM TABELLA LIMIT n,k;) il numero di occorrenze di ogni query sulla
medesima tabella in modo da garantire un buon load balancing. In SQL è possibile eseguire
query parallele ma dopo aver testato la velocità di esecuzione di una singola query contro la
velocità di esecuzione di un insieme di query sulla medesima tabella, è emerso quanto segue:

   • il costo dell’esecuzione seriale della query non è sufficientemente elevato da suggerire
     l’adozione di un piano alternativo di esecuzione parallela;

   • un piano di esecuzione seriale è considerato più veloce di ogni possibile piano di esecu-
     zione parallela per la query in esame.

Prendendo atto di quanto detto sopra è stata preferita una diversa implementazione che con-
siste nell’assegnare ad ogni processo slave un database. In questo modo si hanno tre possibili
casi:

  1. due processi slave che lavorano su sei database aggregators;

  2. quattro processi slave che lavorano su sei database aggregators;

  3. sei processi slave che lavorano su sei database aggregator.

Il tempo di esecuzione di ciascuna query è stato drasticamente diminuito e nel primo e terzo
caso il bilanciamento del carico viene mantenuto. Gli unici difetti di questa implementazione
sono la limitata scalabilità e il caso 2 che provoca una distribuzione del carico sbilanciata in
quanto, su quattro processi slave, due lavorano il doppio. Il programma quindi gira con un
minimo di tre fino ad un massimo di sette processi con il vincolo che il numero di processi
slave deve essere pari.




                                                                                              4
Capitolo 2

    Struttura del database

    Come già anticipato nel capitolo precedente, la struttura di ciascuna base di dati consiste di
    due tabelle definite in questo modo:




                                   Figura 2.1: Struttura della tabella PRINCIPALE

       Nella Figura 2.1 si può notare che il campo id_operazione è chiave primaria di tipo float. I
    restanti campi invece sono di tipo int. Tutti i campi devono essere NOT NULL.




                                  Figura 2.2: Struttura della tabella SECONDARIA

        Nella Figura 2.2 si può notare che il campo cod_controllo è chiave primaria di tipo float. I
    restanti campi invece sono di tipo int. Tutti i campi devono essere NOT NULL.
        Le tabelle non presentano nessun vincolo di integrità referenziale come si può vedere dal
    listato 2.1.


                                        Listing 2.1: Creazione della base di dati
1   CREATE TABLE p r i n c i p a l e (
2       i d _ o p e r a z i o n e f l o a t PRIMARY KEY,


                                                                                                 5
3          p r o t o c o l l o int NOT NULL,
4          i d _ c i t t a int NOT NULL,
5          i d _ s t a t o int NOT NULL
6    )
7    TYPE = InnoDB ;
8
9    CREATE TABLE secondaria (
10       c o d _ c o n t r o l l o f l o a t PRIMARY KEY,
11       p a r t _ i v a int NOT NULL,
12       quantita int NOT NULL
13   )
14   TYPE = InnoDB ;




                                                            6
Capitolo 3

Ambiente di sviluppo e testing

La parte di sviluppo del codice è stata eseguita su un cluster di workstation formato da 1
front-end e 5 nodi. Le caratteristiche tecniche del front-end sono riportate di seguito:

   • CPU AMD Athlon XP 1,8 Ghz;

   • Hard Disk da 40m GB;

   • SO Debian GNU/Linux 4.0 Etch;

   • Rete Fast Ethernet;

   • Switch 10/100 Mbps.

Queste invece sono le caratteristiche tecniche di ciascun nodo:

   • CPU Pentium II 300 Mhz;

   • Hard Disk da 40 GB;

   • SO Debian GNU/Linux 4.0 Etch;

   • Rete Fast Ethernet;

   • Switch 10/100 Mbps.

L’algoritmo è stato implementato usando la Message Passing Interface: in particolare l’imple-
mentazione di MPI usata è stata la MPICH -2. Ogni test è stato ripetuto 5 volte ed è stato preso
il valore medio dei singoli tempi come tempo di esecuzione.




                                                                                              7
Capitolo 4

     Algoritmo sequenziale

     L’algoritmo sequenziale consiste in un ciclo che scorre tutti i database aggregator e per ognuno
     effettua due query di selezione: la prima seleziona tutto il contenuto dalla tabella principale
     mentre la seconda seleziona tutto da secondaria. Ad ogni ciclo vengono anche effettuate le
     scritture nel db_master.


              Listing 4.1: Esempio di interrogazione di un aggregator e scrittura nel buffer
1    i f ( i == num_database ) {
2          conn = m y s q l _ i ni t (NULL) ;
3          i f ( ! mysql_real_connect ( conn , server , user , password , db2 , 0 , NULL, 0 ) ) {
4                  f p r i n t f ( stderr , "%sn " , mysql_error ( conn ) ) ;
5                  exit (1) ;
6          }
7          i f ( mysql_query ( conn , " s e l e c t ∗ from p r i n c i p a l e " ) ) {
8                  f p r i n t f ( stderr , "%sn " , mysql_error ( conn ) ) ;
9                  exit (1) ;
10         }
11         res = mysql_use_result ( conn ) ;
12         contatore = 0;
13         while ( ( row = mysql_fetch_row ( res ) ) != NULL) {
14                 b u f f e r [ c o n t a t o r e ] . i d _ o p e r a z i o n e = a t o f ( row [ 0 ] ) ;
15                 b u f f e r [ c o n t a t o r e ] . p r o t o c o l l o = a t o i ( row [ 1 ] ) ;
16                 b u f f e r [ c o n t a t o r e ] . i d _ c i t t a = a t o i ( row [ 2 ] ) ;
17                 b u f f e r [ c o n t a t o r e ] . i d _ s t a t o = a t o i ( row [ 3 ] ) ;
18                 c o n t a t o r e ++;
19         }
20         m y s q l _ f r e e _ r e s u l t ( res ) ;
21         i f ( mysql_query ( conn , " s e l e c t ∗ from secondaria " ) ) {
22                 f p r i n t f ( stderr , "%sn " , mysql_error ( conn ) ) ;
23                 exit (1) ;
24         }
25         res = mysql_use_result ( conn ) ;
26         contatore = 0;
27         while ( ( row = mysql_fetch_row ( res ) ) != NULL) {
28                 b u f f e r [ c o n t a t o r e ] . c o d _ c o n t r o l l o = a t o f ( row [ 0 ] ) ;
29                 b u f f e r [ c o n t a t o r e ] . p a r t _ i v a = a t o i ( row [ 1 ] ) ;
30                 b u f f e r [ c o n t a t o r e ] . quantita = a t o i ( row [ 2 ] ) ;
31                 c o n t a t o r e ++;
32         }
33         m y s q l _ f r e e _ r e s u l t ( res ) ;
34         mysql_close ( conn ) ;


                                                                                                             8
35   }




                                  Listing 4.2: Esempio di scrittura nel database db_master
1    for ( j = 0 ; j < NELEM; j ++) {
2            sprintf ( scrittura_principale ,
3    " i n s e r t i n t o p r i n c i p a l e values (%3.2 f , %d , %d ,
           %d ) " , b u f f e r [ j ] . id_operazione , b u f f e r [ j ] . p r o t o c o l l o , b u f f e r [ j ] . i d _ c i t t a ,
            buffer [ j ] . id_stato ) ;
4            mysql_query ( conn_master1 , s c r i t t u r a _ p r i n c i p a l e ) ;
5    }
6    for ( j = 0 ; j < NELEM; j ++) {
7            sprintf ( scrittura_secondaria ,
8    " i n s e r t i n t o secondaria values (%3.2 f , %d ,
           %d ) " , b u f f e r [ j ] . c o d _ c o n t r o l l o , b u f f e r [ j ] . part_iva , b u f f e r [ j ] . quantita ) ;
9            mysql_query ( conn_master1 , s c r i t t u r a _ s e c o n d a r i a ) ;
10   }




                                                                                                                                          9
Capitolo 5

    Algoritmo parallelo

    L’algoritmo parallelo si divide principalmente in due sezioni: quella del master e quella dello
    slave. All’inizio il master conosce il numero degli slave e, utilizzando una MPI_Send, in-
    via a ciascuno di essi le informazioni necessarie per effettuare l’accesso in lettura a ciascun
    aggregator.
       Per comodità è stato creato un vettore database che contiene i nomi degli aggregators che
    ancora devono essere assegnati. Tale vettore viene tenuto in continuo aggiornamento dal ma-
    ster che ha il compito di eliminare i nomi dei database ogni volta che questi vengono assegnati
    ai processi slave.
       Gli slave, che fino a quel momento erano in “ascolto” con l’ausilio della primitiva MPI_Probe,
    rispondono alla richiesta con una MPI_Recv ed iniziano il proprio lavoro. In questo modo ogni
    processo slave opera nel corrispettivo database, effettua le query, e scrive nel buffer.
       A questo punto avviene il processo di sincronizzazione. Il master crea la memory win-
    dow (MPI_Win_create) a cui gli slave da remoto fanno riferimento per inviare, tramite la
    primitiva MPI_Put, i buffer che precedentemente erano stati riempiti.
       Il master ora è in possesso di tutti i risultati delle query effettuate fino a quel momento
    dai processi slave e quindi può effettuare la prima scrittura nel db_master. Adesso il master
    deve controllare il vettore database. Se questo è vuoto significa che il contenuto di tutti gli
    aggregators è stato scritto nel db_master e in tal caso il programma termina con l’invio a
    tutti gli slave di una MPI_Send con un tag di fine lavoro. In caso contrario, il master deve
    controllare quali sono i processi slave liberi in quel momento trasmettendo loro le informazioni
    rimanenti.
       Naturalmente il tutto avviene discriminando i processi dispari da quelli pari per cui ad un
    aggregator di indice dispari avrà accesso esclusivamente un processo dispari e viceversa.


                Listing 5.1: Funzione master: prima assegnazione dei lavori agli slave
1   for ( i = 1 ; i <= numworker ; i ++) {
2       invio = i ;
3       MPI_Send(& i n v i o , 1 , MPI_INT , i , CICLO1, MPI_COMM_WORLD) ;
4       database [ i ] = 1 ;
5   }
6   MPI_Win_create(& b u f f e r , NELEM ∗ sizeof ( query ) , sizeof ( query ) , MPI_INFO_NULL,
       MPI_COMM_WORLD, &f i n e s t r a ) ;
7   MPI_Win_fence ( 0 , f i n e s t r a ) ;
8   //


                                                                                                  10
9    //
10   MPI_Win_fence ( 0 , f i n e s t r a ) ;
11   MPI_Win_free(& f i n e s t r a ) ;




                 Listing 5.2: Funzione master: assegnazione dei lavori successivi agli slave
1    MPI_Recv (NULL, 0 , MPI_INT , MPI_ANY_SOURCE, CICLO2, MPI_COMM_WORLD, &s t a t u s ) ;
2    terminato = s t a t u s .MPI_SOURCE;
3    v e t t o r e [ terminato ] = 1 ;
4    i f ( ( terminato % 2 ) == 1 ) {
5            k = 1;
6            for ( k = 1 ; k <= DATABASE; k++) {
7                    i f ( database [ k ] == 0 && ( k % 2 ) == 1 ) {
8                          invio = k ;
9                          MPI_Send(& i n v i o , 1 , MPI_INT , terminato , CICLO1, MPI_COMM_WORLD) ;
10                         database [ k ] = 1 ;
11                         break ;
12                   }
13           }
14   }
15   i f ( ( terminato % 2 ) == 0 ) {
16           k = 1;
17           for ( k = 1 ; k <= DATABASE; k++) {
18                   i f ( database [ k ] == 0 && ( k % 2 ) == 0 ) {
19                         invio = k ;
20                         MPI_Send(& i n v i o , 1 , MPI_INT , terminato , CICLO1, MPI_COMM_WORLD) ;
21                         database [ k ] = 1 ;
22                         break ;
23                   }
24           }
25   }




                                                Listing 5.3: La funzione slave
1    for ( ; ; ) {
2        disp = ( rank−1)∗NELEM;
3        MPI_Probe ( 0 ,MPI_ANY_TAG,MPI_COMM_WORLD s t a t u s ) ;  ,&
4        i f ( s t a t u s .MPI_TAG==CICLO1) {
5               MPI_Recv(& i n v i o , 1 , MPI_INT , source , CICLO1,MPI_COMM_WORLD s t a t u s ) ;
                                                                                   ,&
6               s p r i n t f ( pippo , " db_slave_%d " , i n v i o ) ;
7               char ∗db=pippo ;
8
9               //******** Lavoro database *********//
10
11              conn=m y s q l _ i ni t (NULL) ;
12
13              /* Connect to database */
14
15              i f ( ! mysql_real_connect ( conn , server , user , password , db , 0 ,NULL, 0 ) ) {
16                    f p r i n t f ( stderr , "%sn" , mysql_error ( conn ) ) ;
17                    exit (1) ;
18              }
19
20              /* send SQL query */
21
22               i f ( mysql_query ( conn , " s e l e c t ∗ from p r i n c i p a l e " ) ) {


                                                                                                        11
23                  f p r i n t f ( stderr , "%sn" , mysql_error ( conn ) ) ;
24                  exit (1) ;
25           }
26           res = mysql_use_result ( conn ) ;
27           k = 0;
28           while ( ( row = mysql_fetch_row ( res ) ) != NULL) {
29                 b u f f e r [ k ] . i d _ o p e r a z i o n e = a t o f ( row [ 0 ] ) ;
30                 b u f f e r [ k ] . p r o t o c o l l o = a t o i ( row [ 1 ] ) ;
31                 b u f f e r [ k ] . i d _ c i t t a = a t o i ( row [ 2 ] ) ;
32                 b u f f e r [ k ] . i d _ s t a t o = a t o i ( row [ 3 ] ) ;
33                 k++;
34           }
35           m y s q l _ f r e e _ r e s u l t ( res ) ;
36
37           /* send SQL query */
38
39           i f ( mysql_query ( conn , " s e l e c t ∗ from secondaria " ) ) {
40                 f p r i n t f ( stderr , "%sn" , mysql_error ( conn ) ) ;
41                 exit (1) ;
42           }
43           res = mysql_use_result ( conn ) ;
44           k = 0;
45           while ( ( row = mysql_fetch_row ( res ) ) != NULL) {
46                 b u f f e r [ k ] . c o d _ c o n t r o l l o = a t o f ( row [ 0 ] ) ;
47                 b u f f e r [ k ] . p a r t _ i v a = a t o i ( row [ 1 ] ) ;
48                 b u f f e r [ k ] . quantita = a t o i ( row [ 2 ] ) ;
49                 k++;
50           }
51
52           /* close connection */
53
54           m y s q l _ f r e e _ r e s u l t ( res ) ;
55           mysql_close ( conn ) ;
56           MPI_Type_struct ( 2 , blockcounts , o f f s e t , oldtypes ,&MY_PART) ;
57           MPI_Type_commit(&MY_PART) ;
58           MPI_Win_create (MPI_BOTTOM, 0 , 1 ,MPI_INFO_NULL,MPI_COMM_WORLD f i n e s t r a ) ;
                                                                                          ,&
59           MPI_Win_fence ( 0 , f i n e s t r a ) ;
60           MPI_Put(& b u f f e r ,NELEM,MY_PART, 0 , disp ,NELEM,MY_PART, f i n e s t r a ) ;
61           MPI_Win_fence ( 0 , f i n e s t r a ) ;
62           MPI_Win_free(& f i n e s t r a ) ;
63           MPI_Type_free(&MY_PART) ;
64           MPI_Send (NULL, 0 , MPI_INT, 0 , CICLO2,MPI_COMM_WORLD) ;
65           }
66           else i f ( s t a t u s .MPI_TAG == CICLO3) {
67                 MPI_Recv (NULL, 0 , MPI_INT , source , CICLO3,MPI_COMM_WORLD s t a t u s ) ;
                                                                                      ,&
68                 MPI_Win_create (MPI_BOTTOM, 0 , 1 ,MPI_INFO_NULL,MPI_COMM_WORLD f i n e s t r a ) ;
                                                                                                ,&
69                 MPI_Win_fence ( 0 , f i n e s t r a ) ;
70                 MPI_Win_fence ( 0 , f i n e s t r a ) ;
71                 MPI_Win_free(& f i n e s t r a ) ;
72           }
73           else i f ( s t a t u s .MPI_TAG == FINITO ) {
74                 p r i n t f ( "FINEn" ) ;
75                 break ;
76           }
77       }

     La struttura che abbiamo utilizzato per il buffer prevede sette campi che coincidono con quelli



                                                                                                         12
delle due tabelle del database.


                                  Listing 5.4: Struct query e derived datatype
1    //-----Define struct-----//
2
3    typedef struct {
4        float id_operazione ;
5        float cod_controllo ;
6        int p r o t o c o l l o ;
7        int i d _ c i t t a ;
8        int i d _ s t a t o ;
9        int p a r t _ i v a ;
10       int quantita ;
11   } query ;
12
13   //-----Derived datatype-----//
14
15   MPI_Datatype o l d t y p e s [ 2 ] = { MPI_FLOAT, MPI_INT } ;
16   int blockcounts [ 2 ] = { 2 , 5 } ;
17   MPI_Aint o f f s e t [ 2 ] = { 0 , 2 ∗ sizeof ( f l o a t ) } ;
18   MPI_Datatype MY_PART;




                                                                                 13
Capitolo 6

Analisi di complessità e scalabilità

La complessità temporale dell’algoritmo varia in relazione alla dimensione dell’input. Infatti
all’aumentare delle occorrenze nelle tabelle dei vari aggregators aumenta il tempo di esecu-
zione delle varie query. Come è già stato detto in precedenza si è scelto di effettuare una
query per ogni aggregator invece di effettuare query parallele per non incorrere in una dila-
tazione ancora maggiore dei tempi. Le prove e gli studi effettuati sul tempo di esecuzione di
varie query hanno permesso di stabilire che la complessità temporale dell’algoritmo dipende
fortemente dal tempo effettivo di esecuzione di una query SQL.
    Il tempo delle query è lineare ed aumenta in base al numero di occorrenze. È naturale
quindi che il tempo di esecuzione del programma deriva dal tempo totale per leggere tutte le
occorrenze dei vari aggregators sommato al tempo che occorre al master per scrivere i risultati
nel db_master. Questo è riconducibile al problema di cercare un elemento all’interno di una
lista non ordinata. Tale problema ha una complessità pari ad O (n).
    Per quanto riguarda la scalabilità il programma è da considerarsi “parzialmente” scalabile
(scalabilità di carico) in quanto l’implementazione è vincolata dal numero di database. Infatti
le basi di dati sono strutture statiche e devono essere già presenti nel cluster al momento
del lancio del programma. Tali strutture non possono essere costruite a run-time e perciò
limitano la scalabilità e modificano le strategie di implementazione del codice.




                                                                                            14
Capitolo 7

Valutazione e misurazione delle
prestazioni

Sono stati eseguiti diversi test con valori variabili di carico dei database in modo da osservare
l’impatto delle dimensioni sulle performance; i test sono stati ripetuti per tre dimensioni di
carico: 36000 occorrenze (6000 per ogni aggregator), 72000 occorrenze (12000 per ogni aggre-
gator) e 108000 occorrenze (18000 per ogni aggregator). La tabella 7.1 riporta i valori osservati
per le tre dimensioni:

                       Tabella 7.1: Valori osservati nelle diverse prove
                        Occorrenze Processori        Tp      Sp     Ep
                         36000           seriale     80,2     1      1
                         36000              3        58,4   1,37   0,46
                         36000              5        57,6   1,39   0,28
                         36000              7        56,6   1,42   0,18
                         72000           seriale    156,4     1     1
                         72000              3       113,2   1,38   0,46
                         72000              5        112     1,4   0,28
                         72000              6       108,8   1,44   0,21
                         108000          seriale    234,6     1     1
                         108000             3       167,6    1,4   0,47
                         108000             5       164,8   1,42   0,28
                         108000             7       161,2   1,46   0,21

   Le figure 7.1, 7.2 e 7.3 invece mostrano i grafici relativi ai dati osservati per le diverse
dimensioni del problema testate. Dal grafico 7.2 si evince che più sono piccole le dimensioni del
database e maggiore sarà l’overhead. Non avendo a disposizione un algoritmo sequenziale è
stato calcolato lo speedup relativo eseguendo il programma parallelo con un solo processore.




                                                                                              15
Figura 7.1: Grafico del tempo relativo alle tre prove




Figura 7.2: Grafico dello speedup relativo alle tre prove


                                                           16
Figura 7.3: Grafico dell’efficienza relativo alle tre prove




                                                            17
Bibliografia

[1] http://it.wikipedia.org/.

[2] www-it.mysql.com/.

[3] L. Pacifici, Dispense del corso di Applicazione e Calcolo in Rete - Corso Avanzato.
    Corso di laurea specialistica in Informatica, Università degli studi di Perugia, Italia.




                                                                                               18

Contenu connexe

Similaire à Database Data Aggregator

Tesina di fine seminario sas ed sql
Tesina di fine seminario sas ed sqlTesina di fine seminario sas ed sql
Tesina di fine seminario sas ed sqlMarco D'Alessandro
 
OCP-Architettura e caratteristiche della PaaS
OCP-Architettura e caratteristiche della PaaSOCP-Architettura e caratteristiche della PaaS
OCP-Architettura e caratteristiche della PaaSopencityplatform
 
MySQL Day Milano 2017 - Dalla replica a InnoDB Cluster: l’HA secondo MySQL
MySQL Day Milano 2017 - Dalla replica a InnoDB Cluster: l’HA secondo MySQLMySQL Day Milano 2017 - Dalla replica a InnoDB Cluster: l’HA secondo MySQL
MySQL Day Milano 2017 - Dalla replica a InnoDB Cluster: l’HA secondo MySQLPar-Tec S.p.A.
 
Quanto mi costa SQL Pool Serverless Synapse
Quanto mi costa SQL Pool Serverless SynapseQuanto mi costa SQL Pool Serverless Synapse
Quanto mi costa SQL Pool Serverless SynapseMarco Pozzan
 
e-SUAP - General software architecture (Italiano)
e-SUAP - General software architecture (Italiano)e-SUAP - General software architecture (Italiano)
e-SUAP - General software architecture (Italiano)Sabino Labarile
 
Microservices architecture & Service Fabric
Microservices architecture & Service FabricMicroservices architecture & Service Fabric
Microservices architecture & Service FabricMassimo Bonanni
 
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...DavideFegez
 
MySQL Tech Tour 2015 - Soluzioni di alta disponibilità con MySQL
MySQL Tech Tour 2015 - Soluzioni di alta disponibilità con MySQLMySQL Tech Tour 2015 - Soluzioni di alta disponibilità con MySQL
MySQL Tech Tour 2015 - Soluzioni di alta disponibilità con MySQLPar-Tec S.p.A.
 
Summary of “The Case for Writing Network Drivers in High-Level Programming La...
Summary of “The Case for Writing Network Drivers in High-Level Programming La...Summary of “The Case for Writing Network Drivers in High-Level Programming La...
Summary of “The Case for Writing Network Drivers in High-Level Programming La...LeonardoIurada
 
Babel presenta: Opsview
Babel presenta: OpsviewBabel presenta: Opsview
Babel presenta: OpsviewBabel
 
DbUp - A real case of database migration
DbUp - A real case of database migrationDbUp - A real case of database migration
DbUp - A real case of database migrationAndrea Cirioni
 
Digital 1nn0vation saturday pn 2019 - Azure Machine Learning Service
Digital 1nn0vation saturday pn 2019 - Azure Machine Learning ServiceDigital 1nn0vation saturday pn 2019 - Azure Machine Learning Service
Digital 1nn0vation saturday pn 2019 - Azure Machine Learning ServiceMarco Zamana
 
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQLMigrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQLFabio Ferroni
 
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQLMigrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQLFabio Ferroni
 

Similaire à Database Data Aggregator (20)

Tesina di fine seminario sas ed sql
Tesina di fine seminario sas ed sqlTesina di fine seminario sas ed sql
Tesina di fine seminario sas ed sql
 
OCP-Architettura e caratteristiche della PaaS
OCP-Architettura e caratteristiche della PaaSOCP-Architettura e caratteristiche della PaaS
OCP-Architettura e caratteristiche della PaaS
 
MySQL Day Milano 2017 - Dalla replica a InnoDB Cluster: l’HA secondo MySQL
MySQL Day Milano 2017 - Dalla replica a InnoDB Cluster: l’HA secondo MySQLMySQL Day Milano 2017 - Dalla replica a InnoDB Cluster: l’HA secondo MySQL
MySQL Day Milano 2017 - Dalla replica a InnoDB Cluster: l’HA secondo MySQL
 
OCP Paas_ultima
OCP Paas_ultimaOCP Paas_ultima
OCP Paas_ultima
 
Quanto mi costa SQL Pool Serverless Synapse
Quanto mi costa SQL Pool Serverless SynapseQuanto mi costa SQL Pool Serverless Synapse
Quanto mi costa SQL Pool Serverless Synapse
 
e-SUAP - General software architecture (Italiano)
e-SUAP - General software architecture (Italiano)e-SUAP - General software architecture (Italiano)
e-SUAP - General software architecture (Italiano)
 
Microservices architecture & Service Fabric
Microservices architecture & Service FabricMicroservices architecture & Service Fabric
Microservices architecture & Service Fabric
 
Microservices
MicroservicesMicroservices
Microservices
 
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...
Utilizzo di tecnologie big data per addestramento di metamodelli matematici p...
 
MySQL Tech Tour 2015 - Soluzioni di alta disponibilità con MySQL
MySQL Tech Tour 2015 - Soluzioni di alta disponibilità con MySQLMySQL Tech Tour 2015 - Soluzioni di alta disponibilità con MySQL
MySQL Tech Tour 2015 - Soluzioni di alta disponibilità con MySQL
 
Summary of “The Case for Writing Network Drivers in High-Level Programming La...
Summary of “The Case for Writing Network Drivers in High-Level Programming La...Summary of “The Case for Writing Network Drivers in High-Level Programming La...
Summary of “The Case for Writing Network Drivers in High-Level Programming La...
 
Babel presenta: Opsview
Babel presenta: OpsviewBabel presenta: Opsview
Babel presenta: Opsview
 
DbUp - A real case of database migration
DbUp - A real case of database migrationDbUp - A real case of database migration
DbUp - A real case of database migration
 
Google File System - GFS
Google File System - GFSGoogle File System - GFS
Google File System - GFS
 
The Google File System
The Google File SystemThe Google File System
The Google File System
 
Digital 1nn0vation saturday pn 2019 - Azure Machine Learning Service
Digital 1nn0vation saturday pn 2019 - Azure Machine Learning ServiceDigital 1nn0vation saturday pn 2019 - Azure Machine Learning Service
Digital 1nn0vation saturday pn 2019 - Azure Machine Learning Service
 
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQLMigrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
 
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQLMigrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
Migrazione di basi di dati dall’ambiente MS-Access all’ambiente MS SQL
 
Appunti di big data
Appunti di big dataAppunti di big data
Appunti di big data
 
TesiEtta
TesiEttaTesiEtta
TesiEtta
 

Plus de Davide Ciambelli

SEMrush SEO Fundamentals Exam
SEMrush SEO Fundamentals ExamSEMrush SEO Fundamentals Exam
SEMrush SEO Fundamentals ExamDavide Ciambelli
 
Google Analytics for Beginners
Google Analytics for BeginnersGoogle Analytics for Beginners
Google Analytics for BeginnersDavide Ciambelli
 
Advanced Google Analytics
Advanced Google Analytics Advanced Google Analytics
Advanced Google Analytics Davide Ciambelli
 
Ecommerce Analytics: From Data to Decision
Ecommerce Analytics: From Data to DecisionEcommerce Analytics: From Data to Decision
Ecommerce Analytics: From Data to DecisionDavide Ciambelli
 
Google Tag Manager Fundamentals
Google Tag Manager Fundamentals Google Tag Manager Fundamentals
Google Tag Manager Fundamentals Davide Ciambelli
 
Abilitazione all'utilizzo dei dispositivi DAE
Abilitazione all'utilizzo dei dispositivi DAEAbilitazione all'utilizzo dei dispositivi DAE
Abilitazione all'utilizzo dei dispositivi DAEDavide Ciambelli
 
Google Tag Manager Fundamentals
Google Tag Manager FundamentalsGoogle Tag Manager Fundamentals
Google Tag Manager FundamentalsDavide Ciambelli
 
Un viaggio chiamato LibreUmbria
Un viaggio chiamato LibreUmbriaUn viaggio chiamato LibreUmbria
Un viaggio chiamato LibreUmbriaDavide Ciambelli
 
Guida introduttiva di Google all’ottimizzazione per motori di ricerca (SEO)
Guida introduttiva di Google  all’ottimizzazione per motori di ricerca (SEO)Guida introduttiva di Google  all’ottimizzazione per motori di ricerca (SEO)
Guida introduttiva di Google all’ottimizzazione per motori di ricerca (SEO)Davide Ciambelli
 
Google analytics platform principles certificate
Google analytics platform principles certificateGoogle analytics platform principles certificate
Google analytics platform principles certificateDavide Ciambelli
 
Social Network Analysis for Journalists Using the Twitter API
Social Network Analysis for Journalists Using the Twitter APISocial Network Analysis for Journalists Using the Twitter API
Social Network Analysis for Journalists Using the Twitter APIDavide Ciambelli
 
Dharma Initiative pass card
Dharma Initiative pass cardDharma Initiative pass card
Dharma Initiative pass cardDavide Ciambelli
 
Qnap turbo nas hardware manual
Qnap turbo nas hardware manualQnap turbo nas hardware manual
Qnap turbo nas hardware manualDavide Ciambelli
 
Z750 manuale di assemblaggio
Z750 manuale di assemblaggioZ750 manuale di assemblaggio
Z750 manuale di assemblaggioDavide Ciambelli
 
The 2009 Simulated Car Racing Championship
The 2009 Simulated Car Racing ChampionshipThe 2009 Simulated Car Racing Championship
The 2009 Simulated Car Racing ChampionshipDavide Ciambelli
 

Plus de Davide Ciambelli (20)

SEMrush SEO Toolkit Exam
SEMrush SEO Toolkit ExamSEMrush SEO Toolkit Exam
SEMrush SEO Toolkit Exam
 
SEMrush SEO Fundamentals Exam
SEMrush SEO Fundamentals ExamSEMrush SEO Fundamentals Exam
SEMrush SEO Fundamentals Exam
 
Google Analytics for Beginners
Google Analytics for BeginnersGoogle Analytics for Beginners
Google Analytics for Beginners
 
Advanced Google Analytics
Advanced Google Analytics Advanced Google Analytics
Advanced Google Analytics
 
Ecommerce Analytics: From Data to Decision
Ecommerce Analytics: From Data to DecisionEcommerce Analytics: From Data to Decision
Ecommerce Analytics: From Data to Decision
 
Google Tag Manager Fundamentals
Google Tag Manager Fundamentals Google Tag Manager Fundamentals
Google Tag Manager Fundamentals
 
Eccellenze in digitale
Eccellenze in digitaleEccellenze in digitale
Eccellenze in digitale
 
Abilitazione all'utilizzo dei dispositivi DAE
Abilitazione all'utilizzo dei dispositivi DAEAbilitazione all'utilizzo dei dispositivi DAE
Abilitazione all'utilizzo dei dispositivi DAE
 
Google Tag Manager Fundamentals
Google Tag Manager FundamentalsGoogle Tag Manager Fundamentals
Google Tag Manager Fundamentals
 
Certificazione AdWords
Certificazione AdWordsCertificazione AdWords
Certificazione AdWords
 
Un viaggio chiamato LibreUmbria
Un viaggio chiamato LibreUmbriaUn viaggio chiamato LibreUmbria
Un viaggio chiamato LibreUmbria
 
Guida introduttiva di Google all’ottimizzazione per motori di ricerca (SEO)
Guida introduttiva di Google  all’ottimizzazione per motori di ricerca (SEO)Guida introduttiva di Google  all’ottimizzazione per motori di ricerca (SEO)
Guida introduttiva di Google all’ottimizzazione per motori di ricerca (SEO)
 
Il codice da lopins
Il codice da lopinsIl codice da lopins
Il codice da lopins
 
Google analytics platform principles certificate
Google analytics platform principles certificateGoogle analytics platform principles certificate
Google analytics platform principles certificate
 
Social Network Analysis for Journalists Using the Twitter API
Social Network Analysis for Journalists Using the Twitter APISocial Network Analysis for Journalists Using the Twitter API
Social Network Analysis for Journalists Using the Twitter API
 
Dharma Initiative pass card
Dharma Initiative pass cardDharma Initiative pass card
Dharma Initiative pass card
 
Dossier Dharma Initiative
Dossier Dharma InitiativeDossier Dharma Initiative
Dossier Dharma Initiative
 
Qnap turbo nas hardware manual
Qnap turbo nas hardware manualQnap turbo nas hardware manual
Qnap turbo nas hardware manual
 
Z750 manuale di assemblaggio
Z750 manuale di assemblaggioZ750 manuale di assemblaggio
Z750 manuale di assemblaggio
 
The 2009 Simulated Car Racing Championship
The 2009 Simulated Car Racing ChampionshipThe 2009 Simulated Car Racing Championship
The 2009 Simulated Car Racing Championship
 

Database Data Aggregator

  • 1. U NIVERSITÁ DEGLI S TUDI DI P ERUGIA Facoltá di Scienze Matematiche, Fisiche e Naturali Corso di laurea specialistica in I NFORMATICA Progetto di applicazione e calcolo in rete: corso avanzato Database Data Aggregator Relatori: Professore: Andrea Manfucci Antonio Laganá Davide Ciambelli Anno Accademico 2008/2009
  • 2. Indice 1 Presentazione del problema 2 1.1 Da sqlite3 a MySQL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 I contesti di comunicazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 1.3 Grana fine o grana grossa? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 2 Struttura del database 5 3 Ambiente di sviluppo e testing 7 4 Algoritmo sequenziale 8 5 Algoritmo parallelo 10 6 Analisi di complessità e scalabilità 14 7 Valutazione e misurazione delle prestazioni 15 1
  • 3. Capitolo 1 Presentazione del problema Il presente lavoro ha portato alla realizzazione di un database data aggregator. In parti- colare è stato implementato un programma parallelo che ha permesso la raccolta e l’aggre- gazione in un’unica base di dati (che per comodità chiameremo db_master) di informazioni disperse in vari database (che per comodità chiameremo aggregators). Il problema è stato affrontato seguendo una strategia bottom up per cui l’implementazione finale è il risultato di miglioramenti incrementali del codice che hanno permesso il raggiungimento dell’obiettivo. Tutti i database utilizzati sono stati definiti con la stessa struttura ma con nomi diversi. Le tabelle che compongono le varie basi di dati sono del tipo: principale(id_operazione, protocollo, id_citta, id_stato) secondaria(cod_controllo, part_iva, quantita) Per comodità i campi delle tabelle sono stati definiti con tipi di dato numerici per sfruttare algoritmi che generassero numeri progressivi che hanno permesso di caricare ciascuna base di dati fino ad un massimo di 18000 occorrenze. I dati, diversi per ogni database aggregators, sono recuperati dai singoli processi slave me- diante operazioni di select per essere poi inseriti nel db_master. Gli unici vincoli del problema sono le eventuali duplicazioni dei dati già presenti nel db_master che quindi vanno evitate e l’accesso da parte dei processi dispari a porzioni di dati diverse da quelle a cui hanno ac- cesso i processi pari e viceversa. I programmi sono stati realizzati facendo uso di derived datatypes, due diversi contesti di comunicazione ed accesso remoto alla memoria. Per capire meglio il problema analizziamolo in dettaglio. 1.1 Da sqlite3 a MySQL Innanzi tutto è stato scelto il database da utilizzare. I requisiti fondamentali dovevano essere semplicità di gestione e facilità di utilizzo. La preferenza è quindi ricaduta sul DBMS SQ- LITE . SQlite è una libreria software scritta in linguaggio C che implementa un DBMS SQL incorporabile all’interno di applicazioni. Il suo creatore è D. Richard Hipp, che lo ha rilasciato come software Open Source di pubblico dominio, privo di qualsiasi licenza. Permette di otte- nere una base di dati (comprese tabelle, query, form, report) incorporate in un unico file, come il modulo Access di Microsoft Office o il modulo Base di OpenOffice.org. 2
  • 4. 1.2 I contesti di comunicazione Essendo una libreria, non è un processo standalone utilizzabile di per sè, ma può essere linkato all’interno di un altro programma. È utilizzabile con linguaggio C/C++ ed esiste anche per altri linguaggi. Il pacchetto ha molte interessanti caratteristiche ma presenta anche dei svantaggi che inizialmente non erano stati presi in considerazione come la gestione della concorrenza (le applicazioni che lo utilizzano, se necessario, devono implementarla) e l’assenza di una cache per le query (non esistendo un processo server centrale). Queste imperfezioni non permettevano l’esecuzione di query parallele che causavano il bloccaggio del database (SQLITE _ BUSY) ogni volta che venivano effettuate operazioni di lettura e scrittura concorrente (eseguite da più processi contemporaneamente). Queste limitazioni hanno reso necessario l’utilizzo del DBMS MySQL. MySQL è un database management system relazionale, composto da un client con inter- faccia a caratteri e un server, entrambi disponibili sia per sistemi Unix come GNU/Linux che per Windows. Dal 1996 supporta la maggior parte della sintassi SQL e si prevede in futuro il pieno rispetto dello standard ANSI. Il codice di MySQL è di proprietà dell’omonima società, viene però distribuito con la licenza GNU GPL oltre che con una licenza commerciale. Fino alla versione 4.0, una buona parte del codice del client era licenziato con la GNU LGPL e poteva dunque essere utilizzato per applicazioni commerciali. Dalla versione 4.1 in poi, anche il codice dei client è distribuito sotto GNU GPL. Esiste peraltro una clausola estensiva che consente l’utilizzo di MySQL con una vasta gamma di licenze libere. In MySQL una tabella può essere di diversi tipi (o storage engine). Ogni tipo di tabella presenta proprietà e caratteristiche differenti (transazionale o meno, migliori prestazioni, diverse strategie di locking, funzioni particolari, ecc). Esiste poi un’API che si può utilizzare per creare in modo relativamente facile un nuovo tipo di tabella, che poi si può installare senza dover ricompilare o riavviare il server. Il tipo di tabella utiliz- zata nel programma parallelo è lo storage engine InnoDB (di tipo transazionale, sviluppato da InnoBase Oy, società ora comprata da Oracle). InnoDB è un motore per il salvataggio di dati per MySQL, fornito in tutte le sue distribuzioni. La sua caratteristica principale è quel- la di supportare le transazioni di tipo ACID. ACID deriva dall’acronimo inglese Atomicity, Consistency, Isolation, e Durability (Atomicità, Coerenza, Isolamento e Durabilità). Perché le transazioni parallele operino in modo corretto sui dati è necessario che i meccanismi che le implementano soddisfino le quattro proprietà citate sopra. In particolare deve essere garanti- to l’isolamento in quanto ogni transazione deve essere eseguita in modo isolato e indipendente dalle altre transazioni e l’eventuale fallimento di una transazione non deve interferire con le altre transazioni in esecuzione simultaneamente. 1.2 I contesti di comunicazione Inizialmente è stata valutata la possibilità di utilizzare due contesti di comunicazione. L’idea era quella di formare due gruppi di processi suddivisi in base al rango pari e dispari. Avan- zando nella progettazione però è stato ritenuto inutile suddividere i processi in due gruppi distinti in quanto le comunicazioni che avvenivano erano essenzialmente point-to-point. In- fatti i processi slave devono comunicare solamente con il processo master e non hanno bisogno di scambiarsi informazioni tra di loro; inoltre non c’era la necessità di inviare collettive da parte del master verso i due gruppi di processi (broadcast messagges). Compiere una sud- divisione tra i processi slave avrebbe solo aumentato la complessità del programma senza portare sostanziali miglioramenti. Alla fine quindi è stato deciso di utilizzare un solo contesto di comunicazione. 3
  • 5. 1.3 Grana fine o grana grossa? 1.3 Grana fine o grana grossa? La scelta della grana è stata vincolata dall’utilizzo dei database. Le basi di dati sono strut- ture statiche quindi poco compatibili con un programma parallelo. Rendono molto difficoltoso il mantenimento della scalabilità del programma riducendo di parecchio la dinamicità. In principio è stata valutata la possibilità di effettuare più query in parallelo permettendo a più processi di lavorare sulla stessa base di dati simultaneamente. L’idea in pratica era quella di limitare (SELECT * FROM TABELLA LIMIT n,k;) il numero di occorrenze di ogni query sulla medesima tabella in modo da garantire un buon load balancing. In SQL è possibile eseguire query parallele ma dopo aver testato la velocità di esecuzione di una singola query contro la velocità di esecuzione di un insieme di query sulla medesima tabella, è emerso quanto segue: • il costo dell’esecuzione seriale della query non è sufficientemente elevato da suggerire l’adozione di un piano alternativo di esecuzione parallela; • un piano di esecuzione seriale è considerato più veloce di ogni possibile piano di esecu- zione parallela per la query in esame. Prendendo atto di quanto detto sopra è stata preferita una diversa implementazione che con- siste nell’assegnare ad ogni processo slave un database. In questo modo si hanno tre possibili casi: 1. due processi slave che lavorano su sei database aggregators; 2. quattro processi slave che lavorano su sei database aggregators; 3. sei processi slave che lavorano su sei database aggregator. Il tempo di esecuzione di ciascuna query è stato drasticamente diminuito e nel primo e terzo caso il bilanciamento del carico viene mantenuto. Gli unici difetti di questa implementazione sono la limitata scalabilità e il caso 2 che provoca una distribuzione del carico sbilanciata in quanto, su quattro processi slave, due lavorano il doppio. Il programma quindi gira con un minimo di tre fino ad un massimo di sette processi con il vincolo che il numero di processi slave deve essere pari. 4
  • 6. Capitolo 2 Struttura del database Come già anticipato nel capitolo precedente, la struttura di ciascuna base di dati consiste di due tabelle definite in questo modo: Figura 2.1: Struttura della tabella PRINCIPALE Nella Figura 2.1 si può notare che il campo id_operazione è chiave primaria di tipo float. I restanti campi invece sono di tipo int. Tutti i campi devono essere NOT NULL. Figura 2.2: Struttura della tabella SECONDARIA Nella Figura 2.2 si può notare che il campo cod_controllo è chiave primaria di tipo float. I restanti campi invece sono di tipo int. Tutti i campi devono essere NOT NULL. Le tabelle non presentano nessun vincolo di integrità referenziale come si può vedere dal listato 2.1. Listing 2.1: Creazione della base di dati 1 CREATE TABLE p r i n c i p a l e ( 2 i d _ o p e r a z i o n e f l o a t PRIMARY KEY, 5
  • 7. 3 p r o t o c o l l o int NOT NULL, 4 i d _ c i t t a int NOT NULL, 5 i d _ s t a t o int NOT NULL 6 ) 7 TYPE = InnoDB ; 8 9 CREATE TABLE secondaria ( 10 c o d _ c o n t r o l l o f l o a t PRIMARY KEY, 11 p a r t _ i v a int NOT NULL, 12 quantita int NOT NULL 13 ) 14 TYPE = InnoDB ; 6
  • 8. Capitolo 3 Ambiente di sviluppo e testing La parte di sviluppo del codice è stata eseguita su un cluster di workstation formato da 1 front-end e 5 nodi. Le caratteristiche tecniche del front-end sono riportate di seguito: • CPU AMD Athlon XP 1,8 Ghz; • Hard Disk da 40m GB; • SO Debian GNU/Linux 4.0 Etch; • Rete Fast Ethernet; • Switch 10/100 Mbps. Queste invece sono le caratteristiche tecniche di ciascun nodo: • CPU Pentium II 300 Mhz; • Hard Disk da 40 GB; • SO Debian GNU/Linux 4.0 Etch; • Rete Fast Ethernet; • Switch 10/100 Mbps. L’algoritmo è stato implementato usando la Message Passing Interface: in particolare l’imple- mentazione di MPI usata è stata la MPICH -2. Ogni test è stato ripetuto 5 volte ed è stato preso il valore medio dei singoli tempi come tempo di esecuzione. 7
  • 9. Capitolo 4 Algoritmo sequenziale L’algoritmo sequenziale consiste in un ciclo che scorre tutti i database aggregator e per ognuno effettua due query di selezione: la prima seleziona tutto il contenuto dalla tabella principale mentre la seconda seleziona tutto da secondaria. Ad ogni ciclo vengono anche effettuate le scritture nel db_master. Listing 4.1: Esempio di interrogazione di un aggregator e scrittura nel buffer 1 i f ( i == num_database ) { 2 conn = m y s q l _ i ni t (NULL) ; 3 i f ( ! mysql_real_connect ( conn , server , user , password , db2 , 0 , NULL, 0 ) ) { 4 f p r i n t f ( stderr , "%sn " , mysql_error ( conn ) ) ; 5 exit (1) ; 6 } 7 i f ( mysql_query ( conn , " s e l e c t ∗ from p r i n c i p a l e " ) ) { 8 f p r i n t f ( stderr , "%sn " , mysql_error ( conn ) ) ; 9 exit (1) ; 10 } 11 res = mysql_use_result ( conn ) ; 12 contatore = 0; 13 while ( ( row = mysql_fetch_row ( res ) ) != NULL) { 14 b u f f e r [ c o n t a t o r e ] . i d _ o p e r a z i o n e = a t o f ( row [ 0 ] ) ; 15 b u f f e r [ c o n t a t o r e ] . p r o t o c o l l o = a t o i ( row [ 1 ] ) ; 16 b u f f e r [ c o n t a t o r e ] . i d _ c i t t a = a t o i ( row [ 2 ] ) ; 17 b u f f e r [ c o n t a t o r e ] . i d _ s t a t o = a t o i ( row [ 3 ] ) ; 18 c o n t a t o r e ++; 19 } 20 m y s q l _ f r e e _ r e s u l t ( res ) ; 21 i f ( mysql_query ( conn , " s e l e c t ∗ from secondaria " ) ) { 22 f p r i n t f ( stderr , "%sn " , mysql_error ( conn ) ) ; 23 exit (1) ; 24 } 25 res = mysql_use_result ( conn ) ; 26 contatore = 0; 27 while ( ( row = mysql_fetch_row ( res ) ) != NULL) { 28 b u f f e r [ c o n t a t o r e ] . c o d _ c o n t r o l l o = a t o f ( row [ 0 ] ) ; 29 b u f f e r [ c o n t a t o r e ] . p a r t _ i v a = a t o i ( row [ 1 ] ) ; 30 b u f f e r [ c o n t a t o r e ] . quantita = a t o i ( row [ 2 ] ) ; 31 c o n t a t o r e ++; 32 } 33 m y s q l _ f r e e _ r e s u l t ( res ) ; 34 mysql_close ( conn ) ; 8
  • 10. 35 } Listing 4.2: Esempio di scrittura nel database db_master 1 for ( j = 0 ; j < NELEM; j ++) { 2 sprintf ( scrittura_principale , 3 " i n s e r t i n t o p r i n c i p a l e values (%3.2 f , %d , %d , %d ) " , b u f f e r [ j ] . id_operazione , b u f f e r [ j ] . p r o t o c o l l o , b u f f e r [ j ] . i d _ c i t t a , buffer [ j ] . id_stato ) ; 4 mysql_query ( conn_master1 , s c r i t t u r a _ p r i n c i p a l e ) ; 5 } 6 for ( j = 0 ; j < NELEM; j ++) { 7 sprintf ( scrittura_secondaria , 8 " i n s e r t i n t o secondaria values (%3.2 f , %d , %d ) " , b u f f e r [ j ] . c o d _ c o n t r o l l o , b u f f e r [ j ] . part_iva , b u f f e r [ j ] . quantita ) ; 9 mysql_query ( conn_master1 , s c r i t t u r a _ s e c o n d a r i a ) ; 10 } 9
  • 11. Capitolo 5 Algoritmo parallelo L’algoritmo parallelo si divide principalmente in due sezioni: quella del master e quella dello slave. All’inizio il master conosce il numero degli slave e, utilizzando una MPI_Send, in- via a ciascuno di essi le informazioni necessarie per effettuare l’accesso in lettura a ciascun aggregator. Per comodità è stato creato un vettore database che contiene i nomi degli aggregators che ancora devono essere assegnati. Tale vettore viene tenuto in continuo aggiornamento dal ma- ster che ha il compito di eliminare i nomi dei database ogni volta che questi vengono assegnati ai processi slave. Gli slave, che fino a quel momento erano in “ascolto” con l’ausilio della primitiva MPI_Probe, rispondono alla richiesta con una MPI_Recv ed iniziano il proprio lavoro. In questo modo ogni processo slave opera nel corrispettivo database, effettua le query, e scrive nel buffer. A questo punto avviene il processo di sincronizzazione. Il master crea la memory win- dow (MPI_Win_create) a cui gli slave da remoto fanno riferimento per inviare, tramite la primitiva MPI_Put, i buffer che precedentemente erano stati riempiti. Il master ora è in possesso di tutti i risultati delle query effettuate fino a quel momento dai processi slave e quindi può effettuare la prima scrittura nel db_master. Adesso il master deve controllare il vettore database. Se questo è vuoto significa che il contenuto di tutti gli aggregators è stato scritto nel db_master e in tal caso il programma termina con l’invio a tutti gli slave di una MPI_Send con un tag di fine lavoro. In caso contrario, il master deve controllare quali sono i processi slave liberi in quel momento trasmettendo loro le informazioni rimanenti. Naturalmente il tutto avviene discriminando i processi dispari da quelli pari per cui ad un aggregator di indice dispari avrà accesso esclusivamente un processo dispari e viceversa. Listing 5.1: Funzione master: prima assegnazione dei lavori agli slave 1 for ( i = 1 ; i <= numworker ; i ++) { 2 invio = i ; 3 MPI_Send(& i n v i o , 1 , MPI_INT , i , CICLO1, MPI_COMM_WORLD) ; 4 database [ i ] = 1 ; 5 } 6 MPI_Win_create(& b u f f e r , NELEM ∗ sizeof ( query ) , sizeof ( query ) , MPI_INFO_NULL, MPI_COMM_WORLD, &f i n e s t r a ) ; 7 MPI_Win_fence ( 0 , f i n e s t r a ) ; 8 // 10
  • 12. 9 // 10 MPI_Win_fence ( 0 , f i n e s t r a ) ; 11 MPI_Win_free(& f i n e s t r a ) ; Listing 5.2: Funzione master: assegnazione dei lavori successivi agli slave 1 MPI_Recv (NULL, 0 , MPI_INT , MPI_ANY_SOURCE, CICLO2, MPI_COMM_WORLD, &s t a t u s ) ; 2 terminato = s t a t u s .MPI_SOURCE; 3 v e t t o r e [ terminato ] = 1 ; 4 i f ( ( terminato % 2 ) == 1 ) { 5 k = 1; 6 for ( k = 1 ; k <= DATABASE; k++) { 7 i f ( database [ k ] == 0 && ( k % 2 ) == 1 ) { 8 invio = k ; 9 MPI_Send(& i n v i o , 1 , MPI_INT , terminato , CICLO1, MPI_COMM_WORLD) ; 10 database [ k ] = 1 ; 11 break ; 12 } 13 } 14 } 15 i f ( ( terminato % 2 ) == 0 ) { 16 k = 1; 17 for ( k = 1 ; k <= DATABASE; k++) { 18 i f ( database [ k ] == 0 && ( k % 2 ) == 0 ) { 19 invio = k ; 20 MPI_Send(& i n v i o , 1 , MPI_INT , terminato , CICLO1, MPI_COMM_WORLD) ; 21 database [ k ] = 1 ; 22 break ; 23 } 24 } 25 } Listing 5.3: La funzione slave 1 for ( ; ; ) { 2 disp = ( rank−1)∗NELEM; 3 MPI_Probe ( 0 ,MPI_ANY_TAG,MPI_COMM_WORLD s t a t u s ) ; ,& 4 i f ( s t a t u s .MPI_TAG==CICLO1) { 5 MPI_Recv(& i n v i o , 1 , MPI_INT , source , CICLO1,MPI_COMM_WORLD s t a t u s ) ; ,& 6 s p r i n t f ( pippo , " db_slave_%d " , i n v i o ) ; 7 char ∗db=pippo ; 8 9 //******** Lavoro database *********// 10 11 conn=m y s q l _ i ni t (NULL) ; 12 13 /* Connect to database */ 14 15 i f ( ! mysql_real_connect ( conn , server , user , password , db , 0 ,NULL, 0 ) ) { 16 f p r i n t f ( stderr , "%sn" , mysql_error ( conn ) ) ; 17 exit (1) ; 18 } 19 20 /* send SQL query */ 21 22 i f ( mysql_query ( conn , " s e l e c t ∗ from p r i n c i p a l e " ) ) { 11
  • 13. 23 f p r i n t f ( stderr , "%sn" , mysql_error ( conn ) ) ; 24 exit (1) ; 25 } 26 res = mysql_use_result ( conn ) ; 27 k = 0; 28 while ( ( row = mysql_fetch_row ( res ) ) != NULL) { 29 b u f f e r [ k ] . i d _ o p e r a z i o n e = a t o f ( row [ 0 ] ) ; 30 b u f f e r [ k ] . p r o t o c o l l o = a t o i ( row [ 1 ] ) ; 31 b u f f e r [ k ] . i d _ c i t t a = a t o i ( row [ 2 ] ) ; 32 b u f f e r [ k ] . i d _ s t a t o = a t o i ( row [ 3 ] ) ; 33 k++; 34 } 35 m y s q l _ f r e e _ r e s u l t ( res ) ; 36 37 /* send SQL query */ 38 39 i f ( mysql_query ( conn , " s e l e c t ∗ from secondaria " ) ) { 40 f p r i n t f ( stderr , "%sn" , mysql_error ( conn ) ) ; 41 exit (1) ; 42 } 43 res = mysql_use_result ( conn ) ; 44 k = 0; 45 while ( ( row = mysql_fetch_row ( res ) ) != NULL) { 46 b u f f e r [ k ] . c o d _ c o n t r o l l o = a t o f ( row [ 0 ] ) ; 47 b u f f e r [ k ] . p a r t _ i v a = a t o i ( row [ 1 ] ) ; 48 b u f f e r [ k ] . quantita = a t o i ( row [ 2 ] ) ; 49 k++; 50 } 51 52 /* close connection */ 53 54 m y s q l _ f r e e _ r e s u l t ( res ) ; 55 mysql_close ( conn ) ; 56 MPI_Type_struct ( 2 , blockcounts , o f f s e t , oldtypes ,&MY_PART) ; 57 MPI_Type_commit(&MY_PART) ; 58 MPI_Win_create (MPI_BOTTOM, 0 , 1 ,MPI_INFO_NULL,MPI_COMM_WORLD f i n e s t r a ) ; ,& 59 MPI_Win_fence ( 0 , f i n e s t r a ) ; 60 MPI_Put(& b u f f e r ,NELEM,MY_PART, 0 , disp ,NELEM,MY_PART, f i n e s t r a ) ; 61 MPI_Win_fence ( 0 , f i n e s t r a ) ; 62 MPI_Win_free(& f i n e s t r a ) ; 63 MPI_Type_free(&MY_PART) ; 64 MPI_Send (NULL, 0 , MPI_INT, 0 , CICLO2,MPI_COMM_WORLD) ; 65 } 66 else i f ( s t a t u s .MPI_TAG == CICLO3) { 67 MPI_Recv (NULL, 0 , MPI_INT , source , CICLO3,MPI_COMM_WORLD s t a t u s ) ; ,& 68 MPI_Win_create (MPI_BOTTOM, 0 , 1 ,MPI_INFO_NULL,MPI_COMM_WORLD f i n e s t r a ) ; ,& 69 MPI_Win_fence ( 0 , f i n e s t r a ) ; 70 MPI_Win_fence ( 0 , f i n e s t r a ) ; 71 MPI_Win_free(& f i n e s t r a ) ; 72 } 73 else i f ( s t a t u s .MPI_TAG == FINITO ) { 74 p r i n t f ( "FINEn" ) ; 75 break ; 76 } 77 } La struttura che abbiamo utilizzato per il buffer prevede sette campi che coincidono con quelli 12
  • 14. delle due tabelle del database. Listing 5.4: Struct query e derived datatype 1 //-----Define struct-----// 2 3 typedef struct { 4 float id_operazione ; 5 float cod_controllo ; 6 int p r o t o c o l l o ; 7 int i d _ c i t t a ; 8 int i d _ s t a t o ; 9 int p a r t _ i v a ; 10 int quantita ; 11 } query ; 12 13 //-----Derived datatype-----// 14 15 MPI_Datatype o l d t y p e s [ 2 ] = { MPI_FLOAT, MPI_INT } ; 16 int blockcounts [ 2 ] = { 2 , 5 } ; 17 MPI_Aint o f f s e t [ 2 ] = { 0 , 2 ∗ sizeof ( f l o a t ) } ; 18 MPI_Datatype MY_PART; 13
  • 15. Capitolo 6 Analisi di complessità e scalabilità La complessità temporale dell’algoritmo varia in relazione alla dimensione dell’input. Infatti all’aumentare delle occorrenze nelle tabelle dei vari aggregators aumenta il tempo di esecu- zione delle varie query. Come è già stato detto in precedenza si è scelto di effettuare una query per ogni aggregator invece di effettuare query parallele per non incorrere in una dila- tazione ancora maggiore dei tempi. Le prove e gli studi effettuati sul tempo di esecuzione di varie query hanno permesso di stabilire che la complessità temporale dell’algoritmo dipende fortemente dal tempo effettivo di esecuzione di una query SQL. Il tempo delle query è lineare ed aumenta in base al numero di occorrenze. È naturale quindi che il tempo di esecuzione del programma deriva dal tempo totale per leggere tutte le occorrenze dei vari aggregators sommato al tempo che occorre al master per scrivere i risultati nel db_master. Questo è riconducibile al problema di cercare un elemento all’interno di una lista non ordinata. Tale problema ha una complessità pari ad O (n). Per quanto riguarda la scalabilità il programma è da considerarsi “parzialmente” scalabile (scalabilità di carico) in quanto l’implementazione è vincolata dal numero di database. Infatti le basi di dati sono strutture statiche e devono essere già presenti nel cluster al momento del lancio del programma. Tali strutture non possono essere costruite a run-time e perciò limitano la scalabilità e modificano le strategie di implementazione del codice. 14
  • 16. Capitolo 7 Valutazione e misurazione delle prestazioni Sono stati eseguiti diversi test con valori variabili di carico dei database in modo da osservare l’impatto delle dimensioni sulle performance; i test sono stati ripetuti per tre dimensioni di carico: 36000 occorrenze (6000 per ogni aggregator), 72000 occorrenze (12000 per ogni aggre- gator) e 108000 occorrenze (18000 per ogni aggregator). La tabella 7.1 riporta i valori osservati per le tre dimensioni: Tabella 7.1: Valori osservati nelle diverse prove Occorrenze Processori Tp Sp Ep 36000 seriale 80,2 1 1 36000 3 58,4 1,37 0,46 36000 5 57,6 1,39 0,28 36000 7 56,6 1,42 0,18 72000 seriale 156,4 1 1 72000 3 113,2 1,38 0,46 72000 5 112 1,4 0,28 72000 6 108,8 1,44 0,21 108000 seriale 234,6 1 1 108000 3 167,6 1,4 0,47 108000 5 164,8 1,42 0,28 108000 7 161,2 1,46 0,21 Le figure 7.1, 7.2 e 7.3 invece mostrano i grafici relativi ai dati osservati per le diverse dimensioni del problema testate. Dal grafico 7.2 si evince che più sono piccole le dimensioni del database e maggiore sarà l’overhead. Non avendo a disposizione un algoritmo sequenziale è stato calcolato lo speedup relativo eseguendo il programma parallelo con un solo processore. 15
  • 17. Figura 7.1: Grafico del tempo relativo alle tre prove Figura 7.2: Grafico dello speedup relativo alle tre prove 16
  • 18. Figura 7.3: Grafico dell’efficienza relativo alle tre prove 17
  • 19. Bibliografia [1] http://it.wikipedia.org/. [2] www-it.mysql.com/. [3] L. Pacifici, Dispense del corso di Applicazione e Calcolo in Rete - Corso Avanzato. Corso di laurea specialistica in Informatica, Università degli studi di Perugia, Italia. 18