Indietro | Home | Avanti

Introduzione | Cap.1 | Cap.2 | Cap.3 | Cap.4 | Cap.5 | Appendice | Bibliografia

CAPITOLO 5

Versione parallela del programma Contour

L' approccio piu' immediato per lo sviluppo di algoritmi paralleli e' quello di partire da algoritmi sequenziali, individuare gli eventuali passi indipendenti tra loro e arrivare a versioni parallele. In questo stesso ambito, due sono le possibili vie da seguire. Si puo' dividere il programma, per quanto possibile in tante attivita' parallele (parallelismo fine-grain);oppure scomporlo nelle sue componenti principali (parallelismo course-grain). Per determinare quale dei due approcci sia il migliore bisogna tener presente che l' obiettivo del calcolo parallelo e' l' incremento delle prestazioni rispetto ai programmi scalari. Dal momento che il parallelismo fine-grain ha bisogno di un maggiore overhead di comunicazione, potrebbe capitare che una soluzione fine-grain diventi piu' lenta di una soluzione sequenziale.

FIG.5.1- PARALLELISMO FINE E COURSE-GRAIN.

Per il programma si e' scelta un' implementazione course-grain. Piu' precisamente, dal momento che, ogni rettangolo della griglia e' indipendente dagli altri, si e' scelto di assegnare a processori diversi rettangoli diversi. La griglia viene quindi divisa in parti, tante quante il numero dei processori e ognuno di essi si occupa di tracciare le linee di livello nella parte assegnatagli.

La Fig.5.2 illustra una situazione tipica. La griglia rappresenta la matrice dei punti dati mentre le parti colorate rappresentano le zone assegnate ai processori. Dal momento che il numero dei rettangoli che formano la griglia non e', in generale, divisibile esattamente per il numero di processori, alcuni processori riceveranno un carico di lavoro maggiore rispetto ad altri. La figura riporta anche la percentuale di lavoro assegnato ad ogni processore. La Fig.5.3 riporta invece il caso ideale in cui il numero di rettangoli da processare e' diviso esattamente dal numero di processori. In tal caso infatti non ci sono rettangoli rimanenti e tutti i processori eseguono la stessa quantita' di lavoro.

L' implementazione

Analizziamo adesso piu' da vicino i punti piu' importanti del programma. Come tutti i programmi che girano sotto Express e' necessario dapprima inizializzare alcune strutture necessarie al sistema. Questo viene fatto dichiarando in un blocco COMMON delle variabili opportune e chiamando la funzione KXINIT.

- - - - - - - - - - - -

COMMON /xpress/nocare,norder,nonode,ihost,ialnod,ialprc

INTEGER . . . . . ,nprocs(2)

DATA nprocs/2,2/

- - - - - - - - - - - -

EXTERNAL kxinit

CALL kxinit

- - - - - - - - - - - -

Con la chiamate alla funzione KXPARA si rendono disponibili al programma le informazioni sull' ambiente.


INTEGER env(4), . . . . . . .

- - - - - - - - - - - -

CALL kxpara(env)

- - - - - - - - - - - -

Piu' precisamente chiamando la funzione con un vettore di interi (env) come argomento, essa restituisce, il numero di processori con cui e' stato lanciato il programma in env(2) ed il NIP (numero identificativo del processore) dei processori allocati in env(1). Cio' permette una allocazione dinamica dei compiti e quindi permette al programma di girare su un numero qualunque di processori. La conseguenza piu' importante e' che l' applicazione girera' tanto piu' veloce quanto piu' alto e' il numero di processori disponibili.

- - - - - - - - - - - - -

NumeroProcessori = env(2)

NumeroRetttangoli = xdim1 * ydim1

RettangoliPerProcessore =NumeroRettangoli / NumeroProcessori

RettangoliRimanenti = mod(NumeroRettangoli,NumeroProcessori)

- - - - - - - - - - - - -

C Costruzione di linee di livello per punti distribuiti regolarmente

C ai nodi di una griglia rettangolare

PROGRAM CONTOUR

INTEGER xdim,ydim,xdim1,ydim1

CHARACTER*8 cs(15)

REAL c(15)

COMMON /grid/grid(0:100,0:100)

COMMON /h/hx,hy

COMMON /origin/xx,yy

INTEGER NumProc,NumRet,RePrPr

INTEGER RetRim,process

COMMON /xpress/nocare,norder,nonode,ihost,ialnod,ialprc

INTEGER env(4),gbuffer(8192),nprocs(2)

DATA nprocs/2,2/

EXTERNAL kxinit

CALL kxinit

CALL kxpara(env)

CALL ksingl(6)

WRITE(*,*)'dominio in cui campionare la funzione:'

WRITE(*,*)'intervallo delle ascisse (a,b)'

READ(*,*) xx,xx1

WRITE(*,*)'intervallo delle ordinate (c,d)'

READ(*,*) yy,yy1

IF (xx .GE. xx1 .OR. yy .GE. yy1) STOP

WRITE(*,*)'num. punti sui lati della griglia'

READ(*,*) xdim

ydim=xdim

WRITE(*,*)'numero di linee di livello (max 14)'

READ(*,*) numlin

WRITE(*,*)'vettore delle linee di livello'

DO 5 i=1,numlin

READ(*,23) c(i),cs(i)

5 CONTINUE

23 FORMAT(f9.3,t1,a)

ydim1 = ydim - 1

xdim1 = xdim - 1

hx = (xx1 - xx) / xdim1

hy = (yy1 - yy) / ydim1

istat=kopenp(gbuffer,8192)

IF (istat .LT. 0) THEN

WRITE(*,*)'chiamata grafica fallita'

STOP

ENDIF

C chiama la sub che si occupa della definizione di un vettore per

C i colori delle linee di livello e della costruzione della legenda

CALL LEGENDA(numlin, cs)

C crea una viewport al centro dello schermo che conterra' il

C disegno e assegna ad essa il sistema di coordinate del grafico

ivp=kvport(.3,.3,.8,.8)

CALL kortho(xx,yy,xx1,yy1,0)

CALL krainb(0,15)

CALL kcolor(1)

C Costruisce una reticolazione del dominio in base ai dati forniti.

C i valori ai nodi della griglia sono forniti dalla funzione FUNZ

DO 7 j=0,ydim1

y = yy + hy * j

DO 7 i=0,xdim1

x = xx + hx * i

grid(j, i) = funz(x,y)

7 CONTINUE

NumProc = env(2)

NumRet = xdim1 * ydim1

RePrPr =NumRet / NumProc

RetRim = mod(NumRet,NumProc)

process=env(1)

i = (process * RePrPr) / xdim1

j = mod((process * RePrPr),xdim1)

kk = 0

DO 10 k = 0,RePrPr - 1

IF ((j + kk) .ge. xdim1) THEN

i = i + 1

j = 0

kk = 0

ENDIF

CALL rettangolo(j+kk,i,c,numlin)

kk = kk + 1

10 CONTINUE

CALL kusend

IF (.NOT.(RetRim .EQ. 0)) THEN

IF (process .LT. RetRim) THEN

i = (NumProc * RePrPr + process) / xdim1

j = mod((NumProc * RePrPr + process),xdim1)

CALL rettangolo(j,i,c,numlin)

ENDIF

ENDIF

CALL kusend

DO 11 i=1,1000000

11 CONTINUE

CALL kclosp

END

C questa e' la definizione della funzione utilizzata per la

C costruzione della griglia

REAL FUNCTION funz (x, y)

C funz = x + y

C funz = 3 / 2 * (COS(3 / 5 * (y - 1)) + 5 / 4) / (1 + ((x - 4)

C * / 3) ** 2)

C funz = ABS(x + y)

funz = SIN(x ** 2) + COS(y ** 2) + SIN(x)

C funz = TAN(y - x) + 1

C funz = 8 / 3.14 * EXP(-8 * (x * x + y * y))

C funz = 9 * (3 / 4 * EXP(-(x - 3) ** 2 - (y - 3) ** 2) / 4) +

C * EXP(-(x / 7) ** 2 - (y / 10) - 1 / 5 * EXP(-(x - 5) ** 2 -

C * (y - 8) ** 2) + 1 / 2 * EXP((-(x - 8) ** 2 - (y - 4) ** 2) / 4))

END

C Calcola per interpolazione lineare l'ascissa del punto

C di ordinata c (linea di livello)

REAL FUNCTION interp(x1, z1, x2, z2, c)

IF ((z2 - z1).EQ.0) THEN

interp = 0

ELSE

interp = (c - z1) * (x2 - x1) / (z2 - z1)

END IF

END

C questa sub determina se la linea di livello specificata

C interseca questo lato e la posizione del punto.

SUBROUTINE lato (i, j, m, n, c, x, y, flag)

REAL interp

LOGICAL flag

COMMON /grid/grid(0:100,0:100)

COMMON /h/hx,hy

flag=.FALSE.

IF ((grid(i, j) .LE. c .AND. c .LE. grid(m, n)) .OR. (grid(m, n)

* .LE. c .AND. c .LE. grid(i, j))) THEN

x = j * hx + interp(j * hx, grid(i, j), n * hx, grid(m, n), c)

y = i * hy + interp(i * hy, grid(i, j), m * hy, grid(m, n), c)

flag =.TRUE.

END IF

END

C Costruisce la legenda.

C n e' il numero di linee di livello e c il vettore delle linee

SUBROUTINE legenda (n, cs)

character*8 cs(n)

ivp1=kvport(.1,.1,.2,.8)

CALL kspace(0.,0.,50.,100.)

a = 0.

DO 22 i=1,n

CALL kbox(0.,a,10.,a+10,i,0)

CALL kdotex(cs(i),25.,a+5,0.,1,1)

a = a + 16

22 CONTINUE

CALL kusend

END

C questa sub processa il rettangolino della griglia individuato

C dagli indici i e j.

C c vettore delle linee di livello

C numlin numero delle linee di livello

SUBROUTINE rettangolo (i, j, c, numlin)

REAL x(4), y(4),c(numlin)

LOGICAL flag(1:4)

COMMON /origin/xx,yy

COMMON /h/hx,hy

CALL kcolor(1)

CALL kbox(xx+j*hx,yy+i*hy,xx+(j+1)*hx,yy+(i+1)*hy,0,1)

DO 25 k=1,numlin

CALL lato(i, j, i, j + 1, c(k), x(1), y(1), flag(1))

CALL lato(i, j, i + 1, j, c(k), x(2), y(2), flag(2))

CALL lato(i + 1, j, i + 1, j + 1, c(k), x(3), y(3), flag(3))

CALL lato(i + 1, j + 1, i, j + 1, c(k), x(4), y(4), flag(4))

DO 30 ii=1,4

IF (flag(ii)) THEN

x1 = x(ii)

y1 = y(ii)

DO 35 jj=ii+1,4

IF (flag(jj)) THEN

x2 = x(jj)

y2 = y(jj)

END IF

35 CONTINUE

CALL kcolor(k)

CALL kmove(xx+x1,yy+y1)

CALL kcont(xx+x2,yy+y2)

END IF

30 CONTINUE

flag(1) =.FALSE.

flag(2) =.FALSE.

flag(3) =.FALSE.

flag(4) =.FALSE.

25 CONTINUE

END

Analisi delle performances

L' obiettivo del calcolo parallelo e' di ottenere una accellerazione degli algoritmi sfruttando al meglio le risorse dell' hardware. Affiche' l' utente sia capace di redigere algoritmi efficienti, egli deve essere capace di effettuare un' analisi accurata (profiling) dell' algoritmo per verificare la presenza di "colli di bottiglia" dovuti ad una poco razionale progettazione dell' algoritmo.

Il profiling di algoritmi paralleli e' molto piu' laborioso di quello di algoritmi sequenziali dal momento che entrano in gioco piu' fattori che influenzano le loro prestazioni. Il piu' ovvio, per un' architettura message-passing, e' la quantita' di tempo speso nello spedire e ricevere messaggi.

L' Express di Parasoft mette a disposizione dell' utente tre tool che permettono un' accurata analisi:

1) Execution Profiling;

2) Event Profiling;

3) Communication Profiling;

Per tutti e tre vengono fornite delle funzioni che ne permettono l' attivazione, la disattivazione e l' analisi. I tool descritti sono del tipo "post-mortem", cio' significa che i dati, durante l' esecuzione del programma, vengono accumulati in appositi buffers ed esaminati ad esecuzione terminata. Questo essenzialmente per due ragioni:

- la lentezza dell' I/O dei sistemi parralleli, sopratutto se paragonata alla grande potenza di calcolo di questi sistemi;

- la difficolta di analizzare la grandee mole di dati in tempo reale durante l' esecuzione;

Profilo dell' esecuzione

Il profilo dell' esecuzione riporta, per ogni nodo, il nome di tutte le funzioni o subroutine chiamate , il tempo di esecuzione di ciascuna funzione ed il numero di volte in cui questa e' stata invocata dal nodo, insieme ad una stima del tempo speso in stato "idle" (attesa).

Le funzioni che gestiscono il profilo dell' esecuzione sono:

- KXPINQ();

- KXPINI(buffer,buflen,f_start,scale);

- KXPON();

- KXPOFF();

La funzione KXPINQ() serve a controllare se il programma e' stato lanciato con lo switch -mx che attiva il profiling. Essa restituisce 1 se lo switch e' presente, zero altrimenti.

Tramite la KXPINI si specifica il buffer in cui immagazzinare i dati del profilo, la funzione da cui cominciare l' analisi, mentre il terzo parametro indica il numero di indirizzi da mappare per l' analisi statistica.

Le funzioni KXPON e KXPOFF rispettivamente attivano e disattivano il profilo inizializzato con la chiamata a KXPINI.

Un esempio del loro utilizzo e' il seguente:

C Set up dell' execution profiler

INTEGER PBUB(32768)

EXTERNAL KXINIT

- - - - - - - - - - - -

ISTX=KXPINQ()

IF (ISTX .NE. 0) THEN

CALL KXPINI(PBUF,32768,KXINIT,8192)

CALL KXPON

ENDIF

- - - - - - - - - - - -

C chiusura dell' execution profiler

IF (ISTX .NE. 0) CALL KXPOFF


Una volta ottenuti i dati questi possono essere analizzati mediante il comando xtool che apre il file "xprof.out" generato dal profiler. Questo file contiene delle tabelle, una per ogni nodo, che riportano tutte le funzioni attivate e le percentuali di tempo speso nel compiere lavoro utile e tempo speso in stato di attesa (idle).

Profilo delle comunicazioni

Le comunicazioni tra processori hanno un ruolo importante nell' esecuzione di un programma, in quanto esse influenzano il tempo totale di elaborazione. Eseguire il profilo delle comunicazioni puo' aiutare a decidere la topologia del network da utilizzare.

Le funzioni che gestiscono il profilo delle comunicazioni sono:

- KCPINQ();

- KCPON();

- KCPOFF();

La funzione KCPINQ() serve a controllare se il programma e' stato lanciato con lo switch -mc che attiva il profiling. Essa restituisce 1 se lo switch e' presente, zero altrimenti.

Le funzioni KCPON e KCPOFF rispettivamente attivano e disattivano il profilo.

Un esempio del loro utilizzo e' il seguente:

C Set up del communication profiler

ISTC=KCPINQ()

IF (ISTC .NE. 0) CALL KCPON

- - - - - - - - - - - -

C chiusura del comunication profiler

IF (ISTC .NE. 0) CALL KCPOFF


I dati vengono immagazzinati nel file "cprof.out" generato dal profiler. Questo file contiene delle tabelle, una per ogni nodo, che riportano il tempo speso nelle comunicazioni tra i nodi, il tempo di I/O ed il tempo speso in calcolo.

Node 0

===========

Internode Communication : 0.00 milliseconds

I/O Communication : 3432.90 milliseconds

Calculation : 12520.45 milliseconds

Profilo dell' evento

Per effettuare l' analisi di singole porzioni di codice, si puo' invece utilizzare il profilo dell' evento. Tramite le routines:

- KEPINQ();

- KEPINI(buf,buflen,log_buf,lunl>);

- KEPON;

- KEPOFF;

l' utente puo' selezionare una parte del codice da analizzare. La KEPINI alloca due buffers destinati a contenere i dati del profilo. L' ampiezza di tali buffers deve essere sufficientemente ampia per evitare che alcuni dati vengano scartati, col risultato di invalidare tutta la procedura. La KEPINQ controlla lo stato dello switch -me sulla riga di comando del Cubix. Le KEPON e KEPOFF rispettivamente attivano e disattivano il profilo.

Il profilo dell' evento fornisce un meccanismo per analizzare il codice piu' selettivamente. Per far cio' si utilizzano i "toggles", particolari strutture con le quali si seleziona un segmento di codice. Le routine che permettono il loro uso sono:

- KEPTGI(toggle, label);

- KEPTOG(toggle);

La prima serve ad inizializzare le strutture toggle e ad assegnare una etichetta all'evento che poi comparira' nel file di output del profilo. La seconda serve a definire la parte di codice da analizzare. Essa va infatti inserita prima e dopo l'evento.

Il comando che serve ad analizzare i dati del profilo accumulati nei buffers e' etool. Esso apre il file "eprof.out" generato dal profilo e riporta un' output del tipo:

Node 0

=========

| label | calls | total sec | average | variance |

|--------------------------------------------------------------------------|

| processo rett. riman | 0 | 0.000 | N/A | N/A |

| processo rettangolo | 9 | 0.016 | 0.002 | 0.001 |

La porzione di codice che segue riporta, invece, la definizione delle strutture e dell'evento utilizzato per il profilo del programma Contour. L' evento studiato e' il processo dei rettangoli che formano la griglia. Le tabelle che seguono riportano, per ogni nodo, il numero di volte in cui la subroutine e' stata chiamata ed il tempo totale e medio impiegato.

C Variabili utilizzate per l'analisi del profilo

INTEGER LABBUF(256), LOGBUF(1024)

INTEGER TOGGLE1(20),TOGGLE2(20)

- - - - - - - - - - - - - - -

C Set up the event profiler.

CALL KEPINI(LABBUF, 4*256, LOGBUF, 4*1024)

CALL KEPTGI(TOGGLE1, 'processo rettangolo ')

CALL KEPTGI(TOGGLE2,'processo rettang. rimanenti ')

ISTE = KEPINQ()

IF(ISTE.NE.0) CALL KEPON

C

- - - - - - - - - - - - - - - - - - - -

CALL KEPTOG(toggle1)

CALL RETTANGOLO(J+KK,I,C,NUMLIN)

CALL KEPTOG(TOGGLE1)

C Se ci sono rettangoli rimanenti....

IF (.NOT.(RETRIM .EQ. 0)) THEN

CALL KEPTOG(TOGGLE2)

CALL RETTANGOLO(J,I,C,NUMLIN)

CALL KEPTOG(TOGGLE2)

- - - - - - - - - - - - - - - - -

C chiusura dell'event profiler

IF (ISTE .NE. 0) CALL KEPOFF


Ctool Version 3.1 -- Copyright (C) 1991 ParaSoft

Node 0

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3432.90 milliseconds

Calculation : 12520.45 milliseconds


Node 1

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3429.31 milliseconds

Calculation : 12516.86 milliseconds


Node 2

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3430.66 milliseconds

Calculation : 12515.46 milliseconds


Node 3

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3431.62 milliseconds

Calculation : 12514.37 milliseconds


Node 4

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3435.52 milliseconds

Calculation : 12510.40 milliseconds


Node 5

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3438.21 milliseconds

Calculation : 12508.16 milliseconds


Node 6

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3436.99 milliseconds

Calculation : 12509.38 milliseconds


Node 7

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3428.29 milliseconds

Calculation : 12517.70 milliseconds


Node 8

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3423.30 milliseconds

Calculation : 12522.69 milliseconds

Ctool Version 3.1 -- Copyright (C) 1991 ParaSoft

Node 0

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3295.87 milliseconds

Calculation : 13616.83 milliseconds


Node 1

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3296.38 milliseconds

Calculation : 13608.64 milliseconds


Node 2

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3296.83 milliseconds

Calculation : 13608.45 milliseconds


Node 3

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3297.92 milliseconds

Calculation : 13606.98 milliseconds


Node 4

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3301.63 milliseconds

Calculation : 13604.03 milliseconds


Node 5

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3304.45 milliseconds

Calculation : 13600.38 milliseconds


Node 6

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3297.34 milliseconds

Calculation : 13608.06 milliseconds


Node 7

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3284.35 milliseconds

Calculation : 13620.42 milliseconds

Ctool Version 3.1 -- Copyright (C) 1991 ParaSoft

Node 0

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3188.16 milliseconds

Calculation : 12840.77 milliseconds


Node 1

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3187.97 milliseconds

Calculation : 12834.37 milliseconds


Node 2

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3188.74 milliseconds

Calculation : 12832.83 milliseconds


Node 3

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3188.93 milliseconds

Calculation : 12833.28 milliseconds


Node 4

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3198.59 milliseconds

Calculation : 12823.17 milliseconds


Node 5

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3198.59 milliseconds

Calculation : 12823.87 milliseconds


Node 6

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3182.21 milliseconds

Calculation : 12839.55 milliseconds

Ctool Version 3.1 -- Copyright (C) 1991 ParaSoft

Node 0

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3072.13 milliseconds

Calculation : 14860.03 milliseconds


Node 1

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3069.18 milliseconds

Calculation : 14856.13 milliseconds


Node 2

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3074.75 milliseconds

Calculation : 14849.79 milliseconds


Node 3

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3081.34 milliseconds

Calculation : 14844.16 milliseconds


Node 4

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3082.50 milliseconds

Calculation : 14842.50 milliseconds


Node 5

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 3063.62 milliseconds

Calculation : 14862.21 milliseconds

Ctool Version 3.1 -- Copyright (C) 1991 ParaSoft

Node 0

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2955.78 milliseconds

Calculation : 14083.46 milliseconds


Node 1

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2965.57 milliseconds

Calculation : 14066.30 milliseconds


Node 2

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2962.94 milliseconds

Calculation : 14068.99 milliseconds


Node 3

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2970.24 milliseconds

Calculation : 14061.63 milliseconds


Node 4

===========

Internode Communication *: 0.00 milliseconds

I/O Communication : 2948.48 milliseconds

Calculation : 14083.58 milliseconds

Ctool Version 3.1 -- Copyright (C) 1991 ParaSoft

Node 0

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2829.50 milliseconds

Calculation : 13232.13 milliseconds


Node 1

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2831.23 milliseconds

Calculation : 13222.78 milliseconds


Node 2

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2842.88 milliseconds

Calculation : 13211.01 milliseconds


Node 3

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2818.43 milliseconds

Calculation : 13235.52 milliseconds

Ctool Version 3.1 -- Copyright (C) 1991 ParaSoft

Node 0

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2721.79 milliseconds

Calculation : 12187.90 milliseconds


Node 1

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2733.06 milliseconds

Calculation : 12169.28 milliseconds


Node 2

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2716.74 milliseconds

Calculation : 12185.73 milliseconds

Ctool Version 3.1 -- Copyright (C) 1991 ParaSoft

Node 0

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2561.73 milliseconds

Calculation : 13817.98 milliseconds


Node 1

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2561.47 milliseconds

Calculation : 13811.14 milliseconds

Ctool Version 3.1 -- Copyright (C) 1991 ParaSoft

Node 0

===========

Internode Communication* : 0.00 milliseconds

I/O Communication : 2447.23 milliseconds

Calculation : 11948.22 milliseconds

* Da notare la completa assenza di comunicazioni tra i nodi.

Le figure che seguono riportano graficamente i risultati del profiling esposti in forma tabellare nelle pagine precedenti. Esse indicano il comportamento della velocita' (fig.5.4), speedup (fig.5.5) ed efficienza (fig.5.6) al crescere del numero di processori.

La fig.5.7 rappresenta invece una estrapolazione dei dati forniti dalle varie prove effettuate. Facendo la media dei risultati ottenuti utilizzando differenti funzioni, domini e numero di linee, la figura indica un comportamento generale a cui "tendono" gli algoritmi paralleli per il tracciamento di curve di livello. Il risultato pressoche' ideale ottenuto e' giustificato dal fatto che non sono necessarie comunicazioni tra i processori. Infatti dal momento che la funzione dell' algoritmo e' tracciare le curve, ogni processore puo' spedire i risultati delle proprie elaborazioni al dispositivo grafico appena disponibili. In altre parole l' attivita' dei processori e' completamente indipendente. Cio' non e' sempre vero per gli algoritmi paralleli, in cui, in generale, i risultati parziali dell' attivita' dei processori devono essere ricombinati per giungere alla soluzione finale.


Indietro | Home | Avanti

Introduzione | Cap.1 | Cap.2 | Cap.3 | Cap.4 | Cap.5 | Appendice | Bibliografia