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

Threads & Processus C++ Discussion :

Lenteur multithread vs monothread


Sujet :

Threads & Processus C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 53
    Par défaut Lenteur multithread vs monothread
    Bonjour,
    Je suis en train de faire des tests en multithread. Sur un petit programme de test, j'ai un fort ralentissement en MT que je ne comprend pas.
    Je fais un calcul (qui n'a aucune valeur ici, c'est juste pour le test).
    => j'obtiens un temps en monothread (1)
    Puis je fais ce même calcul N fois sur N threads. Les calculs sont indépendants donc je m'attend à obtenir à peu près le même temps que (1) mais ce n'est pas toujours le cas. Je peux obtenir un temps 10 fois plus long.

    Le ralentissement est toujours plus ou moins proportionnel au nombre de thread.
    Est ce du à l'accès au cache ? Est ce ma facon de c Autre chose ? Y'a-t-il un moyen d’améliorer cela ?

    Ci dessous le code (que j'ai laissé volontairement le plus simple possible).

    Merci

    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
    #include <iostream>
    #include <unistd.h>
    #include <thread>
    #include <vector>
    #include <array>
    #include <chrono>
    #include <iostream>
    #include <utility>
    #include <atomic>
    #include <mutex>
    using namespace std;
     
    int TestMT2Id(int id){
        int i,j;
        int nx=5000;
        int ny=100;
        vector<double> vv(nx,0);
        for( j=0; j<nx; j++)vv[j]=j;
        double xx=0;
        for(i=0; i<ny; i++) {
            for( j=0; j<nx; j++) {
                vv[j]+=1.;
                xx+= vv[j];
            }
        }
        for( j=0; j<nx; j++) {
            xx+=vv[j];
        }
        return 0;
    }
     
    int main(int argc, char **argv)
    {
        int num_cores=8;
        cout<<"ncpu "<<num_cores<<endl;
     
        cout<<"Test monothread  : ";
        auto start = std::chrono::system_clock::now();
        TestMT2Id(0);
        auto end = std::chrono::system_clock::now();
        std::chrono::duration<double> elapsed = end - start;
        std::cout << "Elapsed time= " << elapsed.count() << "s"<<endl;
     
        cout<<"Test multithread : ";
        auto start1 = std::chrono::system_clock::now();
        for (int i = 0; i < num_cores; i++) {
            thread t([i]() {
                TestMT2Id(i);
            });
            t.join();
        }
     
        auto end1 = std::chrono::system_clock::now();
        std::chrono::duration<double> elapsed1 = end1 - start1;
        std::cout << "Elapsed time= " << elapsed1.count() << "s"<<endl;
        return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ncpu 8
    Test monothread  : Elapsed time= 0.000296322s
    Test multithread : Elapsed time= 0.00288444s

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2011
    Messages
    752
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 752
    Par défaut
    join() attend que le thread se termine, donc ici, aucun thread ne tourne en parallèle. Il faut les mettre dans std::vector ou std::array et faire la boucle sur t.join() après avoir créé tous les threads.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 53
    Par défaut
    @jo_link_noir : ok merci, je n'etais pas bien au courant de ce fait. En fait j'avais fait ce que tu preconises dans un 1er temps mais n'ai pas vu de diff sur les perfs:

    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
    #include <iostream>
    #include <unistd.h>
    #include <thread>
    #include <vector>
    #include <array>
    #include <chrono>
    #include <iostream>
    #include <utility>
    #include <atomic>
    #include <mutex>
    using namespace std;
     
    int TestMT2Id(int id){
        int i,j;
        int nx=500000;
        int ny=10000;
        vector<double> vv(nx,0);
      //  double* vv= new double[nx];
        for( j=0; j<nx; j++)vv[j]=j;
        double xx=0;
        for(i=0; i<ny; i++)
        {
            for( j=0; j<nx; j++)
            {
                vv[j]+=1.;
                xx+= vv[j];
            }
        }
        for( j=0; j<nx; j++)
        {
            xx+=vv[j];
        }
        return 0;
    }
     
    int main(int argc, char **argv)
    {
        int num_cores=8;
        cout<<"ncpu "<<num_cores<<endl;
     
        cout<<"Test monothread  : ";
        auto start = std::chrono::system_clock::now();
        TestMT2Id(0);
        auto end = std::chrono::system_clock::now();
        std::chrono::duration<double> elapsed = end - start;
        std::cout << "Elapsed time= " << elapsed.count() << "s"<<endl;
     
        cout<<"Test multithread : ";
        auto start1 = std::chrono::system_clock::now();
        thread threads[num_cores];
        for (int i = 0; i < num_cores; i++) {
            thread t([i]() {
                TestMT2Id(i);
            });
            threads[i] = std::move(t);
        }
        for (thread & t : threads)
            t.join();
     
        auto end1 = std::chrono::system_clock::now();
        std::chrono::duration<double> elapsed1 = end1 - start1;
        std::cout << "Elapsed time= " << elapsed1.count() << "s"<<endl;
        return 0;
    }
    Resultats :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ncpu 8
    Test monothread  : Elapsed time= 1.89004s
    Test multithread : Elapsed time= 7.41875s

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 492
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 492
    Billets dans le blog
    1
    Par défaut
    Il ne faut pas oublier que créer et détruire des threads prend du temps.

    Si le calcul est très rapide, tu peux dégrader les performances à passer en multithread.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    53
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 53
    Par défaut
    Hello,
    Je mets à jour mon code car je me suis rendu compte qu'à l'avoir trop simplifié pour le fil de discussion, il y ai de forte chance que le compilo en ait supprimé une bonne partie pour l'optim (cad variables non utilisées).
    J'ai rajouté des print pour forcer le calcul dans les threads.
    Encore une fois le calcul n'a pas de sens spécial, c'est juste pour l'exemple.

    J'ai donc encore un facteur 2 de vitesse entre monothread et multithread que je n'explique pas vraiment.
    Des avis ??

    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
    #include <iostream>
    #include <unistd.h>
    #include <thread>
    #include <vector>
    #include <array>
    #include <chrono>
    #include <iostream>
    #include <utility>
    #include <atomic>
    #include <mutex>
    #include <cmath>
    using namespace std;
     
    double TestMT2Id(int id){
        int i,j;
        int nx=500000;
        int ny=10000;
        vector<double> vv(nx,0);
        double xx=0;
        for(i=0; i<ny; i++)
        {
            for( j=0; j<nx; j++)
            {
                vv[j]+=1.;
                xx+= vv[j];
            }
        }
        return xx;
    }
     
    int main(int argc, char **argv)
    {
        int num_cores=8;
        cout<<"ncpu "<<num_cores<<endl;
     
        cout<<"Test monothread  : ";
        auto start = std::chrono::system_clock::now();
        double xx = TestMT2Id(0);
        cout<<" xx= "<<xx;
        auto end = std::chrono::system_clock::now();
        std::chrono::duration<double> elapsed = end - start;
        std::cout << " => Elapsed time= " << elapsed.count() << "s"<<endl;
     
        cout<<"Test multithread : ";
        auto start1 = std::chrono::system_clock::now();
        thread threads[num_cores];
        xx = 0;
        for (int i = 0; i < num_cores; i++) {
            thread t([&xx, i]() {
                xx += TestMT2Id(i);
            });
            threads[i] = std::move(t);
        }
        for (thread & t : threads)
            t.join();
     
        cout<<" xx= "<<xx;
     
        auto end1 = std::chrono::system_clock::now();
        std::chrono::duration<double> elapsed1 = end1 - start1;
        std::cout << " => Elapsed time= " << elapsed1.count() << "s"<<endl;
        return 0;
    }
    Resultats :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ncpu 8
    Test monothread  :  xx= 2.50025e+13 => Elapsed time= 6.25111s
    Test multithread :  xx= 2.0002e+14 => Elapsed time= 15.977s

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 146
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Malawi Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        int num_cores=8;
        ...
        thread threads[num_cores];
    Ton compilo arriver à interpréter ça en constant compile-time pour ne pas faire un VLA qui sont interdits en C++ ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

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

Discussions similaires

  1. multithreader un programme monothread
    Par vince3320 dans le forum Threads & Processus
    Réponses: 3
    Dernier message: 19/01/2016, 12h39
  2. Réponses: 16
    Dernier message: 01/10/2010, 13h47
  3. [Sybase]probleme de lenteur
    Par MASSAKA dans le forum Sybase
    Réponses: 3
    Dernier message: 19/03/2003, 22h58
  4. Lenteur d'execution de Jbuilder 6
    Par Tsimplice dans le forum JBuilder
    Réponses: 6
    Dernier message: 18/12/2002, 14h41
  5. Multithreading sous HP Ux 11
    Par pykoon dans le forum Autres éditeurs
    Réponses: 1
    Dernier message: 18/10/2002, 23h36

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