Prodotto Matrice - Vettore in MPI
|
|
|
- Aldo Grasso
- 8 anni fa
- Просмотров:
Транскрипт
1 Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica Elaborato di Calcolo Parallelo Prodotto Matrice - Vettore in MPI Anno Accademico 2011/2012 Professoressa Alessandra D Alessio Studenti
2 Definizione del Problema In quest elaborato ci concentreremo sull operazione di prodotto Matrice Vettore su un architettura parallela MIMD (Multiple Instruction Multiple Data) multi computer, in particolare ci avvarremo di quella a 64 CPU (16 x Intel Xeon E5410 [email protected] 64 bit) offerta dall Università degli Studi di Napoli Federico II attraverso l infrastruttura S.Co.P.E. L obiettivo è la valutazione dell efficienza dell algoritmo da noi implementato, valutazione a cui giungeremo raccogliendo i risultati dei diversi test eseguiti (che si differenziano per la dimensione della matrice su cui verrà effettuata l operazione e/o per il numero di processori coinvolti) per calcolare tre parametri fondamentali: tempo impiegato dall algoritmo parallelo con p processori T(p), speed-up S(p) ed efficienza E(p). Descriviamo in particolare l operazione che vogliamo realizzare. Vogliamo realizzare il calcolo del prodotto: Ax = y ove A è una matrice quadrata,, mentre x e y sono vettori della stessa dimensione della matrice; quindi Definita la matrice A: 2
3 E il vettore x: Si vuole ottenere il vettore risultato y così calcolato: Si può notare come questa operazione sia fortemente parallelizzabile osservando la natura stessa dei calcoli che l algoritmo dovrà effettuare. Infatti, ciascun elemento del vettore dei risultati y viene calcolato effettuando i prodotti scalari di ogni riga della matrice A per il vettore x. E quindi chiaro che i prodotti scalari possono essere effettuati in maniera indipendente gli uni dagli altri, è proprio questa l idea alla base della parallelizzazione di quest algoritmo. 3
4 Descrizione dell algoritmo Nome capitolo Esistono tre diverse strategie per il calcolo del prodotto di una matrice A (che supporremo essere sempre quadrata) con un vettore X, il cui comune denominatore è rappresentato dalla presenza delle seguenti fasi: - Suddivisione della matrice a blocchi: A seconda della strategia implementata viene scelto un modo di decomposizione della matrice A, le alternative sono le seguenti: decomposizione in blocchi di righe, decomposizione in blocchi di colonne o decomposizione a scacchiera. Verrà contestualmente effettuata anche l eventuale decomposizione del vettore x fra i vari processori. Tale divisione sarà necessaria o meno a seconda della strategia implementata. - Calcolo del vettore risultato parziale: operando sui blocchi ricevuti al passo precedente, ogni processore calcolerà un vettore risultato parziale. Le componenti di quest ultimo in base alla strategia adottata rappresenteranno o un sottoinsieme delle componenti definitive del vettore finale oppure un contributo al prodotto scalare che deve avere luogo tra ogni riga della matrice ed il vettore x affinché il prodotto matrice vettore sia calcolato correttamente. - Aggregazione: A seconda della strategia scelta, sarà utilizzato un approccio differente per aggregare i risultati parziali ottenuti al passo precedente. 4
5 Prima strategia (Algoritmo a blocchi di righe) In questo caso il processore designato come ROOT, possessore sia dell intera matrice A che del vettore x, provvederà a frammentare in blocchi di righe la matrice tra i diversi processori, il vettore x sarà invece trasmesso in broadcast a tutti i processori. Ciascun processore riceverà quindi almeno una riga della matrice A e tutto il vettore x, provvederà quindi ad eseguire il prodotto scalare tra ciascuna riga ricevuta e x. Indicando con y il vettore risultante dall operazione di prodotto tra la matrice ed il vettore, si avrà che ogni singolo processore calcolerà tanti elementi del vettore y quante sono le righe della matrice avute in consegna dal ROOT e saranno omologhi tra loro; ciò significa che se un processore ha ricevuto le prime tre righe determinerà i primi tre elementi del vettore risultante y. Alla fine del calcolo parziale, il processore ROOT provvederà a unire i diversi elementi del vettore y calcolati dai diversi processori, andando a formare il vettore risultato completo. Passiamo ora alla descrizione dell algoritmo implementato. In primis definiamo le variabili da utilizzare in seguito, in particolare Matrice ed y (dai nomi è intuibile quali elementi della strategia sopra descritta rappresentino) sono dei puntatori ad intero inizializzati a zero perché per i processori diversi da quello ROOT devono essere solo visibili affinché le funzioni di MPI da essi invocate non diano errori a tempo di compilazione; di fatto tali vettori non saranno mai allocati se non appunto dal processore ROOT. Successivamente inizializziamo l ambiente di esecuzione MPI tramite la funzione di libreria MPI_Init, ad ogni processore assegniamo nella variabile numproc il numero di processori coinvolti sfruttando la funzione di libreria MPI_Comm_size; mentre con la MPI_Comm_rank il processore chiamante potrà memorizzare nella variabile id il proprio identificativo. Una volta accertata la validità degli input inseriti tramite alcuni controlli (tali controlli vengono eseguiti da tutti i processori altrimenti in caso di esito negativo non tutti eseguirebbero la MPI_Finalize()); tutti i processori 5
6 allocano dinamicamente ed inizializzano i vettori SendCount, Displs, RcvCount e RcvDispls, i primi due sono utilizzati dalla funzione MPI_Scatterv, mentre gli ultimi due dalla MPI_Gatherv. La cardinalità di tali vettori è pari al numero di processori coinvolti mentre i valori memorizzati in ogni singola locazione saranno semanticamente simili ma numericamente diversi per SendCount e RcvCount e per Displs e RcvDispls. Infatti SendCount e RcvCount indicano rispettivamente il numero di elementi che il processore ROOT dovrà inviare/ricevere dai vari processori; nel primo caso gli elementi sono le righe della matrice mentre nel secondo sono componenti del vettore y. Displs e RcvDispls invece indicano lo spostamento all interno del vettore da inviare/ricevere. Le ulteriori variabili definite da tutti i processori sono dim, matloc e ypar in cui saranno memorizzati rispettivamente il numero di righe che ogni processore dovrà ricevere, la sottomatrice su cui ciascuno lavorerà localmente e il sottovettore di y prodotto. Il solo processore ROOT si occuperà del riempimento della matrice Matrice (allocata dinamicamente come un vettore per facilitarne l invio) e del vettore x. Si è scelto di riempire la matrice con una costante numerica unitaria per salvaguardasi da problemi legati all overflow. A questo punto è tutto pronto per la distribuzione delle righe ad ogni processore attraverso la funzione MPI_Scatterv, che abbiamo scelto di utilizzare per assicurare la distribuzione anche nel caso in cui il numero di righe non sia un multiplo del numero dei processori, e al broadcast del vettore x, che avviene mediante la funzione MPI_Bcast. Con la funzione MPI_Barrier siamo sicuri che il calcolo del tempo (come differenza di istanti) sarà avviato non appena tutti possederanno il materiale su cui poter operare per determinare il proprio sottovettore ypar. Quest ultimo, una volta calcolato da ciascun processore, sarà recapitato al processore ROOT attraverso l operazione collettiva MPI_Gatherv, funzione che permette appunto la raccolta di dati a carico del processore ROOT. Infine abbiamo pensato di inserire la funzione MPI_Barrier più per un motivo formale che pratico, ovvero per garantire la correttezza del tempo valutato, non solo limitatamente al caso in cui il calcolo sia compiuto dal processore ROOT. Infatti nel caso specifico di questo algoritmo, l ultimo processore che completerà l operazione di raccolta citata sarà 6
7 sempre e solo il processore ROOT in quanto depositario del risultato, mentre gli altri finiranno prima. Dato che il tempo viene calcolato dal processore ROOT, siamo sicuri che anche se non avessimo inserito la funzione di barriera il tempo calcolato da questo non sarebbe variato e sarebbe comunque stato relativo alla terminazione del calcolo per tutti i processori coinvolti; di contro, in assenza della barriera dopo la funzione di gatherv, il calcolo del tempo non sarebbe stato corretto nel caso questo fosse stato calcolato da un processore diverso dal ROOT. Infine, prima di eseguire la MPI_Finalize(), per rilasciare l ambiente di esecuzione MPI, sono deallocati tutti i puntatori. Seconda strategia (Algoritmo a blocchi di colonne) Al contrario del caso appena visto, la ripartizione della matrice tra tutti i processori qui avverrà per colonne, pertanto il processore ROOT non dovrà distribuire tutto il vettore x, ma ogni processore ne riceverà solo una parte. In particolare ognuno riceverà un numero di righe di x pari al numero di colonne della propria sottomatrice. Ciascuno parteciperà in parte al calcolo di tutti i prodotti scalari tra ogni singola riga ed il vettore x, pertanto la ricostruzione della y finale passerà attraverso la somma puntuale dei vettori prodotti localmente. Procediamo con la descrizione dell algoritmo, focalizzandoci solo sui punti per i quali questa strategia si differenzia dalla precedente, onde evitare ripetizioni inutili. La fasi di inizializzazione e controllo sono quasi identiche, ciò che cambia è l implementazione della distribuzione delle colonne della matrice. Per realizzare la distribuzione della matrice A, allocata dinamicamente come se fosse un vettore, abbiamo scelto di ricavarne la trasposta, anch essa istanziata come un vettore, per poi inviare le righe di quest ultima a ciascun processore. In questo modo abbiamo potuto semplificare la distribuzione per colonne, avendo di fatto realizzato una distribuzione per righe della matrice trasposta, molto più semplice in quanto si tratta della distribuzione di elementi 7
8 adiacenti del vettore. I blocchi ricevuti da ogni nodo del communicator MPI_COMM_WORLD coincideranno proprio con le colonne della matrice di partenza; anche qui è impiegata la funzione MPI_Scatterv, scelta al posto della semplice scatter per assicurare la corretta distribuzione della matrice anche nel caso in cui il numero di colonne non sia un multiplo del numero di processori. Per evitare di dover ricalcolare la versione non trasposta della matrice locale ad ogni processore prima di dover lavorare sulla stessa, abbiamo preferito operare su quest ultima invertendo gli indici di riga e colonna. Inoltre visto che l output locale ad ogni processore è un vettore della stessa cardinalità del vettore x, ma in cui saranno memorizzate solo le somme parziali di ogni prodotto scalare riga per colonna, si dovrà provvedere a sommare tali parziali, memorizzati in ypar. Per questo motivo usufruiremo della funzione di libreria MPI_Reduce. Prima di arrestare il conto del tempo, ottenuto come differenza di intervalli, è invocata da tutti i processori la funzione MPI_Barrier. Così come per la strategia vista in precedenza tale invocazione è superflua ai fini dei tempi, ma legittima da un punto di vista formale. Terza strategia (Algoritmo a blocchi quadrati) L ultimo approccio che vedremo può essere facilmente compreso se inquadrato come risultato dell incrocio tra le due precedentemente menzionate. Sulla base di quanto detto si può intuire che ogni processore non riceverà né colonne né righe complete, ma solo una sottoparte di queste. Infatti si ricorrerà alla decomposizione checkboard della matrice, per cui ogni processore si ritroverà a lavorare su un blocco quadrato della matrice iniziale. Dato che ognuno non riceverà mai righe complete della matrice A non dovrà neanche ricevere tutto il vettore x, ma solo la sottoparte di quest ultimo con righe pari in numero e in posizione alla parte di colonne della matrice A ricevute. 8
9 Ricordando la nostra ipotesi di partenza, ovvero che la matrice A deve essere quadrata, possiamo definire p blocchi quadrati, ciascuno dei quali con cardinalità pari a La risposta implementativa a questo approccio può variare nel modo in cui il vettore x è distribuito ai processori. Per facilitare il processo distributivo, i processori vengono organizzati in una topologia a griglia bidimensionale, la quale rappresenta un organizzazione virtuale dei suoi membri. Occorre però diversificare la modalità di distribuzione della matrice A da quella del vettore x. Nel primo caso il processore zero del MPI_COMM_WORLD in posizione (0,0) nella griglia suddividerà la matrice di partenza in sottomatrici non quadrate il cui numero di righe sarà pari a ed il numero di colonne sarà ancora uguale ad n. Ognuna di tali porzioni dovrà poi essere distribuita ai processori disposti lungo la stessa colonna del processore zero, ovvero la prima. Essi rappresenteranno i motori di distribuzione degli ulteriori frammenti in cui il sottoblocco di matrice ad essi assegnato dovrà essere ulteriormente scomposto. In particolare ciascun processore capo-riga (processore 0 di ogni riga) invierà ad ogni nodo del proprio communicator di riga, una sottomatrice quadrata di cardinalità. Per quanto concerne la distribuzione del vettore x, possiamo evidenziare i seguenti passi: Il processore zero (0,0) spezzetta il vettore x in sottovettori ed invia ogni distinta porzione ai processori del suo communicator di colonna. I processori sulla prima colonna eccetto il processore diagonale (0,0) inviano a quelli disposti sulla diagonale della griglia il frammento del vettore x in loro possesso. Da ogni processore diagonale si diffonde lungo il rispettivo communicator di colonna di appartenenza la sottoparte di x. 9
10 L ultima precisazione degna di nota è quella relativa alla ricomposizione dei risultati parziali di ogni nodo della griglia. Ricordiamo che ciascuno di essi, al termine delle operazioni locali, disporrà di un sottovettore che su ogni riga ospiterà la somma parziale del prodotto scalare relativo a ciascuna delle riga della matrice A ricevute in parte. Basterà che i processori zero su ogni communicator di riga raccolgano e sommino puntualmente i vettori localmente prodotti dagli altri; infine il processore in posizione (0,0) all interno della griglia riaggregherà in un unico vettore le porzioni della y di cui ciascun processore del suo communicator di colonna è depositario. Per quanto riguarda l'analisi del codice sviluppato si avrà che dopo la fase di inizializzazione e controllo degli input, il processore zero del MPI_COMM_WORLD invia in broadcast a tutti i processori il numero di righe/colonne di ogni blocco che riceveranno, così poi potranno conoscere lo spazio da dover allocare. Esso si occuperà inoltre dell'istanziazione e della relativa inizializzaione della matrice A (nel codice è la matrice M) e deil vettore x. Segue la parte di codice destinata alla creazione della griglia e dei communicator per ogni riga ed ogni colonna della rete topologica. Successivamente solo i processori disposti lungo la prima colonna della griglia (accomunati dall'avere la seconda componente delle coordinate topologiche pari a 0) saranno coinvolti nella chiamata di due MPI_Scatter; prima per ricevere la sottoparte della matrice A e poi per quella di x da parte del processore ROOT, ovvero zero, del MPI_COMM_WORLD. Abbiamo scelto di non utilizzare la MPI_Scatterv perché qui il numero di elementi da distribuire ad ogni processore sarà sempre uguale in numero. I processori considerati provvederanno a calcolare la versione trasposta M1T della matrice non quadrata ricevuta, in modo da lavorare suelementi adiacenti della stessa, allocata sotto forma di vettore, facilitando la distribuzione. Su ogni singolo communicator di riga verrà eseguita la 10
11 MPI_Scatter. Per quanto concerne la distribuzione della x sono state previste diverse soluzioni. La prima prevede che tale vettore venga distribuito fra tutti i processori della prima colonna e successivamente inviato dagli stessi ai vari processori appartenenti alla diagonale della griglia topologica; essa prevede l utilizzo di MPI_Send e MPI_Recv. Per identificare i processori sulla diagonale abbiamo notato che il loro rank all interno del rispettivo comunicato di riga coincide con il valore della prima coordinata del processore zero sulla medesima riga. La seconda strategia alternativa è basata sulla creazione di un nuovo communicator che includa al suo interno solo i processori disposti sulla diagonale. Tuttavia prima di arrivare a ciò abbiamo creato un gruppo con tutti i processori della griglia e poi un sottogruppo con quelli contenuti nella diagonale della griglia. Il vantaggio del nuovo communicator si esplica nella possibilità di applicare la MPI_Scatter al posto di più di una send. Nell ultima variante è solo il processore zero della griglia ad avere come destinatari quelli sulla diagonale tramite delle MPI_Isend abbinate con MPI_Recv. In questo modo il mittente può risparmiare tempo non dovendo aspettare che il destinatario precedente abbia ricevuto prima del successivo. In seguito tutti i processori della diagonale eseguiranno un broadcast di quanto precedentemente ottenuto sul rispettivo communicator di colonna. Si procederà quindi con il calcolo delle varie componenti del vettore delle soluzioni y. I risultati parziali verrano dapprima sommati mediante l'utilizzo della funzione MPI_Reduce su ciascun communicator di riga ed in seguito raccolte dal processore 0 del COMM_WORLD mediante MPI_Gather eseguita sul communicator della prima colonna. Lo stesso processore 0 calcolerà il tempo totale come differenza tra i due istante temporali a sua disposizione. L ultimo inevitabile passaggio consente di liberare i puntatori utilizzati. 11
12 Input, Output e Errori In questo capitolo descriveremo il modo di funzionamento dei tre programmi da noi sviluppati, corrispondenti alle tre possibili strategie implementative del prodotto matrice vettore. Parleremo dell interfaccia di questi programmi, andando a specificare gli input richiesti e gli output ottenibili. Per i tre programmi le interfacce sono coincidenti, quindi ne parleremo in generale. Procederemo inoltre alla descrizione delle situazioni d errore in cui è possibile incorrere nell utilizzo dei tre programmi da noi sviluppati. Parametri di Input I parametri forniti in ingresso al programma da noi sviluppato sono due: - n: Intero positivo. Dimensione della matrice quadrata di cui andremo a effettuare il prodotto con il vettore x. Tale vettore avrà la stessa dimensione della matrice. Inoltre, questa dimensione dovrà essere almeno pari al numero di processori su cui è richiesta l esecuzione, altro parametro d ingresso. Se omesso è settato al valore di default, n=20. - p: numero di processori a cui sarà sottomessa l esecuzione dell algoritmo. Il sistema su cui andiamo a lavorare è dotato di 64 core, quindi p dovrà essere necessariamente inferiore a tale numero. 12
13 Si noti che per utilizzare il programma relativo alla terza strategia realizzativa sarà necessario fornire i due input in maniera tale che n sia un multiplo della radice di p. Si noti, inoltre, che la matrice A è stata riempita, all interno del codice, da un valore numerico costante (1). Il vettore X, invece, è stato riempito da numeri progressivi i, con per poter controllare l effettiva correttezza dell algoritmo. Sono stati scelti questi valori semplici in quanto lo scopo principale di questo lavoro è quello di mostrare l efficienza dell algoritmo di prodotto matrice - vettore parallelo. Parametri di Output Il programma da noi implementato fornisce come output, mostrati a video al termine dell esecuzione, due parametri: - Il tempo impiegato per effettuare i calcoli, in maniera tale da poter fare delle valutazioni riguardanti l efficienza dell algoritmo. - Il vetore risultato Y, contenente il prodotto matrice vettore, calcolato in parallelo sul numero di processori indicati in input. I parametri di input vengono forniti al sistema mediante il file matvec.pbs e, all interno dello stesso file, viene stabilito che il sistema genererà al termine dell esecuzione due file di output: - matvec.out in cui verrà stampato l output del programma; - matvec.err che conterrà gli eventuali errori restituiti dal sistema; Il formato PBS (Portable Batch System) permette di comandare l esecuzione di un insieme di jobs su un architettura parallela. Abbiamo scritto il file matvec.pbs in maniera tale che esso fornisca in ingresso i parametri, evitando di dover modificare il file matvec.c per ogni esecuzione. Riportiamo qui di seguito il contenuto del file matvec.pbs : 13
14 #!/bin/bash ########################## # # # The PBS directives # # # ########################## #PBS -q studenti #PBS -l nodes=4 #PBS -N matvec #PBS -o matvec.out #PBS -e matvec.err ########################################## # # # Output some useful job information. # # # ########################################## NCPU=`wc -l < $PBS_NODEFILE` echo echo ' This job is allocated on '${NCPU' cpu(s)' echo 'Job is running on node(s): ' cat $PBS_NODEFILE PBS_O_WORKDIR=$PBS_O_HOME/matvec echo echo PBS: qsub is running on $PBS_O_HOST 14
15 echo PBS: originating queue is $PBS_O_QUEUE echo PBS: executing queue is $PBS_QUEUE echo PBS: working directory is $PBS_O_WORKDIR echo PBS: execution mode is $PBS_ENVIRONMENT echo PBS: job identifier is $PBS_JOBID echo PBS: job name is $PBS_JOBNAME echo PBS: node file is $PBS_NODEFILE echo PBS: current home directory is $PBS_O_HOME echo PBS: PATH = $PBS_O_PATH echo echo "Eseguo: /usr/lib64/openmpi/1.4-gcc/bin/mpicc -o $PBS_O_WORKDIR/matvec $PBS_O_WORKDIR/matvec.c" /usr/lib64/openmpi/1.4-gcc/bin/mpicc -o $PBS_O_WORKDIR/matvec $PBS_O_WORKDIR/matvec.c echo "Eseguo: /usr/lib64/openmpi/1.4-gcc/bin/mpiexec -machinefile $PBS_NODEFILE -np $NCPU $PBS_O_WORKDIR/matvec" /usr/lib64/openmpi/1.4-gcc/bin/mpiexec -machinefile $PBS_NODEFILE -np $NCPU $PBS_O_WORKDIR/matvec Il numero di processori viene fornito mediante la direttiva #PBS -l nodes=x, mentre la dimensione n della matrice A (e del vettore X) viene sottomesso aggiungendolo in coda alla direttiva di esecuzione mpiexec. Strategia I: Situazioni d errore Elenchiamo qui di seguito le situazioni d errore che vengono restituite dal programma relativo alla prima strategia nel caso di un errato utilizzo dello stesso. I controlli effettuati per la restituzione di tali situazioni d errore riguardano i parametri di input forniti in ingresso dall utente. 15
16 Elenco delle situazioni d errore previste: 1) Errore dovuto all inserimento di più di un argomento. L unico, eventuale, argomento da fornire in input è n, dimensione della matrice quadrata di cui effettuare il prodotto con il vettore X della stessa dimensione. ERRORE! Sono stati inseriti troppi argomenti! Sintassi corretta: Matvec n_processori [dim_matrix] Il parametro [dim_matrix] e' opzionale ed e' settato a 20 di default. 2) Errore dovuto all inserimento di un valore non intero come dimensione della matrice ERRORE! La cardinalità della matrice deve essere un intero! Il programma terminerà. 3) Errore dovuto alla richiesta di esecuzione su un numero di core superiore a 64, ovvero il numero di core di cui dispone il sistema su cui il programma è stato testato. ERRORE! Il sistema dispone di 64 core. Non è possibile richiederne un numero superiore. Il programma terminerà. 4) Errore dovuto a una combinazione errata dei parametri di input. Il numero di righe della matrice deve essere almeno pari al numero di processori su cui è stata richiesta l esecuzione per assicurare una corretta distribuzione della matrice. ERRORE! La cardinalità della matrice non può essere minore del numero di processori utilizzati! Il programma terminerà. 16
17 Strategia II: Situazioni d errore Elenchiamo qui di seguito le situazioni d errore che vengono restituite dal programma relativo alla seconda strategia nel caso di un errato utilizzo dello stesso. I controlli effettuati per la restituzione di tali situazioni d errore riguardano i parametri di input forniti in ingresso dall utente. Elenco delle situazioni d errore previste: 1) Errore dovuto all inserimento di più di un argomento. L unico, eventuale, argomento da fornire in input è n, dimensione della matrice quadrata di cui effettuare il prodotto con il vettore X della stessa dimensione. ERRORE! Sono stati inseriti troppi argomenti! Sintassi corretta: Matvec n_processori [dim_matrix] Il parametro [dim_matrix] e' opzionale ed e' settato a 20 di default. NB. Il numero di processori p deve essere tale che la sua radice quadrata sia un intero E la [dim_matrix] deve a sua volta essere un multiplo di tale radice. 2) Errore dovuto all inserimento di un valore non intero come dimensione della matrice ERRORE! La cardinalità della matrice deve essere un intero! Il programma terminerà. 3) Errore dovuto alla richiesta di esecuzione su un numero di core superiore a 64, ovvero il numero di core di cui dispone il sistema su cui il programma è stato testato. ERRORE! Il sistema dispone di 64 core. Non è possibile richiederne un numero superiore. Il programma terminerà. 17
18 4) Errore dovuto a una combinazione errata dei parametri di input. Il numero di colonne della matrice deve essere almeno pari al numero di processori su cui è stata richiesta l esecuzione per assicurare una corretta distribuzione della matrice. ERRORE! La cardinalità della matrice non può essere minore del numero di processori utilizzati! Il programma terminerà. Strategia III: Situazioni d errore Elenchiamo qui di seguito le situazioni d errore che vengono restituite dal programma relativo alla terza strategia nel caso di un errato utilizzo dello stesso. I controlli effettuati per la restituzione di tali situazioni d errore riguardano i parametri di input forniti in ingresso dall utente. Elenco delle situazioni d errore previste: 1) Errore dovuto all inserimento di più di un argomento. L unico, eventuale, argomento da fornire in input è n, dimensione della matrice quadrata di cui effettuare il prodotto con il vettore X della stessa dimensione. ERRORE! Sono stati inseriti troppi argomenti! Sintassi corretta: Matvec n_processori [dim_matrix] Il parametro [dim_matrix] e' opzionale ed e' settato a 20 di default. 2) Errore dovuto all inserimento di un valore non intero come dimensione della matrice ERRORE! La cardinalità della matrice deve essere un intero! Il programma terminerà. 18
19 3) Errore dovuto alla richiesta di esecuzione su un numero di core superiore a 64, ovvero il numero di core di cui dispone il sistema su cui il programma è stato testato. ERRORE! Il sistema dispone di 64 core. Non è possibile richiederne un numero superiore. Il programma terminerà. 4) Errore dovuto alla richiesta di esecuzione su un numero di core che non rispetti le specifiche dettate dalla terza strategia. Infatti, il numero di processori deve essere tale che la sua radice quadrata sia un intero. ERRORE! Il numero di processori p deve essere tale che la sua radice quadrata sia un intero! Il programma terminerà. 5) Errore dovuto a una combinazione errata dei parametri di input. Infatti, la dimensione della matrice deve essere un multiplo della radice quadrata del numero di processori. ERRORE! La [dim_matrix] deve essere un multiplo della radice di p! Il programma terminerà. 19
20 Analisi del software Adesso concentreremo l attenzione sulle tabelle e i grafici relativi al calcolo del tempo di esecuzione T(p), dello speed-up S(p) e dell efficienza E(p). Strategia I Tempo di esecuzione T(p) Nella tabella che segue sono riportati i valori del tempo di esecuzione registrato al variare del numero di processori P e del numero di righe della matrice N. Quindi muovendoci lungo la colonna possiamo capire se c è un vantaggio o meno legato all aumento del numero di processori coinvolti. Tutti i valori del T(p) sono espressi in microsecondi, mentre ciascuno dei valori in tabella è stato ottenuto eseguendo la media sui campioni ottenuti eseguendo una quindicina di prove; un analogo discorso si estende anche ai valori posizionati nelle tabella dello speed-up S(p) e dell efficienza E(p). 20
21 N P 1 84, , , , , , , , , , , , , , , , , , , , , , , ,3625 Tabella 1 Tempo di esecuzione T(p) prima strategia Figura 2 T(p) al variare del numero di processori e del numero di righe della matrice: prima strategia Guardando la Figura 2 e la Tabella 1 possiamo notare che per N fissato non è sempre conveniente l utilizzo di un architettura parallela. In particolare, per N ridotto l utilizzo dell architettura parallela non è conveniente. Un esempio particolare è quello per N=100 nel quale, passando da p=4 a p=8 i tempi di esecuzione addirittura peggiorano. Possiamo notare che fino a N=1.000 è quasi indifferente l impiego di più processori, mentre iniziamo a scoprirne i vantaggi a partire da N=5.000 e ad avere dei tempi particolarmente soddisfacenti per N= ed N= Negli ultimi tre casi citati si ottengono dei tempi particolarmente convenienti per p=8. Si può quindi dedurre, anche osservando la 21
22 figura 2, ottenuta mediante il software MATLAB, che l utilizzo di un architettura parallela diventa efficace solo per N abbastanza grande. Invertendo il punto di vista, fissando quindi il numero di processori p e variando il valore di N, è possibile notare un ragionevole aumento dei tempi, dovuto alla necessità di effettuare calcoli su ordini di grandezza molto differenti tra loro. Strategia I Speed-up S(p) Nella tabella che segue sono riportati i valori dello speed-up relativi alla prima strategia. Ricordiamo che esso misura, a parità di n, la riduzione del tempo di esecuzione rispetto all algoritmo su 1 processore. Il valore è stato ottenuto a partire dal T(p) medio calcolato a partire da una quindicina di campioni. S( p) T(1) T( p) N P 2 1, , , , , , , , , , , , , , , , , , Tabella 2 Valori dello Speed-up S(p) al variare di N e di P prima strategia 22
23 Figura 3 Valori dello Speed-up S(p) al variare di N e di P prima strategia Il punto di riferimento per giudicare lo speed-up delle nostre esecuzioni è la linea rosa, che rappresenta il valore ideale. Questo grafico conferma ulteriormente le considerazioni fatte osservando i tempi, infatti per N di dimensione ridotta siamo molto lontani dalla linea ideale. Per N=100 e N=500 siamo ancora lontani dall approssimarci al miglior caso possibile, mentre valori nei dintorni di quelli ideali sono stati registrati per N= e N= Per quanto riguarda il numero di processori p, la vicinanza ai valori ottimi viene registrata per i valori di N su menzionati con p=2 e p=4, mentre con p=8 i benefici tratti dall uso dell architettura parallela non sono ottimi come nei casi precedenti. Strategia I Efficienza E(p) Nella tabella che segue sono riportati i valori dell efficienza, indicativa di quanto l algoritmo sfrutti il parallelismo del calcolatore. S( p) E( p) p 23
24 N P 2 0, , , , , , , , , , , , , , , , , , Tabella 3 Valori dell Efficienza E(p) al variare di N e p prima strategia Il valore di riferimento di E(p) è rappresentato nella Figura 4, in rapporto allo stesso scopriamo che i nostri test forniscono un risultato interessante per N=5.000 e N= con p=2 e con p=4, mentre sugli stessi processori per N= si ottengono valori quasi ideali. In tutti gli altri casi all aumentare di p l efficienza degrada, ciò in piena aderenza con le osservazioni suggeriteci dai grafici di T(p) ed S(p). Figura 4 Efficienza E(p) al variare di N e di p 24
25 Strategia II Tempo di esecuzione T(p) Nella tabella che segue sono riportati i valori del tempo di esecuzione del programma relativo alla seconda strategia registrati al variare del numero di processori P e del numero N di colonne della matrice. N P 1 91, , , , , , , , , , , , , , , , , , , , , , , ,8833 Tabella 4 Tempo di esecuzione T(p) seconda strategia Figura 5 T(p) al variare del numero di processori e del numero di colonne della matrice: seconda strategia 25
26 Guardando la Figura 5 e la Tabella 4 possiamo notare che le considerazioni da fare sono analoghe a quelle fatte per la strategia I. Anche in questo caso è possibile notare che per N ridotto l utilizzo dell architettura parallela non è conveniente. Un esempio particolare è quello per N=100 nel quale, aumentando esponenzialmente il numero di processori su cui è eseguito il programma, i tempi di esecuzione addirittura peggiorano. Possiamo notare che fino a N=1.000 è quasi indifferente l impiego di più processori, mentre iniziamo a scoprirne i vantaggi a partire da N=5.000 e ad avere dei tempi particolarmente soddisfacenti per N= ed N= Negli ultimi tre casi citati si ottengono dei tempi particolarmente convenienti per p=8. Come già fatto per la prima strategia, si può quindi dedurre, anche osservando la figura 2, ottenuta mediante il software MATLAB, che l utilizzo di un architettura parallela diventa efficace solo per N abbastanza grande. Invertendo il punto di vista, fissando quindi il numero di processori p e variando il valore di N, è possibile notare un ragionevole aumento dei tempi, dovuto alla necessità di effettuare calcoli su ordini di grandezza molto differenti tra loro. Strategia II Speed-up S(p) Nella tabella che segue sono riportati i valori dello speed-up relativi alla seconda strategia. Ricordiamo che esso misura, a parità di n, la riduzione del tempo di esecuzione rispetto all algoritmo su 1 processore. N P 2 1, , , , , , , , , , , , , , , , , , Tabella 5 Valori dello Speed-up S(p) al variare di N e di P seconda strategia 26
27 Figura 6 Valori dello Speed-up S(p) al variare di N e di P seconda strategia Il punto di riferimento per giudicare lo speed-up delle nostre esecuzioni è la linea tratteggiata, che rappresenta il valore ideale. Questo grafico conferma ulteriormente le considerazioni fatte osservando i tempi, infatti per N di dimensione ridotta siamo molto lontani dalla linea ideale. A differenza di quanto accadeva per la prima strategia, però, il valore dello speed-up si attesta intorno a quello ideale già per N=500. Come nella prima strategia, valori nei dintorni di quelli ideali sono stati registrati per N= e N= Per quanto riguarda il numero di processori p, la vicinanza ai valori ottimi viene registrata per i valori di N su menzionati con p=2 e p=4, mentre con p=8 i benefici tratti dall uso dell architettura parallela non sono ottimi come nei casi precedenti. Strategia II Efficienza E(p) Nella tabella che segue sono riportati i valori dell efficienza, indicativa di quanto l algoritmo sfrutti il parallelismo del calcolatore. 27
28 N P 2 0, , , , , , , , , , , , , , , , , , Tabella 6 Valori dell Efficienza E(p) al variare di N e p seconda strategia Il valore di riferimento di E(p) è rappresentato nella Figura 4, in rapporto allo stesso scopriamo che i nostri test forniscono un risultato interessante per N=5.000 e N= con p=2 e con p=4, mentre sugli stessi processori per N= si ottengono valori quasi ideali. In tutti gli altri casi all aumentare di p l efficienza degrada, ciò in piena aderenza con le osservazioni suggeriteci dai grafici di T(p) ed S(p). Figura 7 Efficienza E(p) al variare di N e di p 28
29 Strategia III Tempo di esecuzione T(p) Nella tabella che segue sono riportati i valori del tempo di esecuzione del programma relativo alla terza strategia registrati al variare del numero di processori P e del numero N di colonne della matrice. N P 1 127, , , , , , , , , , , , , , , , , , , ,162 Tabella 7 Tempo di esecuzione T(p) terza strategia Figura 8 T(p) al variare del numero di processori e del numero di righe della matrice: terza strategia 29
30 Guardando la Figura 8 e la Tabella 7 la prima cosa da notare è che, rispetto ai casi precedenti, è stato necessario testare l esecuzione del programma su input differenti. Ad ogni modo, le considerazioni da fare sono analoghe a quelle fatte per le altre strategie. Anche in questo caso è possibile notare che per N ridotto l utilizzo dell architettura parallela non è conveniente. Per N=240 si può notare come il tempo d esecuzione per p=16 è peggiore rispetto a p=1. Questo è possibile spiegarlo a causa dei ritardi dovuti alla elevata comunicazione MPI che, però, risulta non utile a causa del ridotto ordine di grandezza dei calcoli da effettuare. Anche in questo caso, iniziamo a scoprire i vantaggi dell uso di un architettura parallela a partire da N=7.200 e ad avere dei tempi particolarmente soddisfacenti per N= e N= Negli ultimi tre casi citati si ottengono dei tempi particolarmente convenienti per p=16. Come già fatto per la prima strategia, si può quindi dedurre, anche osservando la figura 8, ottenuta mediante il software MATLAB, che l utilizzo di un architettura parallela diventa efficace solo per N abbastanza grande. Invertendo il punto di vista, fissando quindi il numero di processori p e variando il valore di N, è possibile notare un ragionevole aumento dei tempi, dovuto alla necessità di effettuare calcoli su ordini di grandezza molto differenti tra loro. Strategia III Speed-up S(p) Nella tabella che segue sono riportati i valori dello speed-up relativi alla terza strategia. Ricordiamo che esso misura, a parità di n, la riduzione del tempo di esecuzione rispetto all algoritmo su 1 processore. 30
31 N P 4 2, , , , , , , , , , , , , , , Tabella 8 Valori dello Speed-up S(p) al variare di N e di P: terza strategia Figura 9 Valori dello Speed-up S(p) al variare di N e di P: terza strategia Il punto di riferimento per giudicare lo speed-up delle nostre esecuzioni è la linea tratteggiata, che rappresenta il valore ideale. Questo grafico conferma ulteriormente le considerazioni fatte osservando i tempi, infatti per N di dimensione ridotta siamo molto lontani dalla linea ideale. Come nelle altre strategie, valori nei dintorni di quelli ideali sono stati registrati per input abbastanza elevati come N= e N= Per quanto riguarda il numero di processori p, la vicinanza ai valori ottimi viene registrata per i valori di N su menzionati con p=4 e p=9, in paticolare con N= notiamo un aderenza quasi ottimale alla linea del valore ideale per tutti i processori con i quali abbiamo testato il programma. 31
32 Strategia III Efficienza E(p) Nella tabella che segue sono riportati i valori dell efficienza, indicativa di quanto l algoritmo sfrutti il parallelismo del calcolatore. N P 4 0, , , , , , , , , , , , , , , Tabella 9 Valori dell Efficienza E(p) al variare di N e p terza strategia Il valore di riferimento di E(p) è rappresentato nella Figura 10, in rapporto allo stesso scopriamo che i nostri test forniscono un risultato interessante per N=7.200 con p=4 e con p=9, mentre per = ed N= si ottengono valori quasi ideali per qualsiasi valore di p. In tutti gli altri casi all aumentare di p l efficienza degrada, ciò in piena aderenza con le osservazioni suggeriteci dai grafici di T(p) ed S(p). Figura 10 Efficienza E(p) al variare di N e di p 32
33 Esempi d uso e codice In questo capitolo verranno illustrati degli esempi d uso degli algoritmi da noi implementati. Mostreremo in che modo verrà richiamato il programma e come esso verrà mostrato a video. Inoltre, mostreremo qui il codice dei programmi da noi sviluppati, il quale sarà correlato da una documentazione interna che ne spiegherà il funzionamento. Esempio d uso Mostriamo un esempio del risultato che si ottiene a video andando a eseguire uno dei tre programmi da noi implementati. Abbiamo deciso di mostrare un solo esempio d uso in quanto per le tre strategie l output è identico. Forniremo come input una cardinalità della matrice pari 25 e richiederemo che l algoritmo venga eseguito su p=2 processori. Come illustrato nel capitolo dedicato a Input, Output e Situazioni d Errore, tali input saranno forniti al sistema mediante il file matvec.pbs. 33
34 Figura 2 Esempio esecuzione con N=25 Si nota che vengono mostrate a video le informazioni sugli input forniti, n e p, il tempo totale impiegato per il calcolo del prodotto matrice-vettore ed il relativo risultato dell elaborazione. Il risultato verrà mostrato sottoforma di vettore ed è stato validato confrontando tale vettore con i risultati ottenuti in Matlab; è stato scelto di utilizzare una matrice semplice costituita da tutti 1 in quanto il nostro obiettivo è quello di ottenere informazioni significative riguardo i tempi di esecuzione, essendo già stata provata la correttezza dell algoritmo sviluppato. 34
35 Strategia I: Codice del programma Riportiamo qui di seguito il codice da noi scritto per la realizzazione di questo programma. Abbiamo utilizzato il linguaggio di programmazione C. Il codice è stato corredato di una documentazione interna che spiega le varie istruzioni utilizzate. /*Algoritmo per il calcolo del prodotto matrice - vettore: strategia I. Autori: Giuffrida Serena M63/239 Lampognana Francesca M63/144 Mele Gianluca M63/145 */ #include <stdio.h> #include <mpi.h> #include "malloc.h" #define ROOT 0 int main(int argc, char **argv) { /***Definizione delle variabili***/ int id, numproc; int dimmatrix=20; // Valore di default relativo alla cardinalità della matrice int dim; int i,j; double tin,tfin,tempotot; int* Matrice=0; // Tali puntatori vengono utilizzati ed allocate solo dal processore 0 int* y=0; // ma devono essere visti da tutti per le varie funzioni offerte da MPI /***Inizializzazione***/ MPI_Init(&argc, &argv); /***Numero processori***/ MPI_Comm_size(MPI_COMM_WORLD, &numproc); /***Individuazione ranks***/ MPI_Comm_rank(MPI_COMM_WORLD, &id); // Controlli sugli input // E' possibile richiamare il programma specificando uno o due argomenti, rispettivamente numero di processori // e cardinalità della matrice if(argc==2) // nel caso in cui viene specificata una cardinalità diversa da quella di default tramite il PBS dimmatrix=atoi(argv[1]); 35
36 else if(argc>2){ // controllo su eventuale inserimento di un numero eccessivo di argomenti if(!id){ printf("errore! Sono stati inseriti troppi argomenti!\n"); printf("\nsintassi corretta:\n"); printf("matvec n_processori [dim_matrix]\n\n"); printf("il parametro [dim_matrix] e' opzionale ed e' settato a 20 di default.\n"); MPI_Finalize(); return -1; // Controllo sulla cardinalità della matrice che deve essere un intero if((dimmatrix-(int)dimmatrix)!=0){ if(!id){ printf("errore! La cardinalità della matrice deve essere un intero!\n"); printf("il programma terminerà.\n"); MPI_Finalize(); return -1; // Controllo che il numero di righe della matrice sia almeno pari al numero di processori associati per // una corretta distribuzione della stessa if(dimmatrix<numproc){ if(!id){ printf("errore! La cardinalità della matrice non può essere minore del numero di processori utilizzati!\n"); printf("il programma terminerà.\n"); MPI_Finalize(); return -1; // Controllo sull'eventuale richiesta di esecuzione su un numero eccessivo di processori if(numproc>64){ if(!id){ printf("errore! Il sistema dispone di 64 core. Non è possibile richiederne un numero superiore.\n"); printf("il programma terminerà.\n"); MPI_Finalize(); return -1; // Fine controlli sugli input // Istanzio dinamicamente i vettori necessari alla ScatterV e GatherV int* SendCount=(int*)calloc(numproc,sizeof(int)); int* Displs=(int*)calloc(numproc,sizeof(int)); int* RcvCount=(int*)calloc(numproc,sizeof(int)); int* RcvDispls=(int*)calloc(numproc,sizeof(int)); // Inizializzo il vettore SendCount e RcvCount for(i=0;i<numproc;i++){ SendCount[i]=(int)(dimmatrix/numproc); 36
37 RcvCount[i]=SendCount[i]; if(dimmatrix%numproc>0) // Caso in cui la matrice non sia equidistribuibile fra i vari processori for(i=0;i<dimmatrix%numproc;i++){ SendCount[i]=SendCount[i]+1; RcvCount[i]=RcvCount[i]+1; for(i=0;i<numproc;i++) SendCount[i]=SendCount[i]*dimmatrix; // Inizializzo il vettore Displs e RcvDispls Displs[0]=0; RcvDispls[0]=0; for(i=1;i<numproc;i++){ RcvDispls[i]=RcvDispls[i-1]+RcvCount[i-1]; Displs[i]=Displs[i-1]+SendCount[i-1]; // Ogni processore avrà nella variabile dim il numero di righe assegnategli dim=(int)(dimmatrix/numproc); if(id<(dimmatrix%numproc)) dim=dim+1; // Alloco la matrice parziale che l'id-esimo processore riceverà in base alla I strategia ed il vettore // in cui inserire i risultati parziali int* matloc=(int*)calloc(dim*dimmatrix,sizeof(int*)); int* ypar=(int*)calloc(dim,sizeof(int)); int* x=(int*)calloc(dimmatrix,sizeof(int)); // Il processore ROOT va ad allocare ed istanziare la Matrice,il vettore x ed il vettore delle soluzioni finali y if(!id){ Matrice=(int*)calloc(dimmatrix*dimmatrix,sizeof(int*)); y=(int*)calloc(dimmatrix,sizeof(int)); printf("numero di processori: %d.\n",numproc); printf("dimensione matrice: %d.\n",dimmatrix); for(i=0;i<dimmatrix;i++){ x[i]=i; // definito come sequenza dei primi dimmatrix-1 numeri for(j=0;j<dimmatrix;j++) Matrice[j+i*dimmatrix]=1; // utilizzeremo una matrice costituita da tutti 1 // Distribuzione delle varie matrici parziali e del vettore x a tutti i processori MPI_Scatterv(Matrice,SendCount,Displs,MPI_INT,matloc,dim*dimmatrix,MPI_INT,ROOT, MPI_COMM_WORLD); MPI_Bcast(x,dimmatrix,MPI_INT,ROOT,MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD); // Aspettiamo che tutti abbiano ricevuto i vari elementi // Inizio valutazione dei tempi if(!id) tin=mpi_wtime(); 37
38 // Ogni processore effettua il calcolo e andrà a definire la sua porzione del vettore delle soluzioni for(j=0;j<dim;j++){ for(i=0;i<dimmatrix;i++) ypar[j]=ypar[j]+x[i]*matloc[i+j*dimmatrix]; // La gatherv andrà a comporre il vettore finale delle soluzioni raccogliendo i vari risultati // parziali da tutti i processori coinvolti MPI_Gatherv(ypar,dim,MPI_INT,y,RcvCount,RcvDispls,MPI_INT,ROOT,MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD); if(!id){ tfin=mpi_wtime(); // Fine valutazione dei tempi tempotot=1.e6*(tfin-tin); // il tempo impiegato viene calcolato come differenza degli istanti tfin e tin printf("tempo totale impiegato: %f.\n",tempotot); printf("algoritmo PARALLELO\n"); printf("calcolo su %d processori.\n",numproc); for(i=0;i<dimmatrix;i++) printf("y[%d] = %d\n",i,y[i]); // Deallocazione delle variabili dinamiche istanziate all'interno del programma. free(matrice); free(x); free(y); free(ypar); free(matloc); free(sendcount); free(displs); free(rcvcount); free(rcvdispls); MPI_Finalize(); return 0; 38
39 Strategia II: Codice del programma Riportiamo qui di seguito il codice da noi scritto per la realizzazione di questo programma. Abbiamo utilizzato il linguaggio di programmazione C. Il codice è stato corredato di una documentazione interna che spiega le varie istruzioni utilizzate. /*Algoritmo per il calcolo del prodotto matrice - vettore: II strategia. Autori: Giuffrida Serena M63/239 Lampognana Francesca M63/144 Mele Gianluca M63/145 */ #include <stdio.h> #include <mpi.h> #include "malloc.h" #define ROOT 0 int main(int argc, char **argv) { /***Definizione delle variabili***/ int id, numproc; int dimmatrix=20; // Valore di default relativo alla cardinalità della matrice int dim; int i,j; double tin,tfin,tempotot; int* Matrice=0; // Tali puntatori vengono utilizzati ed allocate solo dal int* x=0; // processore 0 ma devono essere visti da tutti per le varie int* y=0; // funzioni offerte da MPI int* MTrasposta=0; /***Inizializzazione***/ MPI_Init(&argc, &argv); /***Numero processori***/ MPI_Comm_size(MPI_COMM_WORLD, &numproc); /***Individuazione ranks***/ MPI_Comm_rank(MPI_COMM_WORLD, &id); // Controlli sugli input // E' possibile richiamare il programma specificando uno o due argomenti, rispettivamente numero di processori // e cardinalità della matrice if(argc==2) // nel caso in cui viene specificata una cardinalità diversa da quella di default tramite il PBS dimmatrix=atoi(argv[1]); else if(argc>2){ // controllo su eventuale inserimento di un numero eccessivo di argomenti 39
40 if(!id){ printf("errore! Sono stati inseriti troppi argomenti!\n"); printf("\nsintassi corretta:\n"); printf("matvec2 n_processori [dim_matrix]\n\n"); printf("il parametro [dim_matrix] e' opzionale ed e' settato a 20 di default.\n"); MPI_Finalize(); return -1; // Controllo sulla cardinalità della matrice che deve essere un intero if((dimmatrix-(int)dimmatrix)!=0){ if(!id){ printf("errore! La cardinalità della matrice deve essere un intero!\n"); printf("il programma terminerà.\n"); MPI_Finalize(); return -1; // Controllo che il numero di righe della matrice sia almeno pari al numero di processori associati per // una corretta distribuzione della stessa if(dimmatrix<numproc){ if(!id){ printf("errore! La cardinalità della matrice non può essere minore del numero di processori utilizzati!\n"); printf("il programma terminerà.\n"); MPI_Finalize(); return -1; // Controllo sull'eventuale richiesta di esecuzione su un numero eccessivo di processori if(numproc>64){ if(!id){ printf("errore! Il sistema dispone di 64 core. Non è possibile richiederne un numero superiore.\n"); printf("il programma terminerà.\n"); MPI_Finalize(); return -1; // Fine controlli sugli input // Istanzio dinamicamente i vettori necessari alla ScatterV e GatherV int* SendCount=(int*)calloc(numproc,sizeof(int)); int* Displs=(int*)calloc(numproc,sizeof(int)); int* RcvCount=(int*)calloc(numproc,sizeof(int)); int* RcvDispls=(int*)calloc(numproc,sizeof(int)); // Inizializzo il vettore SendCount e RcvCount for(i=0;i<numproc;i++){ SendCount[i]=(int)(dimmatrix/numproc); RcvCount[i]=SendCount[i]; 40
41 if(dimmatrix%numproc>0) // Caso in cui la matrice non sia equidistribuibile fra i vari processori for(i=0;i<dimmatrix%numproc;i++){ SendCount[i]=SendCount[i]+1; RcvCount[i]=RcvCount[i]+1; for(i=0;i<numproc;i++) SendCount[i]=SendCount[i]*dimmatrix; // Inizializzo il vettore Displs e RcvDispls Displs[0]=0; RcvDispls[0]=0; for(i=1;i<numproc;i++){ RcvDispls[i]=RcvDispls[i-1]+RcvCount[i-1]; Displs[i]=Displs[i-1]+SendCount[i-1]; // Ogni processore avrà nella variabile dim il numero di colonne assegnategli dim=(int)(dimmatrix/numproc); if(id<(dimmatrix%numproc)) dim=dim+1; // Alloco la matrice parziale che l'id-esimo processore riceverà in base alla II strategia, il vettore // delle x assegnategli ed il vettore in cui inserire i risultati locali int* matloc=(int*)calloc(dim*dimmatrix,sizeof(int*)); int* xloc=(int*)calloc(dim,sizeof(int)); int* ypar=(int*)calloc(dimmatrix,sizeof(int)); // Il processore ROOT va ad allocare ed istanziare la Matrice, il vettore x ed il vettore delle soluzioni finali y, // esso utilizzerà anche una matrice ausiliaria definita come la trasposta della Matrice; tale matrice faciliterà // la fase di distribuzione della matrice, così come richiesto per la II strategia if(!id){ Matrice=(int*)calloc(dimmatrix*dimmatrix,sizeof(int*)); MTrasposta=(int*)calloc(dimmatrix*dimmatrix,sizeof(int*)); x=(int*)calloc(dimmatrix,sizeof(int)); y=(int*)calloc(dimmatrix,sizeof(int)); printf("numero di processori: %d.\n",numproc); printf("dimensione matrice: %d.\n",dimmatrix); for(i=0;i<dimmatrix;i++){ x[i]=i; // definito come sequenza dei primi dimmatrix-1 numeri for(j=0;j<dimmatrix;j++) Matrice[j+i*dimmatrix]=1; // utilizzeremo una matrice costituita da tutti 1 // Calcolo della matrice trasposta for(i=0;i<dimmatrix;i++) for(j=0;j<dimmatrix;j++) MTrasposta[j+i*dimmatrix]=Matrice[i+j*dimmatrix]; // Distribuzione delle varie matrici parziali e del vettore x a tutti i processori 41
42 MPI_Scatterv(MTrasposta,SendCount,Displs,MPI_INT,matloc,dim*dimmatrix,MPI_INT,RO OT,MPI_COMM_WORLD); MPI_Scatterv(x,RcvCount,RcvDispls,MPI_INT,xloc,dim,MPI_INT,ROOT,MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD); // Aspettiamo che tutti abbiano ricevuto i vari elementi // Inizio valutazione dei tempi if(!id) tin=mpi_wtime(); // Ogni processore effettua il calcolo e andrà a definire la sua porzione del vettore delle soluzioni for(j=0;j<dimmatrix;j++){ for(i=0;i<dim;i++) ypar[j]=ypar[j]+xloc[i]*matloc[j+i*dimmatrix]; // avendo utilizzato la trasposta della Matrice iniziale // La funzione Reduce effettua la riunione dei risultati calcolati da ogni processore, calcolando la somma totale. // Il risultato complessivo verrà calcolato dal processore ROOT nella variabile y MPI_Reduce(ypar,y,dimmatrix,MPI_INT,MPI_SUM,ROOT,MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD); if(!id){ tfin=mpi_wtime(); // Fine valutazione dei tempi tempotot=1.e6*(tfin-tin); // il tempo impiegato viene calcolato come differenza degli istanti tfin e tin printf("tempo totale impiegato: %f.\n",tempotot); printf("algoritmo PARALLELO\n"); printf("calcolo su %d processori.\n",numproc); for(i=0;i<dimmatrix;i++) printf("y[%d] = %d\n",i,y[i]); // Deallocazione delle variabili dinamiche istanziate all'interno del programma. free(matrice); free(mtrasposta); free(x); free(y); free(ypar); free(xloc); free(matloc); free(sendcount); free(displs); free(rcvcount); free(rcvdispls); MPI_Finalize(); return 0; 42
43 Strategia III: Codice del programma Riportiamo qui di seguito il codice da noi scritto per la realizzazione di questo programma. Abbiamo utilizzato il linguaggio di programmazione C. Il codice è stato corredato di una documentazione interna che spiega le varie istruzioni utilizzate. /*Algoritmo per il calcolo del prodotto Matrice - Vettore: III Strategia. Autori: Giuffrida Serena M63/239 Lampognana Francesca M63/144 Mele Gianluca M63/145 */ #include <stdio.h> #include <mpi.h> #include "malloc.h" #include "math.h" #define ROOT 0 int main(int argc, char **argv) { /***Definizione delle variabili***/ int id,id_griglia, nprocs; int dimmatrix=24; // Valore di default relativo alla cardinalità della matrice int nlocal; int j,i; double tin,tfin,tempotot; int* M=0; // Tali puntatori vengono utilizzati ed allocate solo dal int* x=0; // processore 0 ma devono essere visti da tutti per le varie int* y=0; // funzioni offerte da MPI int* ypar=0; int* M1T=0; // Questi due puntatori invece saranno utilizzati unicamente dai processori int* M1=0; // della prima colonna della griglia per la distribuzione della matrice int dim[2],period[2],coord_griglia[2]; // Variabili utilizzate nella creazione della int free_cord[2]={1,0; // topologia e delle sottotopologie MPI_Comm comm_grid,comm_col,comm_row,comm_diag; MPI_Group grp_aus,grp_diag; MPI_Status stato; MPI_Request rqst; // Communicator ausiliari /***Inizializzazione***/ 43
44 MPI_Init(&argc, &argv); /***Numero processori***/ MPI_Comm_size(MPI_COMM_WORLD, &nprocs); /***Individuazione ranks***/ MPI_Comm_rank(MPI_COMM_WORLD, &id); // Controlli sugli input // E' possibile richiamare il programma specificando uno o due argomenti, rispettivamente numero di processori // e cardinalità della matrice if(argc==2) // nel caso in cui viene specificata una cardinalità diversa da quella di default tramite il PBS dimmatrix=atoi(argv[1]); else if(argc>2){ //controllo su eventuale inserimento di un numero eccessivo di argomenti if(!id){ printf("errore! Sono stati inseriti troppi argomenti!\n"); printf("\nsintassi corretta:\n"); printf("matvec3 n_processori [dim_matrix]\n\n"); printf("il parametro [dim_matrix] e' opzionale ed e' settato a 20 di default.\n"); printf("nb. Il numero di processori p deve essere tale che la sua radice quadrata sia un intero"); printf(" e la [dim_matrix] deve a sua volta essere un multiplo di tale radice.\n"); MPI_Finalize(); return -1; // Controllo che il numero di processori richiesti rispetti le specifiche, il numero di processori deve essere // tale che la sua radice quadrata sia un intero if(((int)(sqrt(nprocs))-sqrt(nprocs))!=0){ if(!id){ printf("errore! Il numero di processori p deve essere tale che la sua radice quadrata sia un intero!\n"); printf("il programma terminerà.\n"); MPI_Finalize(); return -1; // Controllo che la dimensione assegnata alla matrice rispetti le specifiche, la cardinalità della matrice // deve essere un multiplo della radice del numero di processori if(dimmatrix%(int)(sqrt(nprocs))>0){ if(!id){ printf("errore! La cardinalità della matrice deve essere un multiplo della radice del numero di processori!\n"); printf("il programma terminerà.\n"); MPI_Finalize(); return -1; // Controllo sull'eventuale richiesta di esecuzione su un numero eccessivo di processori 44
45 if(nprocs>64){ if(!id){ printf("errore! Il sistema dispone di 64 core. Non è possibile richiederne un numero superiore.\n"); printf("il programma terminerà.\n"); MPI_Finalize(); return -1; // Fine controlli sugli input // Come da specifiche P0 legge dimmatrix, calcola nlocal if(!id) nlocal=dimmatrix/sqrt(nprocs); // E lo manda in broadcast a tutti i processori MPI_Bcast(&nlocal,1,MPI_INT,ROOT,MPI_COMM_WORLD); // Il processore ROOT va ad allocare ed istanziare la Matrice, il vettore x ed il vettore delle soluzioni finali y if(!id){ y=(int*)calloc(dimmatrix,sizeof(int)); x=(int*)calloc(dimmatrix,sizeof(int)); M=(int*)calloc(dimmatrix*dimmatrix,sizeof(int)); printf("numero di processori: %d.\n",nprocs); printf("dimensione matrice: %d.\n",dimmatrix); for(j=0;j<dimmatrix;j++){ x[j]=j; // definito come sequenza dei primi dimmatrix-1 numer for(i=0;i<dimmatrix;i++) M[i+j*dimmatrix]=1; // utilizzeremo una matrice costituita da tutti 1 // Tutti i processori allocano la matrice parziale che l'id-esimo processore riceverà in base // alla III strategia, il vettore delle x assegnategli ed il vettore in cui inserire i risultati parziali int* Mloc=(int*)calloc(nlocal*nlocal,sizeof(int)); int* xloc=(int*)calloc(nlocal,sizeof(int)); int* yloc=(int*)calloc(nlocal,sizeof(int)); // Fase di definizione delle variabili necessarie per la creazione della topologia dim[0]=dim[1]=sqrt(nprocs); // numero di righe e colonne della griglia period[0]=period[1]=0; // imponiamo l'assenza di periodicità // Andiamo a definire la griglia bidimensionale MPI_Cart_create(MPI_COMM_WORLD,2,dim,period,0,&comm_grid); // Ad ogni processore sarà assegnato un nuovo id nella topologia creata MPI_Comm_rank(comm_grid,&id_griglia); // Ogni processore sarà identificato nella griglia con delle coordinate cartesiane MPI_Cart_coords(comm_grid,id_griglia,2,coord_griglia); // Andiamo a definire delle sottogriglie formate dalle varie colonne // della griglia precedentemente definita MPI_Cart_sub(comm_grid,free_cord,&comm_col); 45
46 // Come richiesto nelle specifiche, i processori della prima colonna della griglia riceveranno dal processore 0 // un determinato numero di righe della matrice (pari a nlocal), che andranno poi a distribuire // tra i vari processori della propria riga if(coord_griglia[1]==0){ // Qui accedono solo i processori della prima colonna M1=(int*)calloc(nlocal*dimmatrix,sizeof(int)); // Il processore 0 distribuisce la matrice ed il vettore x ai processori della prima colonna MPI_Scatter(M,nlocal*dimmatrix,MPI_INT,M1,nlocal*dimmatrix,MPI_INT,ROOT,comm_col ); MPI_Scatter(x,nlocal,MPI_INT,xloc,nlocal,MPI_INT,ROOT,comm_col); // Tale Scatter è relativa alla strategia prevista dalle specifiche M1T=(int*)calloc(nlocal*dimmatrix,sizeof(int)); for(j=0;j<dimmatrix;j++) for(i=0;i<nlocal;i++) M1T[i+j*(int)nlocal]=M1[j+i*(int)nlocal]; // Calcolo la traposta della matrice ricevuta in modo da semplificare // Andiamo a definire delle sottogriglie formate dalle varie righe // della griglia precedentemente definita free_cord[0]=0; free_cord[1]=1; MPI_Cart_sub(comm_grid,free_cord,&comm_row); // E procediamo con la distribuzione della matrice lungo le righe MPI_Scatter(M1T,nlocal*nlocal,MPI_INT,Mloc,nlocal*nlocal,MPI_INT,0,comm_row); // STRATEGIA PREVISTA DALLE SPECIFICHE // Distribuzione lungo i processori della diagonale del rispettivo sottovettore di x if(coord_griglia[1]==0 && coord_griglia[0]!=0){ MPI_Send(xloc,nlocal,MPI_INT,coord_griglia[0],coord_griglia[0],comm_row); if(coord_griglia[0]==coord_griglia[1] && coord_griglia[0]!=0) MPI_Recv(xloc,nlocal,MPI_INT,0,coord_griglia[0],comm_row,&stato); /* COMM DIAGONALE // Prima strategia alternativa per la distribuzione del vettore delle x lungo i processori della diagonale; // Essa consiste nel creare un nuovo communicator contenente unicamente i processori della diagonale, così da // facilitare ed ottimizzare il processo di comunicazione e scambio dati MPI_Comm_group(MPI_COMM_WORLD,&grp_aus); // Definiamo un gruppo di processori int* ranks=(int*)calloc(sqrt(nprocs),sizeof(int)); // in cui aggiungo i vari for(i=0;i<sqrt(nprocs);i++) // processori appartenenti ranks[i]=i*sqrt(nprocs)+i; MPI_Group_incl(grp_aus,sqrt(nprocs),ranks,&grp_diag); // della griglia bidimensionale // all 46
47 MPI_Comm_create(MPI_COMM_WORLD,grp_diag,&comm_diag); MPI_Barrier(MPI_COMM_WORLD); // Si procede infine con la distribuzione del vettore if(coord_griglia[0]==coord_griglia[1]) MPI_Scatter(x,nlocal,MPI_INT,xloc,nlocal,MPI_INT,ROOT,comm_diag); */ /* STRATEGIA SEND ASINCRONA // Seconda strategia alternativa per la distribuzione del vettore delle x lungo i processori della diagonale; // Essa prevede una Send asincrona da parte del processore 0 a tutti i processori della diagonale if(!id){ int* xaus=(int*)calloc(nlocal,sizeof(int)); for(i=0;i<sqrt(nprocs);i++){ for(j=0;j<nlocal;j++) xaus[j]=x[i*nlocal+j]; MPI_Isend(xaus,nlocal,MPI_INT,i*(sqrt(nprocs))+i,i,comm_grid,&rqst); // Ogni processore della diagonale andrà ad effettuare quindi una receive dal processore 0, // acquisendo così la propria porzione di x if(coord_griglia[0]==coord_griglia[1]) MPI_Recv(xloc,nlocal,MPI_INT,0,coord_griglia[0],comm_grid,&stato); */ // Una volta che i processori della diagonale hanno la propria porzione del vettore x, // lo inviano in broadcast lungo la propria colonna MPI_Bcast(xloc,nlocal,MPI_INT,coord_griglia[1],comm_col); // Il processore 0 di ogni riga dovrà raccogliere i risultati locali calcolati dai // processori della propria riga, allocherà quindi un vettore ausiliario if(coord_griglia[1]==0) ypar=(int*)calloc(nlocal,sizeof(int)); MPI_Barrier(MPI_COMM_WORLD); // Inizio valutazione dei tempi if(!id) tin=mpi_wtime(); // Ogni processore andrà a calcolarsi la sua porzione di soluzione for(j=0;j<nlocal;j++) for(i=0;i<nlocal;i++) yloc[j]=yloc[j]+mloc[j+i*(int)nlocal]*xloc[i]; // Si procederà con l'operazione di raccolta e somma per ogni riga, sempre a carico del processore 0 // della riga stessa MPI_Reduce(yloc,ypar,nlocal,MPI_INT,MPI_SUM,ROOT,comm_row); // Il processore 0 della griglia si occuperà invece di raccogliere tali vettore per riunirli in un // unico vettore delle soluzioni y if(coord_griglia[1]==0) MPI_Gather(ypar,nlocal,MPI_INT,y,nlocal,MPI_INT,ROOT,comm_col); 47
48 MPI_Barrier(MPI_COMM_WORLD); if(!id){ tfin=mpi_wtime(); // Fine valutazione dei tempi tempotot=1.e6*(tfin-tin); // il tempo impiegato viene calcolato come differenza degli istanti tfin e tin printf("tempo totale impiegato: %f.\n",tempotot); printf("algoritmo PARALLELO\n"); printf("calcolo su %d processori.\n",nprocs); for(i=0;i<dimmatrix;i++) printf("y[%d] = %d\n",i,y[i]); //Deallocazione delle variabili dinamiche istanziate all'interno del programma. free(m); free(x); free(y); free(ypar); free(yloc); free(xloc); free(mloc); free(m1); free(m1t); MPI_Finalize(); return 0; 48
Somma di un array di N numeri in MPI
Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica Elaborato di Calcolo Parallelo Somma di un array di N numeri in MPI Anno Accademico 2011/2012 Professoressa Alessandra D Alessio Studenti
Pigreco in OpenMP. Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica. Elaborato di Calcolo Parallelo. Anno Accademico 2011/2012
Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica Elaborato di Calcolo Parallelo Pigreco in OpenMP Anno Accademico 2011/2012 Professoressa Alessandra D Alessio Studenti Giuffrida Serena M63/000239
Prodotto Matrice - Vettore in OpenMP
Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica Elaborato di Calcolo Parallelo Prodotto Matrice - Vettore in OpenMP Anno Accademico 2011/2012 Professoressa Alessandra D Alessio Studenti
Prodotto Matrice - Vettore in MPI II Strategia
Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica Esercitazione di Calcolo Parallelo Prodotto Matrice - Vettore in MPI II Strategia Anno Accademico 2010/2011 Prof.ssa Alessandra D'alessio
Prodotto Matrice - Vettore in MPI - III Strategia
Facoltà di Ingegneria Corso di Studi in Ingegneria Informatica Esercitazione di Calcolo Parallelo Prodotto Matrice - Vettore in MPI - III Strategia Anno Accademico 2010/2011 Prof.ssa Alessandra D'alessio
Si digita login e password e si clicca su accedi. Si apre la finestra di collegamento:
Corso di Laurea Specialistica Ingegneria Informatica Laboratorio di Calcolo Parallelo Prof. Alessandra d Alessio GUIDA AL LABORATORIO DI CALCOLO PARALLELO Il progetto SCoPE (www.scope.unina.it) ha messo
UNIVERSITA DEGLI STUDI DI NAPOLI FEDERICO II
UNIVERSITA DEGLI STUDI DI NAPOLI FEDERICO II PROGETTO DI CALCOLO PARALLELO SOMMA DEGLI ELEMENTI DI UN VETTORE STUDENTE Gabriele Piantadosi (885/000282) 1. OBIETTIVI E AMBIENTE DI CALCOLO Si vuole distribuire
L Allocazione Dinamica della Memoria
L Allocazione Dinamica della Memoria Maurizio Palesi DIIT Università di Catania Viale Andrea Doria 6, 95125 Catania [email protected] http://www.diit.unict.it/users/mpalesi Sommario Questo documento
A.d'Alessio. Calcolo Parallelo. Esempi di topologie
Message Passing Interface MPI Le topologie 1 Esempi di topologie Anello Griglia Toro L utilizzo di una topologia per la progettazione di un algoritmo in ambiente MIMD è spesso legata alla geometria intrinseca
Introduzione a Matlab
INFORMATICA B Ingegneria Elettrica Introduzione a Matlab Introduzione a Matlab Matlab (MATrix LABoratory) è uno strumento per il calcolo scientifico ed ingegneristico Matlab facilita lo sviluppo di programmi
L'Allocazione Dinamica della Memoria nel linguaggio C
L'Allocazione Dinamica della Memoria nel linguaggio C Prof. Rio Chierego [email protected] http://www.riochierego.it/informatica.htm Sommario Questo documento tratta l'allocazione dinamica della memoria
Calcolo Parallelo. Domanda. In particolare. Qual è l algoritmo parallelo. PROBLEMA: Prodotto Matrice-Vettore
Calcolo Parallelo Algoritmi Paralleli per il prodotto Matrice-Vettore Laura Antonelli PROBLEMA: Prodotto Matrice-Vettore Progettazione di un algoritmo parallelo per architettura MIMD a memoria distribuita
Gestione dinamica della memoria
Programmazione M-Z Ingegneria e Scienze Informatiche - Cesena A.A. 2016-2017 Gestione dinamica della memoria Pietro Di Lena - [email protected] A pessimistic programmer sees the array as half empty.
ERRATA CORRIGE. void SvuotaBuffer(void); void SvuotaBuffer(void) { if(getchar()!=10) {svuotabuffer();} }
ERRATA CORRIGE Pulizia del buffer di input: come fare? (1) Dopo aver richiamato getchar() per prelevare un carattere dal buffer di input, inseriamo una seconda chiamata a getchar(), senza assegnare il
Fondamenti di Informatica
Fondamenti di Informatica AlgoBuild: Strutture selettive, iterative ed array Prof. Arcangelo Castiglione A.A. 2016/17 AlgoBuild : Strutture iterative e selettive OUTLINE Struttura selettiva Esempi Struttura
Linguaggio C: le funzioni. Introduzione e sintassi
ISIS "Guido Tassinari" di Pozzuoli Indirizzo Informatico - Articolazione Informatica Informatica Prof. A.S. 2012/2013 Linguaggio C: le funzioni. Introduzione e sintassi 21/10/2012 Introduzione Spesso alcuni
Introduzione alla programmazione Algoritmi e diagrammi di flusso. Sviluppo del software
Introduzione alla programmazione Algoritmi e diagrammi di flusso F. Corno, A. Lioy, M. Rebaudengo Sviluppo del software problema idea (soluzione) algoritmo (soluzione formale) programma (traduzione dell
Funzioni in C. Funzioni. Strategie di programmazione. Funzioni in C. Come riusare il codice? (2/3) Come riusare il codice? (1/3)
Funzioni Il concetto di funzione Parametri formali e attuali Il valore di ritorno Definizione e chiamata di funzioni Passaggio dei parametri Corpo della funzione 2 Strategie di programmazione Riuso di
STRUTTURE DI CONTROLLO DEL C++
STRUTTURE DI CONTROLLO DEL C++ Le istruzioni if e else Le istruzioni condizionali ci consentono di far eseguire in modo selettivo una singola riga di codice o una serie di righe di codice (che viene detto
Corso sul linguaggio Java
Corso sul linguaggio Java Modulo JAVA2 2.1- Funzioni 1 Prerequisiti Programmazione elementare in Java Tecnica top-down Concetto matematico di funzione Compilazione e link di programmi Esecuzione di funzioni
Funzioni, Stack e Visibilità delle Variabili in C
Funzioni, Stack e Visibilità delle Variabili in C Programmazione I e Laboratorio Corso di Laurea in Informatica A.A. 2016/2017 Calendario delle lezioni Lez. 1 Lez. 2 Lez. 3 Lez. 4 Lez. 5 Lez. 6 Lez. 7
MPI è una libreria che comprende:
1 Le funzioni di MPI MPI è una libreria che comprende: Funzioni per definire l ambiente Funzioni per comunicazioni uno a uno Funzioni percomunicazioni collettive Funzioni peroperazioni collettive 2 1 3
Funzioni. Unità 1. Domenico Daniele Bloisi. Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR
Corso di Fondamenti di Informatica Ingegneria delle Comunicazioni BCOR Ingegneria Elettronica BELR Domenico Daniele Bloisi Docenti Parte I prof. Silvio Salza [email protected] http://www.dis.uniroma1.it/~salza/fondamenti.htm
Sistemi lineari. Lorenzo Pareschi. Dipartimento di Matematica & Facoltá di Architettura Universitá di Ferrara
Sistemi lineari Lorenzo Pareschi Dipartimento di Matematica & Facoltá di Architettura Universitá di Ferrara http://utenti.unife.it/lorenzo.pareschi/ [email protected] Lorenzo Pareschi (Univ. Ferrara)
Linguaggio C++ 8. Matrici
2009-2010 Ingegneria Aerospaziale Prof. A. Palomba - Elementi di Informatica (E-Z) Linguaggio C++ 8 Matrici Linguaggio C++ 8 1 Array a più dimensioni. Sintassi generale : tipo nome [dimensione 1][dimensione
Esercizi sulla macchina assembler, strutturazione a livelli, spazio di indirizzamento
Architettura degli Elaboratori, a.a. 2005-06 Esercizi sulla macchina assembler, strutturazione a livelli, spazio di indirizzamento Esercizio 1 (svolto) a) Compilare in assembler Risc (Cap. V) un programma
C: panoramica. Violetta Lonati
C: panoramica Violetta Lonati Università degli studi di Milano Dipartimento di Scienze dell Informazione Laboratorio di algoritmi e strutture dati Corso di laurea in Informatica AA 2009/2010 Violetta Lonati
Studio degli algoritmi
COMPLESSITÀ COMPUTAZIONALE DEGLI ALGORITMI Fondamenti di Informatica a.a.2006/07 Prof. V.L. Plantamura Dott.ssa A. Angelini Studio degli algoritmi Dato un problema P, le problematiche riguardano: Sintesi
Unità Didattica 4 Linguaggio C. Vettori. Puntatori. Funzioni: passaggio di parametri per indirizzo.
Unità Didattica 4 Linguaggio C Vettori. Puntatori. Funzioni: passaggio di parametri per indirizzo. 1 Vettori Struttura astratta: Insieme di elementi dello stesso tipo, ciascuno individuato da un indice;
Problema. Vettori e matrici. Vettori. Vettori
e matrici Ver. 2.4 2010 - Claudio Fornaro - Corso di programmazione in C Problema Si vuole un programma che chieda 10 numeri dalla tastiera e li visualizzi dall ultimo al primo Soluzione attuale (con le
Università degli Studi di Napoli Parthenope. Corso di Calcolo Parallelo e Distribuito. Virginia Bellino Matr. 108/1570
Università degli Studi di Napoli Parthenope Corso di Calcolo Parallelo e Distribuito Virginia Bellino Matr. 108/1570 Virginia Bellino Progetto 1 Corso di Calcolo Parallelo e Distribuito 2 Indice Individuazione
Elaborato Shell. Elementi di architettura e sistemi operativi 2016/2017
Elaborato Shell Elementi di architettura e sistemi operativi 2016/2017 Introduzione passwd è il file di configurazione di sistema in cui sono memorizzate alcune delle informazioni relative agli account
Sistemi Web per il turismo - lezione 3 -
Sistemi Web per il turismo - lezione 3 - Software Si definisce software il complesso di comandi che fanno eseguire al computer delle operazioni. Il termine si contrappone ad hardware, che invece designa
Correttezza (prima parte)
Fondamenti di informatica Oggetti e Java (prima parte) Capitolo 16 ottobre 2015 1 Contenuti Introduzione alla correttezza dei programmi specifica di un programma correttezza di un programma verifica di
Esercizi di MatLab. Sommario Esercizi di introduzione a MatLab per il corso di Calcolo Numerico e Laboratorio, A.A
Esercizi di MatLab Sommario Esercizi di introduzione a MatLab per il corso di Calcolo Numerico e Laboratorio, AA 2017 2018 Gli esercizi sono divisi in due gruppi: fondamentali ed avanzati I primi sono
La Gestione della Memoria. Carla Binucci e Walter Didimo
La Gestione della Memoria Carla Binucci e Walter Didimo Esecuzione di programmi Java L esecuzione di un programma Java richiede: la compilazione del codice Java in bytecode Java (un linguaggio macchina
Esercitazione 11. Liste semplici
Esercitazione 11 Liste semplici Liste semplici (o lineari) Una lista semplice (o lineare) è una successione di elementi omogenei che occupano in memoria una posizione qualsiasi. Ciascun elemento contiene
Appunti su Indipendenza Lineare di Vettori
Appunti su Indipendenza Lineare di Vettori Claudia Fassino a.a. Queste dispense, relative a una parte del corso di Matematica Computazionale (Laurea in Informatica), rappresentano solo un aiuto per lo
Problema: dati i voti di tutti gli studenti di una classe determinare il voto medio della classe.
Problema: dati i voti di tutti gli studenti di una classe determinare il voto medio della classe. 1) Comprendere il problema 2) Stabilire quali sono le azioni da eseguire per risolverlo 3) Stabilire la
Tipi di dati scalari (casting e puntatori) Alessandra Giordani Lunedì 10 maggio 2010
Tipi di dati scalari (casting e puntatori) Alessandra Giordani [email protected] Lunedì 10 maggio 2010 http://disi.unitn.it/~agiordani/ I tipi di dati scalari I tipi aritmetici, i tipi enumerativi
Linguaggio C: le funzioni. Introduzione e sintassi
Dipartimento di Elettronica ed Informazione Politecnico di Milano Informatica e CAD (c.i.) - ICA Prof. Pierluigi Plebani A.A. 2008/2009 Linguaggio C: le funzioni. Introduzione e sintassi La presente dispensa
I puntatori. Un puntatore è una variabile che contiene l indirizzo di un altra variabile. puntatore
I puntatori Un puntatore è una variabile che contiene l indirizzo di un altra variabile. puntatore...... L operatore & fornisce l indirizzo di un oggetto: p = &c; assegna a p l indirizzo di c, i.e., p
SOLUZIONI DELLA PROVA SCRITTA DEL CORSO DI. NUOVO E VECCHIO ORDINAMENTO DIDATTICO 28 Settembre 2006
SOLUZIONI DELLA PROVA SCRITTA DEL CORSO DI NUOVO E VECCHIO ORDINAMENTO DIDATTICO 28 Settembre 26 MOTIVARE IN MANIERA CHIARA LE SOLUZIONI PROPOSTE A CIASCUNO DEGLI ESERCIZI SVOLTI ESERCIZIO 1 (8 punti)
COMPLESSITÀ COMPUTAZIONALE DEGLI ALGORITMI
COMPLESSITÀ COMPUTAZIONALE DEGLI ALGORITMI Fondamenti di Informatica a.a.200.2005/06 Prof. V.L. Plantamura Dott.ssa A. Angelini Confronto di algoritmi Uno stesso problema può essere risolto in modi diversi,
Esercizio 2 (punti 7) Dato il seguente programma C: #include <stdio.h> int swap(int * nome, int length);
Fondamenti di Informatica L-A (A.A. 004/005) - Ingegneria Informatica Prof.ssa Mello & Prof. Bellavista I Prova Intermedia del 11/11/004 - durata h - COMPITO B Esercizio 1 (punti 1) Una associazione di
Strutture dati e loro organizzazione. Gabriella Trucco
Strutture dati e loro organizzazione Gabriella Trucco Introduzione I linguaggi di programmazione di alto livello consentono di far riferimento a posizioni nella memoria principale tramite nomi descrittivi
Evoluzione del FORTRAN 14/03/2016. LABORATORIO DI PROGRAMMAZIONE Corso di laurea in matematica 15 IL LINGUAGGIO FORTRAN
LABORATORIO DI PROGRAMMAZIONE Corso di laurea in matematica 15 IL LINGUAGGIO FORTRAN Marco Lapegna Dipartimento di Matematica e Applicazioni Universita degli Studi di Napoli Federico II wpage.unina.it/lapegna
Esercizi di riepilogo (Fondamenti di Informatica 1 Walter Didimo)
Esercizi di riepilogo (Fondamenti di Informatica 1 Walter Didimo) Selezione di prove di esame al calcolatore Esercizio 1 (esame del 13/01/2006) La classe Matrice definisce oggetti che rappresentano matrici
Progetto Matlab N 2. Calcolo Numerico 6 CFU. Corso di Laurea in Ingegneria delle Comunicazioni 31/05/2014
Progetto Matlab N 2 Calcolo Numerico 6 CFU Corso di Laurea in Ingegneria delle Comunicazioni 31/05/2014 Procedimento 1. Scrivere una function che implementi il prodotto matrice-vettore AX con A matrice
Compitino di Laboratorio di Informatica CdL in Matematica 13/11/2007 Teoria Compito A
Matematica 13/11/2007 Teoria Compito A Domanda 1 Descrivere, eventualmente utilizzando uno schema, gli elementi funzionali di una CPU. Domanda 2 Java è un linguaggio compilato o interpretato? Motivare
Lezione 21 e 22. Valentina Ciriani ( ) Laboratorio di programmazione. Laboratorio di programmazione. Lezione 21 e 22
Lezione 21 e 22 - Allocazione dinamica delle matrici - Generazione di numeri pseudocasuali - Funzioni per misurare il tempo - Parametri del main - Classificazione delle variabili Valentina Ciriani (2005-2008)
Introduzione alla programmazione Esercizi risolti
Esercizi risolti 1 Esercizio Si determini se il diagramma di flusso rappresentato in Figura 1 è strutturato. A B C D F E Figura 1: Diagramma di flusso strutturato? Soluzione Per determinare se il diagramma
Definizione di metodi in Java
Definizione di metodi in Java Un metodo in Java definisce un operazione ad alto livello (sottoprogramma) che consente di manipolare dati e oggetti. Durante la computazione effettuata da un programma, un
Rappresentazione degli algoritmi
Rappresentazione degli algoritmi Universitá di Ferrara Ultima Modifica: 21 ottobre 2014 1 1 Diagramma di flusso Utilizzare il diagramma di flusso per rappresentare gli algoritmi che risolvono i seguenti
Fondamenti di Informatica 6. Algoritmi e pseudocodifica
Vettori e matrici #1 Fondamenti di Informatica 6. Algoritmi e pseudocodifica Corso di Laurea in Ingegneria Civile A.A. 2010-2011 1 Semestre Prof. Giovanni Pascoschi Le variabili definite come coppie
Una Libreria di Algebra Lineare per il Calcolo Scientifico
Una Libreria di Algebra Lineare per il Calcolo Scientifico Introduzione Il Lavoro di Tesi Introduzione al Metodo Ridurre l Occupazione di Memoria Metodo di Memorizzazione degli Elementi Risultati Attesi
Il Sistema Operativo
Il Sistema Operativo Il sistema operativo Con il termine sistema operativo si intende l insieme di programmi e librerie che opera direttamente sulla macchina fisica mascherandone le caratteristiche specifiche
Matrici. Matrici.h Definizione dei tipi. Un po di esercizi sulle matrici Semplici. Media difficoltà. Difficili
Matrici Un po di esercizi sulle matrici Semplici Lettura e scrittura Calcolo della trasposta Media difficoltà Calcolo del determinante Difficili Soluzione di sistemi lineari È veramente difficile? 1 Matrici.h
Complementi ed Esercizi di Informatica Teorica II
Complementi ed Esercizi di Informatica Teorica II Vincenzo Bonifaci 21 maggio 2008 4 Problemi di ottimizzazione: il Bin Packing Il problema bin packing è il seguente: dato un insieme di n oggetti di dimensioni
Gli Array. Dichiarazione di un array
Gli Array Un array rappresenta una variabile indicizzata (ovvero contenente un indice) che viene utilizzata per contenere più elementi dello stesso tipo. Ogni array ha un nome al quale viene associato
ESECUZIONE DI PROGRAMMI C SU MACCHINE REALI. Docente: Giorgio Giacinto AA 2008/2009. formalizzazione degli algoritmi in linguaggio C
Università degli Studi di Cagliari Corso di Laurea Specialistica in Ingegneria per l Ambiente ed il Territorio Corso di Laurea Specialistica in Ingegneria Civile - Strutture FONDAMENTI DI INFORMATICA 2
IL PRIMO PROGRAMMA IN C
IL PRIMO PROGRAMMA IN C LO SCOPO Si vuole scrivere un programma in linguaggio C che chieda all utente di introdurre da tastiera due numeri interi e visualizzi il valore della loro somma sul video SOLUZIONE
Esercizio 2: Algebra dei Puntatori e Puntatori a Puntatori
Esercizio 2: Algebra dei Puntatori e Puntatori a Puntatori Salvatore Mandrà 7 Ottobre 2008 1 Esercizio L esercizio prevede l implementazione di funzioni per il prodotto di una matrice per un vettore, attraverso
Alcuni strumenti per lo sviluppo di software su architetture MIMD
Alcuni strumenti per lo sviluppo di software su architetture MIMD Calcolatori MIMD Architetture SM (Shared Memory) OpenMP Architetture DM (Distributed Memory) MPI 2 MPI : Message Passing Interface MPI
Unità F1. Obiettivi. Il linguaggio C. Il linguaggio C++ Linguaggio C. Pseudolinguaggio. Primi programmi
Obiettivi Unità F1 Primi programmi Conoscere il significato di dichiarazione e definizione di variabili Conoscere i tipi di dato numerici Essere in grado di realizzare semplici algoritmi in pseudolinguaggio
Fondamenti di Informatica T-1 Modulo 2
Fondamenti di Informatica T-1 Modulo 2 Obiettivi di questa lezione 1. Valutazione in cortocircuito 2. If e if innestati 3. Switch 4. Cicli Valutazione in cortocircuito In C, le espressioni booleane sono
INTRODUZIONE ALLA PROGRAMMAZIONE AD ALTO LIVELLO IL LINGUAGGIO JAVA. Fondamenti di Informatica - D. Talia - UNICAL 1. Fondamenti di Informatica
Fondamenti di Informatica INTRODUZIONE ALLA PROGRAMMAZIONE AD ALTO LIVELLO IL LINGUAGGIO JAVA Fondamenti di Informatica - D. Talia - UNICAL 1 Fondamenti di Informatica - Programma Un programma è una formulazione
2. Algoritmi e Programmi
12 2. Algoritmi e Programmi Dato un problema, per arrivare ad un programma che lo risolva dobbiamo: individuare di cosa dispongo: gli input; definire cosa voglio ottenere: gli output; trovare un metodo
Sistemi di Elaborazione delle Informazioni
SCUOLA DI MEDICINA E CHIRURGIA Università degli Studi di Napoli Federico II Corso di Sistemi di Elaborazione delle Informazioni Dott. Francesco Rossi a.a. 2016/2017 1 I linguaggi di programmazione e gli
3. Matrici e algebra lineare in MATLAB
3. Matrici e algebra lineare in MATLAB Riferimenti bibliografici Getting Started with MATLAB, Version 7, The MathWorks, www.mathworks.com (Capitolo 2) Mathematics, Version 7, The MathWorks, www.mathworks.com
ACSO Programmazione di Sistema e Concorrente
ACSO Programmazione di Sistema e Concorrente P2 Modello Thread 2/12/2015 programma e parallelismo il tipo di parallelismo dipende dal grado di cooperazione (scambio di informazione) necessario tra attività
Il sistema C è formato dal linguaggio C, dal preprocessore, dal compilatore, dalle librerie e da altri strumenti di supporto.
Sistema C e organizzazione del codice Il sistema C è formato dal linguaggio C, dal preprocessore, dal compilatore, dalle librerie e da altri strumenti di supporto. Un programma C è costituito da un insieme
Le basi del linguaggio Java
Le basi del linguaggio Java Compilazione e interpretazione Quando si compila il codice sorgente scritto in Java, il compilatore genera il codice compilato, chiamato bytecode. È un codice generato per una
VERIFICA DI UNA RETE DI DISTRIBUZIONE INTERNA
UNIVERSITÀ DEGLI STUDI DI NAPOLI FEDERICO II Dipartimento di Ingegneria Civile, Edile ed Ambientale VERIFICA DI UNA RETE DI DISTRIBUZIONE INTERNA mediante programma realizzato in ambiente Office Excel
SIMULAZIONE DELLA PROVA INTERMEDIA DEL CORSO DI CALCOLATORI ELETTRONICI
SIMULAZIONE DELLA PROVA INTERMEDIA DEL CORSO DI CALCOLATORI ELETTRONICI ESERCIZIO 1 (10 Punti) Si implementi una rete sequenziale la cui uscita valga Z=1 solo quando viene riconosciuta la sequenza in ingresso
Non ci sono vincoli sul tipo degli elementi di un vettore Possiamo dunque avere anche vettori di
ARRAY DI PUNTATORI Non ci sono vincoli sul tipo degli elementi di un vettore Possiamo dunque avere anche vettori di puntatori Ad esempio: char * stringhe[4]; definisce un vettore di 4 puntatori a carattere
15 Riepilogo di esercizi in MATLAB
15.1 Esercizi Esercizio 15.1 (TdE 2014) Si consideri l array definito in MATLAB e chiamato dati. Tale array contiene le informazioni riguardanti le precipitazioni atmosferiche registrate da una stazione
