2017-08-04 3 views
0

Ceci est mon code, je veux le rendre parallèle avec OpenMP. J'ai une boucle principale pour faire des boucles parallèles et internes.L'index des boucles internes, privées ou partagées?

  1. sont les indices de boucles internes, comme p, i ou Li privée ou partagée?
  2. Que se passe-t-il si je ne déclare pas les variables comme privées ou partagées?
  3. Suggérez-vous d'utiliser les variables allouables pour cette boucle parallèle?

    !$OMP PARALLEL DO 
        do l = 1,n_rep  
        do p = 1,n_l - 1 
        do q = 1,n_l - 1 
        do r = 1,n_l - 1 
         Li = (p - 1)*(n_l - 1)**2 + (q - 1)*(n_l - 1) + r 
    
         alpha(Li) = pi*rand() 
         gamma(Li) = pi*rand() 
         beta(Li) = pi/2*rand() 
    
         R_x(1,1) = 1.d0 
         R_x(1,2) = 0.d0 
         R_x(1,3) = 0.d0 
    
         R_x(2,1) = 0.d0 
         R_x(2,2) = cos(alpha(Li)) 
         R_x(2,3) = sin(alpha(Li)) 
    
         R_x(3,1) = 0.d0 
         R_x(3,2) = -sin(alpha(Li)) 
         R_x(3,3) = cos(alpha(Li)) 
    
         R_y(1,1) = cos(beta(Li)) 
         R_y(1,2) = 0.d0 
         R_y(1,3) = -sin(beta(Li)) 
    
         R_y(2,1) = 0.d0 
         R_y(2,2) = 1.d0 
         R_y(2,3) = 0.d0 
    
         R_y(3,1) = sin(beta(Li)) 
         R_y(3,2) = 0.d0 
         R_y(3,3) = cos(beta(Li)) 
    
         R_z(1,1) = cos(gamma(Li)) 
         R_z(1,2) = sin(gamma(Li)) 
         R_z(1,3) = 0.d0 
    
         R_z(2,1) = -sin(gamma(Li)) 
         R_z(2,2) = cos(gamma(Li)) 
         R_z(2,3) = 0.d0 
    
         R_z(3,1) = 0.d0 
         R_z(3,2) = 0.d0 
         R_z(3,3) = 1.d0 
    
         R_xy = matmul(R_x,R_y) 
         R_xyz = matmul(R_xy,R_z) 
    
    
         do i = 1,n_f - 1 
         do j = 1,n_f - 1 
         do k = 1,n_f - 1 
         Li = (i - 1)*(n_f - 1)**2 + (j - 1)*(n_f - 1) + k 
    
         cf_x(i) = x_f(i) + (p - 1)*d_l - x_c(p) 
         cf_y(j) = y_f(j) + (q - 1)*d_l - y_c(q) 
         cf_z(k) = z_f(k) + (r - 1)*d_l - z_c(r) 
    
         x_rotated = R_xyz(1,1)*cf_x(i) + R_xyz(1,2)*cf_y(j)  & 
            + R_xyz(1,3)*cf_z(k) 
         y_rotated = R_xyz(2,1)*cf_x(i) + R_xyz(2,2)*cf_y(j)  & 
            + R_xyz(2,3)*cf_z(k) 
         z_rotated = R_xyz(3,1)*cf_x(i) + R_xyz(3,2)*cf_y(j)  & 
            + R_xyz(3,3)*cf_z(k) 
    
         enddo 
         enddo 
         enddo 
    
    
        enddo 
        enddo 
        enddo 
        enddo 
    
    !$OMP END PARALLEL DO 
    
+3

OpenMP fait indices boucle do privés par défaut. Les rendre partagés créerait une condition de concurrence avec des résultats imprévisibles. Vous avez beaucoup de variables qui devront être rendues privées, incluant éventuellement des tableaux allouables. – tim18

+0

Une partie de ce que vous avez posté semble incomplète car il ya – tim18

+0

Beaucoup de résultats inutilisés. – tim18

Répondre

-1

Personnellement, je briser ce problème un peu.

Size_of_Array = n_l * n_l * n_l 
IF(ALLOCATED(Li))  DEALLOCATE( Li ) 
ALLOCATE( Li  (Size_of_Array)) 
IF(ALLOCATED(Alpha)) DEALLOCATE( Alpha) 
ALLOCATE (Alpha (Size_of_Array)) 
IF(ALLOCATED(Beta)) DEALLOCATE( Beta) 
ALLOCATE( Beta (Size_of_Array)) 
IF(ALLOCATED(Gamma)) DEALLOCATE( Gamma) 
ALLOCATE( Gamma (Size_of_Array)) 

indexer = 0 
do l = 1,n_rep  
    do p = 1,n_l - 1 
    do q = 1,n_l - 1 
     do r = 1,n_l - 1 
     indexer = indexer + 1 
     Li(Indexer) = (p - 1)*(n_l - 1)**2 + (q - 1)*(n_l - 1) + r 
     ENDDO 
    ENDDO 
    ENDDO 
ENDDO 

alpha = pi*rand() 
gamma = pi*rand() 
beta = pi/2*rand() 
!?OMP DO PARALLEL 
DO I= 1, SIZE(Li) 
    CALL Make_Array(Alpha(I), Beta(I), Gamma(I), MyArray(:,:,I)) 
ENDDO 
!etc 

déménagement Fondamentalement, le réseau d'être à l'intérieur de l'une d'une fonction élémentaire ou un sous-programme PURE. Ensuite, voir ce qu'il fait pour la vitesse avec l'inline et un seul faire une sorte de parallèle (OMP ou autre).

PURE SUBROUTINE Make_Array(Alpha, Beta, Gamma, MyArray) 
IMPLICIT NONE 
DOUBLE,    INTENT(IN ) :: Alpha 
DOUBLE,    INTENT(IN ) :: Beta 
DOUBLE,    INTENT(IN ) :: Gamma 
DOUBLE, DIMENSION(3,3) INTENT(INOUT) :: MyArray ! Maybe just intent(OUT)? 

    R_x(:,:) = 0.d0 
    R_x(1,1) = 1.d0 
    R_x(2,2) = cos(alpha) 
    R_x(2,3) = sin(alpha) 

    R_x(3,2) = -sin(alpha) 
    R_x(3,3) = cos(alpha) 

    R_y(1,1) = cos(beta) 
    R_y(1,3) = -sin(beta) 

    R_y(2,1) = 0.d0 
    R_y(2,2) = 1.d0 
    R_y(2,3) = 0.d0 

    R_y(3,1) = sin(beta(Li)) 
    R_y(3,2) = 0.d0 
    R_y(3,3) = cos(beta(Li)) 

    R_z(1,1) = cos(gamma(Li)) 
    R_z(1,2) = sin(gamma(Li)) 
    R_z(1,3) = 0.d0 

    R_z(2,1) = -sin(gamma(Li)) 
    R_z(2,2) = cos(gamma(Li)) 

    END SUBROUTINE Make_Array 

Etc ... Pour d'autres fonctions élémentaires ou pures

sous-routines
R_xy = matmul(R_x,R_y) 
    R_xyz = matmul(R_xy,R_ ... 
+1

Comment cela répond-il à la question? A savoir, quelles sont vos réponses aux points 1. 2. et 3. de la question à laquelle vous répondez? –

+1

Ceci est un conseil pas une réponse. –