IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Fortran Discussion :

Optimiser un RedBlack Gauss Seidel, scalaire puis parallèle


Sujet :

Fortran

  1. #1
    Membre régulier Avatar de moomba
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    134
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 134
    Points : 104
    Points
    104
    Par défaut Optimiser un RedBlack Gauss Seidel, scalaire puis parallèle
    Bonjour

    J'ai construit un PCG (Gradient Conjugué Préconditionné) pour résoudre l'équation de Poisson. Ce dernier utilise comme préconditionnement une méthode multigrid, qui utilise elle même un Red Black Gauss Seidel comme "smoother".

    Le problème, c'est qu'après une petite étude sous Valgrind, il apparait que mon Red Black est très gourmand en temps de calcul (et en échanges de mémoire).

    Je cherche donc à l'optimiser avec en objectif final avoir une version scalaire optimisée, puis une version parallèle (MPI).

    Voici la partie importante du code : (le type VG contient les différentes grilles. Ici, on travail sur la grille 1, la grille normale)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
     
    !      +---------------------------------+
    !      | Smoothing                       |
    !      +---------------------------------+
     
     do IT=1,1
     
        ! Periodic
        if(BoundMG(1,1) == 12) VG(1)%U(0,:,:)     = VG(1)%U(n1(1),:,:)
        if(BoundMG(1,2) == 12) VG(1)%U(n1(1)+1,:,:) = VG(1)%U(1,:,:)
        if(BoundMG(2,1) == 12) VG(1)%U(:,0,:)     = VG(1)%U(:,n2(1),:)
        if(BoundMG(2,2) == 12) VG(1)%U(:,n2(1)+1,:) = VG(1)%U(:,1,:)
     
        ! Neumann
        if(BoundMG(1,1) == 1) VG(1)%U(0,:,:)     = VG(1)%U(2,:,:)
        if(BoundMG(1,2) == 1) VG(1)%U(n1(1)+1,:,:) = VG(1)%U(n1(1)-1,:,:)
        if(BoundMG(2,1) == 1) VG(1)%U(:,0,:)     = VG(1)%U(:,2,:)
        if(BoundMG(2,2) == 1) VG(1)%U(:,n2(1)+1,:) = VG(1)%U(:,n2(1)-1,:)
     
        ! Center Pass for Red Nodes
        do i=1+m01,n1(1)-m11,1
           do j=1+m02+mod(i-1,2),n2(1)-m12,2
              VG(1)%U(i,j,1) = (VG(1)%U(i+1,j,1) + VG(1)%U(i-1,j,1) + VG(1)%U(i,j+1,1) + &
              &                 VG(1)%U(i,j-1,1) - h(1)*h(1)*VG(1)%F(i,j,1))/4.0d0
           end do
        end do
     
        ! Periodic
        if(BoundMG(1,1) == 12) VG(1)%U(0,:,:)     = VG(1)%U(n1(1),:,:)
        if(BoundMG(1,2) == 12) VG(1)%U(n1(1)+1,:,:) = VG(1)%U(1,:,:)
        if(BoundMG(2,1) == 12) VG(1)%U(:,0,:)     = VG(1)%U(:,n2(1),:)
        if(BoundMG(2,2) == 12) VG(1)%U(:,n2(1)+1,:) = VG(1)%U(:,1,:)
     
        ! Neumann
        if(BoundMG(1,1) == 1) VG(1)%U(0,:,:)     = VG(1)%U(2,:,:)
        if(BoundMG(1,2) == 1) VG(1)%U(n1(1)+1,:,:) = VG(1)%U(n1(1)-1,:,:)
        if(BoundMG(2,1) == 1) VG(1)%U(:,0,:)     = VG(1)%U(:,2,:)
        if(BoundMG(2,2) == 1) VG(1)%U(:,n2(1)+1,:) = VG(1)%U(:,n2(1)-1,:)
     
        ! Center Pass for Black Nodes
        do i=1+m01,n1(1)-m11,1
           do j=1+m02+mod(i,2),n2(1)-m12,2
              VG(1)%U(i,j,1) = (VG(1)%U(i+1,j,1) + VG(1)%U(i-1,j,1) + VG(1)%U(i,j+1,1) + &
              &                 VG(1)%U(i,j-1,1) - h(1)*h(1)*VG(1)%F(i,j,1))/4.0d0
           end do
        end do
     
     end do
     
    !      +---------------------------------+
    !      | Residut Calculation             |
    !      +---------------------------------+
     
     do i=1+m01,n1(1)-m11,1
        do j=1+m02,n2(1)-m12,1
           VG(1)%Residut(i,j,1) = VG(1)%F(i,j,1) - (VG(1)%U(i+1,j,1) + VG(1)%U(i-1,j,1) + &
           &                      VG(1)%U(i,j+1,1) + VG(1)%U(i,j-1,1) - 4*VG(1)%U(i,j,1))/(h(1)*h(1))
        end do
     end do
     
    !      +---------------------------------+
    !      | Restriction                     |
    !      +---------------------------------+
     
    k=1
     
     do i=1,n1(2),1
        do j=1,n2(2),1
           ii=(i-1)*2+1
           jj=(j-1)*2+1
           VG(2)%F(i,j,1) = (VG(1)%Residut(ii,  jj,1)+VG(1)%Residut(ii+1,jj,1)+ &
           &                 VG(1)%Residut(ii,jj+1,1)+VG(1)%Residut(ii+1,jj+1,1))*0.25d0
        end do
     end do
    Le code fait ici une simple passe de Red Black, puis calcul le résidu, et enfin fait une restriction vers la grille plus grossière.

    Un peu plus loin, on retrouve l'opération inverse, à savoir une interpolation (k est le numéros de la grille) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        do i=1,n1(k-1),2
           do j=1,n2(k-1),2
              ii = int((i-1)*0.5+1)
              jj = int((j-1)*0.5+1)
              VG(k-1)%U(i,j,1)     = VG(k-1)%U(i,j,1) + VG(k)%U(ii,jj,1)
              VG(k-1)%U(i,j+1,1)   = VG(k-1)%U(i,j+1,1) + VG(k)%U(ii,jj,1)
              VG(k-1)%U(i+1,j,1)   = VG(k-1)%U(i+1,j,1) + VG(k)%U(ii,jj,1)
              VG(k-1)%U(i+1,j+1,1) = VG(k-1)%U(i+1,j+1,1) + VG(k)%U(ii,jj,1)
           end do
        end do
    Ces opérations sont répétées sur chaque niveau de grille, sachant que la grille k+1 est 2 fois plus petite que la grille k.

    Le problème des grilles n'est pas important ici

    Je cherche à optimiser au maximum les opérations données ci dessus. J'ai pensé à découper la mémoire dans un tableau Red, et un tableau Black afin d'avoir continuité en lecture, mais je ne sais pas trop si ca vaut le coup...

    Auriez vous des idées d'optimisation (déjà remplacer le /4.0, et le h*h) ?

    Merci d'avance pour votre aide

    Cordialement

    Moomba
    "Celui qui à le pouvoir de faire le mal, mais qui ne le fait pas, celui là est le prince de l'univers." (shakespeare)

  2. #2
    Membre habitué

    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    35
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2007
    Messages : 35
    Points : 185
    Points
    185
    Par défaut
    Bonjour,

    Je te conseille l'outil ThreadSpotter, qui va analyser ton code, t'indiquer les zones qui sont gourmandes en accès mémoire/cache et qui va te suggérer des pistes d'amélioration.

    Bonus : un PDF qui devrait t'intéresser, puisqu'il parle exactement de ton cas.


    -SebGR

Discussions similaires

  1. gauss seidel et cholesky
    Par lorlye dans le forum MATLAB
    Réponses: 6
    Dernier message: 20/01/2009, 01h46
  2. Réponses: 5
    Dernier message: 05/12/2006, 18h40
  3. decomposition LU, gauss-seidel, implementation lorsqu il y a des 0 sur la diagonale
    Par le_voisin dans le forum Algorithmes et structures de données
    Réponses: 1
    Dernier message: 08/09/2006, 23h12
  4. [maths] Méthode de Gauss-Seidel
    Par al85 dans le forum Mathématiques
    Réponses: 5
    Dernier message: 20/05/2006, 20h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo