OpenMP Um método de paralelização para as linguagens Fortran, C, C++ para shared memory systems. Directivas para o compilador Threads Biblioteca de rotinas Variáveis de ambiente entidade que pode executar de f o r m a i n d e p e n d e n t e u m conjunto de instruções B. Chapman, G. Jost, R. van der Pas Using OpenMP, MIT Press 2008
OpenMP - II Multiplicação Matriz-Vector M ik V k = A i k i Paralelização segundo i
PROGRAM matriz_vector END PROGRAM matriz_vector IMPLICIT NONE INTEGER n, m, memstat REAL start, finish DOUBLE PRECISION, DIMENSION (:), ALLOCATABLE :: vec, a DOUBLE PRECISION, DIMENSION (:,:), ALLOCATABLE :: mat PRINT *, " M(n,m) V(m) = A(m) " PRINT *, " Valores para m, n >>>" READ(*,*) n, m SUBROUTINE mat_vect( n, m, mat, vec, x ) IMPLICIT NONE INTEGER, INTENT(IN) :: n, m DOUBLE PRECISION, DIMENSION (n,m), INTENT(IN) :: mat ALLOCATE( mat(n,m), STAT=memstat ) IF ( memstat /= 0) STOP " Erro na alocação de M " ALLOCATE( vec(m), STAT=memstat ) IF ( memstat /= 0) STOP " Erro na alocação de V " ALLOCATE( a(m), STAT=memstat ) IF ( memstat /= 0) STOP " Erro na alocação de A " PRINT *, " Inicialização da matriz M e vector V" mat = 1 vec = 1 PRINT *, " M * V" CALL CPU_TIME(start) CALL mat_vect( n, m, mat, vec, a ) CALL CPU_TIME(finish) PRINT *, " Tempo Mat*Vec = ", finish-start, seg PRINT *, " Finaliza" IF ( ALLOCATED(mat) ) DEALLOCATE( mat, STAT=memstat ) IF ( ALLOCATED(vec) ) DEALLOCATE( vec, STAT=memstat ) IF ( ALLOCATED(a) ) DEALLOCATE( a, STAT=memstat ) DOUBLE PRECISION, DIMENSION (m), INTENT(IN) :: vec DOUBLE PRECISION, DIMENSION (m), INTENT(INOUT) :: x!... Variáveis Locais INTEGER i, j DO i = 1, n x(i) = 0 DO j = 1, m x(i) = x(i) + mat(i,j)*vec(j) END SUBROUTINE mat_vect
SUBROUTINE mat_vect( n, m, mat, vec, x ) IMPLICIT NONE INTEGER, INTENT(IN) :: n, m DOUBLE PRECISION, DIMENSION (n,m), INTENT(IN) :: mat DOUBLE PRECISION, DIMENSION (m), INTENT(IN) :: vec #pragma omp parallel for default(none) \ DOUBLE PRECISION, DIMENSION (m), INTENT(INOUT) :: x shared(n,m,mat,vec,x) private(i,j)!... Variáveis Locais INTEGER i, j!$omp PARALLEL DO DEFAULT(none) & for( i = 1; i <= n; i++) { x(i) = 0; for( j = 1; j <= m; j++) x(i) = x(i) + mat(i,j)*vec(j) }!$OMP SHARED(n,m,mat,vec,x) PRIVATE(i,j) DO i = 1, n x(i) = 0 DO j = 1, m x(i) = x(i) + mat(i,j)*vec(j)!$omp END PARALLEL DO END SUBROUTINE mat_vect
!$OMP PARALLEL DO DEFAULT(none)!$OMP SHARED(n,m,mat,vec,x) PRIVATE(i,j) DO i = 1, n x(i) = 0!$OMP PARALLEL DO DEFAULT(none) &!$OMP SHARED(x,mat,vec,i) PRIVATE(j) DO j = 1, m x(i) = x(i) + mat(i,j)*vec(j)!$omp END PARALLEL DO!$OMP END PARALLEL DO &!$OMP PARALLEL DO DEFAULT(none)!$OMP SHARED(n,m,mat,vec,x) PRIVATE(i) DO i = 1, n x(i) = SUM(mat(i,:)*vec(:))!$OMP END PARALLEL DO &
Tempos Execução (3000 x 3000): Série: (somátorios) 0.175 (SUM) 0.126 Paralelo (2 Threads): (somatórios) 0.196 (2 ciclos) 0.219 (SUM) 0.136
PROGRAM pi_s USE omp_lib IMPLICIT NONE INTEGER n, i, n_threads REAL start, finish DOUBLE PRECISION w, s, x, pi DOUBLE PRECISION, PARAMETER :: ZERO = 0, ONE = 1, HALF = 0.5 DOUBLE PRECISION, EXTERNAL :: f FUNCTION f(x) IMPLICIT NONE DOUBLE PRECISION, INTENT(IN) :: x DOUBLE PRECISION f!... DOUBLE PRECISION, PARAMETER :: FOUR = 4, ONE = 1 f = FOUR / (ONE + x*x) END FUNCTION f READ(*,*) n n_threads = 1 pi = ZERO w = ONE/DBLE(n) CALL CPU_TIME(start)!$OMP PARALLEL PRIVATE(x,s)!$ n_threads = omp_get_num_threads() s = ZERO!$OMP DO DO i = 1, n x = w*( DBLE(i) - HALF) s = s + f(x)!$omp!$omp CRITICAL pi = pi + w*s!$omp END CRITICAL Cálculo Pi!$OMP END PARALLEL CALL CPU_TIME(finish) PRINT *, n, pi PRINT *, " T Exec. = ", finish-start PRINT *, " # Threads = ", n_threads END PROGRAM pi_s
!$OMP PARALLEL PRIVATE(x,s)!$ n_threads = omp_get_num_threads() s = ZERO!$OMP DO DO i = 1, n x = w*( DBLE(i) - HALF) s = s + f(x)!$omp!$omp CRITICAL pi = pi + w*s!$omp END CRITICAL!$OMP END PARALLEL!$OMP PARALLEL DEFAULT(none) &!$OMP SHARED(pi,w,n,n_threads) PRIVATE(i,x,s)!$ n_threads = omp_get_num_threads() s = ZERO!$OMP DO DO i = 1, n x = w*( DBLE(i) - HALF) s = s + f(x)!$omp!$omp CRITICAL pi = pi + w*s!$omp END CRITICAL!$OMP END PARALLEL!$OMP PARALLEL DEFAULT(none) &!$OMP SHARED(w,n,n_threads) PRIVATE(i,x,s), reduction(+:pi)!$ n_threads = omp_get_num_threads() s = ZERO pi = ZERO!$OMP DO DO i = 1, n x = w*( DBLE(i) - HALF) s = s + f(x)!$omp pi = pi + w*s!$omp END PARALLEL
Problema du dt = f(t, u) u(t = 0) = u 0 Procurar solução para 0 t T du dt (t) u(t + t) u(t) t u(t + t) u(t) + tf(t, u(t)) Data dependency - não há forma de paralelizar
Método de 2ª ordem: du dt = f(t, u(t)) u(t + t) =u(t)+ tu (t)+ 2 2 u (t) u (t + t) =u (t)+ tu (t)+ 2 2 u (t) tu (t) =u (t + t) u (t)++o( t 2 ) tu (t) =u (t) u (t t)++o( t 2 ) u(t + t) =u(t)+ tf(t, u(t)) + t [f(t, u(t)) f(t t, u(t t)] 2 u(t + t) =u(t)+ t 2 [3f(t, u(t)) f(t t, u(t t)] + O( t3 ) u(t + t) =u(t)+ t 2 [f(t, u(t)) + f(t, 2u(t) u(t t)] + O( t2 )
Método de 2ª ordem u n+1 = u((n + 1) t) =u n + t n+1 t n 2 [ ] f(t n,u n )+f(t n+1, 2u n u n+1 ) Cálculos Independentes Considere f(t, u) =u u 0, u 1 = u 0 + t, u n+1 = Au n + Bu n 1, A = 1 + 3 t 2, B = t 2
Resolução de Sistema Linear 1 0 0 0 0 1 1 0 0 0 B A 1 0 0 0 B A 1 0..... u 0 u 1 u 2 u 3. = 0 t 0 0. (I + A)u = B u = I I + A B = B AB + A2 B
Ler B u = B B = AB Oportunidades de Paralelização Multiplicação Matriz Vector Soma Vectores Norma Vector u = u + B B Erro Sim Não Stop
Escreva o programa para resolver o problema de condições formulado usando OpenMP e efectue medidas do speedup=( Tempo Execução Paralela)/(Tempo Execução Série) e da eficiência paralela = speedup/thread. Ao executar o programa considere T = 1 e utilize valores do intervalo de tempo de 0.01 e 0.001. Compare a solução numérica com a solução exacta obtida por integração directa da equação diferencial.