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

C++ Discussion :

Comment obtenir le maximum de performance (calcul) ?


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut Comment obtenir le maximum de performance (calcul) ?
    Il y a une dizaine d'années, plusieurs articles sont parus pour montrer que C++ pouvait avoir des performances égales ou équivalentes au Fortran. En particulier, on pouvait s'appuyer sur la bibliothèque Blitz++ (http://www.oonumerics.org/blitz/).
    Depuis, j'ai refait des tests sur plusieurs plateformes. Les performances en Fortran sont bien plus impressionnantes en Fortran 90 qu'en Fortran 77 (un facteur 2 est courant). Même certaines versions "tunées" sont plus lentes que les versions classiques. Cela s'inverse par exemple sur le bench acoustique 2D si on prend un modèle de taille 6500*6500 (donc 100 fois plus important).

    Pour en revenir au C++, les performances sont actuellement inférieures à celles de Fortran sur ces benchs avec les compilateurs actuels (ICC 10 ou 11, PGI 8, sur plusieurs plateformes comme les Xeon avec architecture Core, Opteron, Itanium). Même en indiquant au compilateur que les arguments ne peuvent pas être aliasés (-fno-fnalias pour GCC et ICC par exemple, tout en sachantq ue ces options sont dangereuses, ou en utilisant le mot-clé C99 restrict sur des benchs C), il n'est pas toujours possible d'obtenir les mêmes performances qu'en Fortran (sur d'autres benchs).

    Ce post est donc proposé ici pour voir quelles sont les solutions pour approcher les performances maximales... Pour l'instant, je n'en ai pas

  2. #2
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Avant de parler solution, parlons problème

    Tu as un bench particulier et simple où la solution C++ est plus lente que la solution Fortran ? Tu as eu l'occasion de l'analyser pour voir qu'est-ce qui faisait la différence ?
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  3. #3
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Le bench Blitzz++, la version Acoustic 2D et 3D (il peut tout de même y avoir un facteur 2 ou 3 entre les versions, c'est dire...). Je vais essayer de faire plus simple demain avec juste 2 ou 3 boucles for imbriquées.

  4. #4
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Un exemple simple, mais assez représentatif :
    La version C++ (c'est quasiment du C) :
    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
    #include <iostream>
    #include <cstdlib>
     
    #define XYZ(x, y, z, N) ((x) + (y) * (N) + (z) * (N) * (N))
     
    void compute(float* P, float* Q, int N);
     
    int main(int argc, char** argv)
    {
      const int N = 100;
      const int iter = 100;
     
      float* P = new float[N*N*N];
      float* Q = new float[N*N*N];
     
      for(int i = 0; i < N*N*N; ++i)
      {
        P[i] = 1500;
        Q[i] = 1500;
      }
     
      for(int i = 0; i < iter; ++i)
      {
        compute(P, Q, N);
        compute(Q, P, N);
      }
     
      std::cout << P[XYZ(N/2, N/2, N/2, N)] << std::endl;
     
      delete[] P;
      delete[] Q;
     
      return EXIT_SUCCESS;
    }
     
    void compute(float* P, float* Q, int N)
    {
      for(int k = 4; k < N-4; ++k)
      {
        for(int j = 4; j < N-4; ++j)
        {
          for(int i = 4; i < N-4; ++i)
          {
            Q[XYZ(i, j, k, N)] = P[XYZ(i, j, k, N)]
              + (P[XYZ(i+1, j, k, N)] - P[XYZ(i-1, j, k, N)])
              + (P[XYZ(i+2, j, k, N)] - P[XYZ(i-2, j, k, N)])
              + (P[XYZ(i+3, j, k, N)] - P[XYZ(i-3, j, k, N)])
              + (P[XYZ(i+4, j, k, N)] - P[XYZ(i-4, j, k, N)])
              + (P[XYZ(i, j+1, k, N)] - P[XYZ(i, j-1, k, N)])
              + (P[XYZ(i, j+2, k, N)] - P[XYZ(i, j-2, k, N)])
              + (P[XYZ(i, j+3, k, N)] - P[XYZ(i, j-3, k, N)])
              + (P[XYZ(i, j+4, k, N)] - P[XYZ(i, j-4, k, N)])
              + (P[XYZ(i, j, k+1, N)] - P[XYZ(i, j, k-1, N)])
              + (P[XYZ(i, j, k+2, N)] - P[XYZ(i, j, k-2, N)])
              + (P[XYZ(i, j, k+3, N)] - P[XYZ(i, j, k-3, N)])
              + (P[XYZ(i, j, k+4, N)] - P[XYZ(i, j, k-4, N)]);
          }
        }
      }
    }
    La version Fortran :
    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
    PROGRAM test2Df
     
      IMPLICIT NONE
     
      REAL, ALLOCATABLE :: P(:,:,:)
      REAL, ALLOCATABLE :: Q(:,:,:)
     
      INTEGER N, iter
     
      INTEGER i
     
      N = 100
      iter = 100
     
      ALLOCATE(P(N,N,N))
      ALLOCATE(Q(N,N,N))
     
      P(:,:,:) = 1500
      Q(:,:,:) = 1500
     
      do i = 1, iter
        CALL COMPUTE(P, Q, N)
        CALL COMPUTE(Q, P, N)
      enddo
     
      PRINT *, P(N/2+1,N/2+1,N/2+1)
     
      DEALLOCATE(P)
      DEALLOCATE(Q)
     
    END PROGRAM
     
    SUBROUTINE COMPUTE(P, Q, N)
     
      IMPLICIT NONE
     
      REAL :: P(N,N,N)
      REAL :: Q(N,N,N)
      INTEGER :: N
     
      INTEGER i, j, k
     
      do k = 5, N-4
        do j = 5, N-4
          do i = 5, N-4
            Q(i, j, k) = P(i, j, k) &
              + (P(i-1, j, k) - P(i+1, j, k)) &
              + (P(i-2, j, k) - P(i+2, j, k)) &
              + (P(i-3, j, k) - P(i+3, j, k)) &
              + (P(i-4, j, k) - P(i+4, j, k)) &
              + (P(i, j-1, k) - P(i, j+1, k)) &
              + (P(i, j-2, k) - P(i, j+2, k)) &
              + (P(i, j-3, k) - P(i, j+3, k)) &
              + (P(i, j-4, k) - P(i, j+4, k)) &
              + (P(i, j, k-1) - P(i, j, k+1)) &
              + (P(i, j, k-2) - P(i, j, k+2)) &
              + (P(i, j, k-3) - P(i, j, k+3)) &
              + (P(i, j, k-4) - P(i, j, k+4))
          enddo
        enddo
      enddo
     
    END SUBROUTINE
    Compilé avec ICC 10.1.018 (-O2 par défaut), j'obtiens 3.3s pour le C++ et 1.7s pour le Fortran...

    Comme je l'ai dit, il y a des extensions qui me permettent d'optimiser, mais ce ne sont pas des extensions officielles, elles viennent sur le C99, mais je ne sais pas si elles intègreront C0x. Donc si je mets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void compute(float* __restrict__ P, float* __restrict__ Q, int N)
    Là, j'ai des perfs identiques. Mais ce n'est pas standard. De plus, c'est sur une signature, la fonction que j'utilise réellement est une structure qui englobe plusieurs P et Q (car le stencil est plus complexe).

  5. #5
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    float == real ?
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  6. #6
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Par défaut
    Oui, pardon, les real Fortran sont des flottants 32bits.

Discussions similaires

  1. comment obtenir différents calcul dans état
    Par Domi70 dans le forum IHM
    Réponses: 10
    Dernier message: 16/02/2009, 00h06
  2. Comment obtenir la valeur d'un calcul ?
    Par EGSway dans le forum IHM
    Réponses: 4
    Dernier message: 21/06/2007, 19h14
  3. comment obtenir un polynome de regression
    Par evariste_galois dans le forum Mathématiques
    Réponses: 17
    Dernier message: 19/01/2007, 15h06
  4. Comment obtenir l'heure du serveur avec flash ?
    Par Michaël dans le forum Flash
    Réponses: 9
    Dernier message: 23/12/2003, 17h50
  5. Comment obtenir la liste des paramètres d'une SP ?
    Par Le Gritche dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 14/03/2003, 16h54

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