| subroutine blocchi(nstart,nend,nprocs,mype,istart,iend)
integer nstart, nend, nprocs, mype, istart, iend integer i1, i2, i3 i1 = nend - nstart + 1 i2 = i1/nprocs i3 = mod(i1,nprocs) istart = mype*i2 + nstart + min(mype,i3) iend = istart + i2 - 1 if(i3.gt.mype) iend = iend + 1 return end |
dove:
| ITERAZIONE | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| PROCESSO | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 2 | 2 | 2 | 3 | 3 | 3 |
Questa ridistribuzione corrisponde ad esprimere il numero di iterazioni i1 come i1=i3*(i2+1)+(nprocs-i3)*i2.
Ovviamente sono possibili anche altri modi di
realizzare una ridistribuzione a blocchi. Un altro esempio, meno efficiente,
è dato dalla seguente subroutine in cui può accadere che
qualche processo rimanga senza lavoro:
| subroutine blocchi2(nstart,nend,nprocs,mype,istart,iend)
integer nstart, nend, nprocs, mype, istart, iend integer i1 i1 = 1 + (nend - nstart)/nprocs istart = min(mype*i1 + nstart, nend + 1) iend = min(istart + i1 - 1, nend) return end |
Con questa subroutine la ridistribuzione dell'esempio
precedente diviene:
| ITERAZIONE | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| PROCESSO | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 2 | 2 | 2 | 2 | 3 | 3 |
Prendiamo in cosiderazione ora il seguente esempio
di codice seriale da parallelizzare:
|
program esempio7seriale
parameter (n=100) integer i, a, sum dimension a(n)
do i=1,n
|
La versione parallelizzata con le iterazioni ridistribuite
a blocchi è la seguente:
|
program esempio7
include 'mpif.h' parameter (n=100) integer nprocs, mype, ierr integer istart, iend integer i, a, sum, ssum dimension a(n)
call MPI_INIT(ierr)
do i=istart,iend
call MPI_REDUCE(sum,ssum,1,MPI_INTEGER,MPI_SUM,
if(mype.eq.0) then
subroutine blocchi(nstart,nend,nprocs,mype,istart,iend)
|