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 :

Problème de lenteur en 64 bits avec Mingw-w64


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Août 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

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

    Informations forums :
    Inscription : Août 2016
    Messages : 3
    Points : 3
    Points
    3
    Par défaut Problème de lenteur en 64 bits avec Mingw-w64
    Bonjour,

    Je suis depuis un certain temps sur la programmation d'un projet personnel en C. Après avoir fait la majeur partie du en développant en 32 bits, j'ai par la suite utilisé la suite mingw-w64 pour faire mes binaires en 64 bits (j'utilisais mingw32 pour mes binaires en 32 bits). Le fonctionnement du programme est nickel sur les deux. Par contre, je rencontre un problème de lenteur important avec mingw-w64 lors de l'éxécution (qui peut varier de 6x à 90x plus lent que la version 32 bits, dépendant de ce qui est demandé). Ainsi, j'ai tenté de faire des tests et je suis venu à trouver un code minimal qui est beaucoup plus lent lorsqu'il est compilé sous mingw-w64 que lorsqu'il est fait avec mingw32, que voici:

    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
     
    #include <stdio.h>
     
    int  main(int argc, char *argv[])
    {
     
        printf("%d\n",sizeof(void*));
     
     
        int i=0;
        long long segpa;
        long long segpa2;
        long long segpa3;
        long long segpa4;
        long long segpa5;
        long long segpa6;
        long long segpa7;
        long long segpa8;
     
     
        while(i<1000000000)
        {
            *((int*)&segpa)+=100;
     
            *((int*)&segpa2)+=(i*2);
     
            *((int*)&segpa3)+=300;
     
            *((int*)&segpa4)+=segpa8;
     
            *((int*)&segpa5)+=segpa7;
     
            *((int*)&segpa6)+=segpa;
     
            *((int*)&segpa7)+=segpa6;
     
            *((int*)&segpa8)+=segpa2;
     
           i+=1;
        }
     
        printf("%d",segpa);
        printf("%d",segpa2);
        printf("%d",segpa3);
        printf("%d",segpa4);
        printf("%d",segpa5);
        printf("%d",segpa6);
        printf("%d",segpa7);
        printf("%d\n\n\n",segpa8);
     
        return 0;
    }


    La temps d’exécution est de 2.5 secondes en 32 bits, et de un peu moins de 13 secondes en 64 bits (Sur un Intel I5-4690 à 3.50Ghz). Désolé si le code est un peu étrange, je voulais que le compilateur ne puisse pas optimisé les variables inutilisés et les résultats qui étaient possible de prévoir.

    J'utilise aussi beaucoup de déférencement de pointeur (autant dans l'exemple, que dans le programme complet) , qui semble être ce qui pose problème. J'ai essayé pas mal tout les paramètres d'optimisations du compilateur, mais rien n'y change. J'ai essayé de compiler ce code exemple sur MSVC, la version 64 bits est très légèrement plus rapide que la 32 bits, mais aucune différence vraiment remarquable. La vitesse dans les deux cas est comparable aux résultats avec Mingw32.

    Avez-vous déjà eu ce genre de problème? Est-ce possible d'écrire mon déférencement d'une meilleur façon pour éviter que le compilateur génère du code aussi lent? Est-ce quelque chose de normal? Ai-je fait une bourde?



    Merci de votre aide!
    Si j'e n'ai pas été assez clair ou quoi que ce soit ,n'hésitez pas à me demander plus d'informations.

  2. #2
    Expert éminent sénior
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 214
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 214
    Points : 10 140
    Points
    10 140
    Par défaut
    Bonne question je n'en sais rien je connais peu le compilateur MingW .

    Mais #include <cstdio> , c'est pas quand on code en C++ ?
    Du coup tu utilise le compilateur C ou le compilateur C++ ? (ça peut nous être utile pour savoir si ce comportement vient du compilateur C ou du C++).

  3. #3
    Candidat au Club
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Août 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

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

    Informations forums :
    Inscription : Août 2016
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Merci de m'avoir fait remarqué une légère bourde de configuration que j'avais fait sur le programme d'exemple. J'ai réglé le problème de mon côté pour le faire compiler avec le compilateur C (je vais aussi modifier le code du post, pour le mettre en pure C), mais le problème est toujours présent, ce qui démontre que mon problème est autant présent sur le compilateur C que celui du C++.

    Merci!

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Il y a, à mon avis, un gros problème :
    Désolé si le code est un peu étrange, je voulais que le compilateur ne puisse pas optimisé les variables inutilisés
    Le compilateur est là pour optimiser. Si tu l'empêches de faire son travail, tu auras forcément de mauvais résultats. Dire que ce code est plus rapide avec mingw32 qu'avec mingw64 veut simplement dire que le premier s'en sort mieux que le second avec ce code compliqué. Et c'est tout le problème de l'optimisation : c'est du cas par cas, compilateur par compilateur, fonction par fonction. Même si certains grands principes restent, notamment celui de faire du code lisible et relativement que le compilateur arrivera à optimiser.

    Pour enquêter sur les raisons de la lenteur de ton code sur 64 bits, il ne faut pas créer un code minimaliste différent de ton application, sauf si le but est de mon montrer un bug ou un réel défaut du compilateur. C'est peut-être d'ailleurs ton but ? Si tu veux "juste" améliorer ton application, il faut la profiler. Utilise un outil comme gproof, qui est fourni avec mingw32. Regarde les fonctions lentes avec mingw64. Regarde si ce sont les mêmes ou pas avec mingw32. Compare les codes assembleurs de ces fonctions. Cherche comme les améliorer.

    Au passage, ton code compile mais avec plein de warnings avec mingw32 sur Windows 7 :
    ||=== Build: Debug in CodeBlocks (compiler: GNU GCC Compiler) ===|
     main.c||In function 'int main(int, char**)':|
     main.c|23|warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]|
     main.c|25|warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]|
     main.c|27|warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]|
     main.c|29|warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]|
     main.c|31|warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]|
     main.c|33|warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]|
     main.c|35|warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]|
     main.c|37|warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]|
     main.c|42|warning: format '%d' expects argument of type 'int', but argument 2 has type 'long long int' [-Wformat=]|
     main.c|43|warning: format '%d' expects argument of type 'int', but argument 2 has type 'long long int' [-Wformat=]|
     main.c|44|warning: format '%d' expects argument of type 'int', but argument 2 has type 'long long int' [-Wformat=]|
     main.c|45|warning: format '%d' expects argument of type 'int', but argument 2 has type 'long long int' [-Wformat=]|
     main.c|46|warning: format '%d' expects argument of type 'int', but argument 2 has type 'long long int' [-Wformat=]|
     main.c|47|warning: format '%d' expects argument of type 'int', but argument 2 has type 'long long int' [-Wformat=]|
     main.c|48|warning: format '%d' expects argument of type 'int', but argument 2 has type 'long long int' [-Wformat=]|
     main.c|49|warning: format '%d' expects argument of type 'int', but argument 2 has type 'long long int' [-Wformat=]|
     main.c|23|warning: iteration 42949673u invokes undefined behavior [-Waggressive-loop-optimizations]|
     main.c|21|note: containing loop|
    ||=== Build finished: 0 error(s), 17 warning(s) (0 minute(s), 1 second(s)) ===|
    
    Les printf(), ce n'est pas bien grave. L'aliasing, c'est pas bien du tout. Le dernier, je ne le connaissais pas, mais il me fait un peu peur.

  5. #5
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Les printf(), ce n'est pas bien grave.
    Comportement indéterminé tout de même..

  6. #6
    Candidat au Club
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Août 2016
    Messages
    3
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

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

    Informations forums :
    Inscription : Août 2016
    Messages : 3
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Bktero Voir le message

    Pour enquêter sur les raisons de la lenteur de ton code sur 64 bits, il ne faut pas créer un code minimaliste différent de ton application, sauf si le but est de mon montrer un bug ou un réel défaut du compilateur. C'est peut-être d'ailleurs ton but ? Si tu veux "juste" améliorer ton application, il faut la profiler. Utilise un outil comme gproof, qui est fourni avec mingw32. Regarde les fonctions lentes avec mingw64. Regarde si ce sont les mêmes ou pas avec mingw32. Compare les codes assembleurs de ces fonctions. Cherche comme les améliorer.
    C'était un peu mon but, remarque que c'est grâce au profilage que j'ai pu voir qu'elle genre de ligne était très lente à exécuter pour en faire un code minimal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    *((int*)&segpa4)+=segpa8;
    Citation Envoyé par Bktero Voir le message
    Dire que ce code est plus rapide avec mingw32 qu'avec mingw64 veut simplement dire que le premier s'en sort mieux que le second avec ce code compliqué
    C'est ce que je vois! Je viens de tester une façon pour tenter de faire d'une façon différente, en utilisant un char* pour procéder à mes actions enlève les warning et semble être beaucoup mieux digérer par le compilateur. Merci!

    Pour conclure le topic, je suis pas mal sûr que le problème vient de Mingw-w64...mais en fait pas vraiment. Comme c'est une....très mauvaise ligne de code, le compilateur n'optimise pas la ligne du tout, comparé aux autres compilateurs que j'ai utilisé. N'empêche, je peux vraiment pas blâmé le compilateur, comme c'est une ligne provocant un "undefined behavior", je vais donc utiliser une autre façon de faire mon déférencement de façon plus "clean".

    Merci à tout le monde (et à toi Bktero qui m'a bien guidé) pour avoir lu/aidé.

  7. #7
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Ça fonctionne avec un cast vers char * car c'est le seul type de pointeur autorisé à être déréférencé alors qu'il pointe sur un objet de type différent (aliasing).

  8. #8
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 679
    Points
    13 679
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    Comportement indéterminé tout de même..
    Undefined ou implementation-defined ? Je chipote, pardon ! On peut imaginer que ça reformate le disque dur mais en toute logique, ça ne fait qu'un affichage possiblement erroné. Ce qui peut-être tragique quand tu te bases dessus pour afficher le résultat d'un calcul et que tu passes ensuite 1 heure à chercher pourquoi ça marche pas...

    J'en profite d'ailleurs pour balancer un lien intéressant sur les undefined behaviors qu'on devrait tous connaitre et surtout ne jamais utilisés : http://blog.llvm.org/2011/05/what-ev...ould-know.html

    Citation Envoyé par Chaore26 Voir le message
    Je viens de tester une façon pour tenter de faire d'une façon différente, en utilisant un char* pour procéder à mes actions enlève les warning et semble être beaucoup mieux digérer par le compilateur.

    Pour conclure le topic, je suis pas mal sûr que le problème vient de Mingw-w64...mais en fait pas vraiment. Comme c'est une....très mauvaise ligne de code, le compilateur n'optimise pas la ligne du tout, comparé aux autres compilateurs que j'ai utilisé. N'empêche, je peux vraiment pas blâmé le compilateur, comme c'est une ligne provocant un "undefined behavior", je vais donc utiliser une autre façon de faire mon déférencement de façon plus "clean".
    Citation Envoyé par Matt_Houston Voir le message
    Ça fonctionne avec un cast vers char * car c'est le seul type de pointeur autorisé à être déréférencé alors qu'il pointe sur un objet de type différent (aliasing).
    Il faut faire très attention à ne pas casser la règle du strict aliasing : http://blog.qt.io/blog/2011/06/10/ty...rict-aliasing/ et http://cellperformance.beyond3d.com/...-aliasing.html

    Citation Envoyé par Chaore26 Voir le message
    Merci à tout le monde (et à toi Bktero qui m'a bien guidé) pour avoir lu/aidé.
    De rien

  9. #9
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Undefined ou implementation-defined ? Je chipote, pardon ! On peut imaginer que ça reformate le disque dur mais en toute logique, ça ne fait qu'un affichage possiblement erroné. Ce qui peut-être tragique quand tu te bases dessus pour afficher le résultat d'un calcul et que tu passes ensuite 1 heure à chercher pourquoi ça marche pas...

    J'en profite d'ailleurs pour balancer un lien intéressant sur les undefined behaviors qu'on devrait tous connaitre et surtout ne jamais utilisés : http://blog.llvm.org/2011/05/what-ev...ould-know.html
    De mémoire il me semble que c'est undefined, je peux me gourer. De toute manière c'est que dalle à corriger vaut mieux pas prendre de risque.

    Lien effectivement très instructif, merci ! D'ailleurs ça :

    Shifting a uint32_t by 32 or more bits is undefined.
    Je ne le savais pas !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Compilation en 64 bits avec MinGW
    Par Xarnet dans le forum Qt Creator
    Réponses: 4
    Dernier message: 03/02/2016, 23h24
  2. Compilation de Qt en 64 bits avec MinGW
    Par Glandelf dans le forum Débuter
    Réponses: 4
    Dernier message: 19/09/2013, 23h23
  3. Problème de lenteur sur une proc avec EF mais pas sur la base
    Par Oberown dans le forum Entity Framework
    Réponses: 0
    Dernier message: 14/02/2013, 16h49
  4. Problème de lenteur avec 2 sous-formulaires
    Par picatchou dans le forum Access
    Réponses: 1
    Dernier message: 29/01/2007, 08h48

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