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 :

Probl�me de lenteur du multi-threading


Sujet :

Threads & Processus C++

Mode arborescent

Message pr�c�dent Message pr�c�dent   Message suivant Message suivant
  1. #1
    Membre chevronn�
    Avatar de ABD-Z
    Homme Profil pro
    Ing�. webapps embarqu�es � Admin/mainteneur serveur/BDD � Formateur WordPress � Desiger : logo/site
    Inscrit en
    Septembre 2016
    Messages
    302
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 28
    Localisation : France, Val de Marne (�le de France)

    Informations professionnelles :
    Activit� : Ing�. webapps embarqu�es � Admin/mainteneur serveur/BDD � Formateur WordPress � Desiger : logo/site

    Informations forums :
    Inscription : Septembre 2016
    Messages : 302
    Billets dans le blog
    3
    Par d�faut Probl�me de lenteur du multi-threading
    Bonjour � vous tous!
    Je me retourne vers vous, les pros, pour avoir vos opinions sur le multi-threading, et plus pr�cis�ment en C++.

    Je souhaite en fait am�liorer les performances de mon s�quenceur de musique temps r�el (voir branche performance) en apportant justement du multi-treading.

    Pour faire simple, le s�quenceur peut �tre compos� de N canaux.
    Chaque canal, � un instant T, calcul son propre �chantillon audio. Les r�sultats de chaque canal vont �tre � la fin additionn�s pour former l��chantillon audio de la musique � l�instant T.
    On additionne N �chantillons pour former un �chantillon audio effectif qui sera sauvegarder dans le tampon audio.

    Cette op�ration de calcul des �chantillons au niveau des canaux se fait s�quentiellement : c�est-�-dire qu�on commence par calculer l��chantillon du canal N-1, puis celui du canal N-2 jusqu�au canal 0.
    (oui t�as capt�, commencer la boucle par N-1 c�est plus rapide!)

    Je me suis dit : �Tiens, �a serait pas mal si l�on parall�lisait tout �a !�.
    Surtout que les canaux n�ont pas d�interd�pendances ; chaque canal a ses propres donn�es et donc pas de prise de t�te avec la concurrence, de ressources bien entendu.

    Du coup, avant de me lancer dans la modification de mon projet, j�ai fait un croquis pour simuler l�ex�cution en s�quentielle et en �parall�le� (oui je me des guillemets parce qu�on sait tous que les threads c�est pas forc�ment parall�le en r�alit�) et ainsi comparer leur temps d�ex�cution.

    Dans le fichier de simulation (disponible, j�ai d�clar� trois constantes en #define.
    CHANSc�est le nombre de canaux que l�on va cr�er.
    COUNTle nombre de fois que l�on va r�p�ter le �calcul d��chantillonnage�
    LOOPSest utilis� dans les boucles for pour faire �couler du temps et ainsi simuler le temps de �calcul d��chantillonnage� au niveau du canal.

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    #define CHANS 2
    #define COUNT 10
    #define LOOPS 666
    Premi�rement, on a la classe Seq_Chan qui sera utilis� pour simuler le calcul s�quentiel.
    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
    class Seq_Chan {
    private:
    	unsigned char id = 0;
    	static unsigned char chancount;
    public:
    	Seq_Chan() {
            this->id = Seq_Chan::chancount++;
        }
     
        void play()
        {
        	//std::cout << "Seq Chan " << +this->id <<" play  " << std::endl;
        	for(int i = 0; i<LOOPS; ++i);
        	//std::cout << "Seq Chan " << +this->id <<" finish play  " << std::endl;
        }
    };
    unsigned char Seq_Chan::chancount = 0;
    Dans le main rien de plus simple :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    Seq_Chan seq_chan[CHANS];
    	for(unsigned int j = 0; j < COUNT; ++j){
    		//std::cout << "*******************************"<<j<<"*******************************"<<std::endl;
    		for(char i=(CHANS-1); i >=0; --i){
    			seq_chan[i].play();
    		}
     
    	}
    Deuxi�mement, concernant la classe qui g�re les threads, Chan,elle stocke le std::thread (processor) et une structure Mutexcontenant deux std::mutex (maint2thread, thread2main) verrouill�es � partir du constructeur. L�important ici c�est de pouvoir synchroniser avec le thread principal C�est pour �a que deux mutex sont n�cessaires : une pour donner le d�part, et une pour avertir de la fin.
    La classe dispose donc d�une m�thode pour acc�der � la structure contenant les mutex.
    Dans la m�thode play, on verrouille main2threadpour bien synchroniser.
    Il faudra d�verrouiller main2threaddans le main afin d�ex�cuter la suite de la m�thode play(premi�re boucle for dans le main).
    La deuxi�me boucle for dans le main verrouille thread2mainpour synchroniser le main avec les threads. Dans la m�thode play, avant de reboucler, thread2mainest d�verrouill�.
    Nom : threadingsynch.png
Affichages : 346
Taille : 21,3 Ko
    Sch�ma illustrant la synchronisation
    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
    75
    struct Mutex{
        std::mutex maint2thread, thread2main;
    };
     
    class Chan {
    private:
    	std::thread processor;
    	Mutex mut;
    	unsigned char id = 0;
    	static unsigned char chancount;
    	bool stopped = false;
    public:
    	Chan() {
    		std::thread p(&Chan::play, this);
            this->processor = std::move(p);
            mut.maint2thread.lock();
            mut.thread2main.lock();
            this->id = Chan::chancount++;
        }
     
        void play()
        {
        	while(true){
        		this->mut.maint2thread.lock();
        		if(this->stopped){
        			break;
        		}
        	    //std::cout << "Chan " <<  +this->id <<" play thread " << std::endl;
        	    for(int i = 0; i<LOOPS; ++i);
        	    //std::cout << "Chan " <<  +this->id <<" finish play thread " << std::endl;
     
        		this->mut.thread2main.unlock();
        	}
     
        }
     
        void wait(){
        	std::cout << "wait processor " <<  +this->id << " for finish" << std::endl;
        	this->processor.join();
        }
     
        void stop(){
        	std::cout << "stop processor " <<  +this->id << std::endl;
        	this->stopped = true;
        	this->mut.maint2thread.unlock();
        }
     
        Mutex* getMut(){
        	return &this->mut;
        }
     
    };
     
    int main(){
    	Chan chan[CHANS];
    	for(unsigned int j = 0; j < COUNT; ++j){
    		//std::cout << "*******************************"<<j<<"*******************************"<<std::endl;
    		for(short i=(CHANS-1); i >=0; --i){
    			chan[i].getMut()->maint2thread.unlock();
    		}
     
    		for(short i=(CHANS-1); i >=0; --i){
    			chan[i].getMut()->thread2main.lock();	
    		}
    		//std::cout<<"----add samples-----"<< std::endl;
    	}
     
    	for(short i=(CHANS-1); i >=0; --i){
    		chan[i].stop();	
    	}
     
    	for(short i=(CHANS-1); i >=0; --i){
    		chan[i].wait();	
    	}
    }
    Eh bien, en chronom�trant le temps �coul� pour le calcul s�quentiel et pour le calcul �parall�le�, je me suis rendu compte que l�approche multi-thread� est int�ressante lorsque la fonction play est vraiment co�teuse en temps. Or, en r�alit�, mon s�quenceur calcule l��chantillon d�un canal en 900 ns jusqu�� � peu pr�s 20000 ns (� cause des traitements d�effets s�rement). Et j�ai test� en mettant LOOPS � 66 (900 ns sur ma machine) et � 6666 (18000 ns) voire m�me plus et les r�sultats me montrent que l�approche thread� n�est pas du tout rentable pour mon cas! Du moins, vu comment je l�ai impl�ment�.
    Pourtant en th�orie, �a doit �tre beaucoup plus performant qu�en s�quentielle.
    Je met le doigt sur les boucles for dans le main g�rant les mutex et sur la performance des threads (changement de pile, contexte etc... c�est pas du vrai parall�lisme).

    Ma question : d�j�, est-ce que j�ai bien impl�ment� l�approche thread� ? Sachant que la synchronisation est obligatoire pour mon cas ou sinon j�aurais des threads qui iront plus vite que la musqiue !

    Deuxi�me question : comment vraiment parall�liser ? Et surtout efficacement. Le processeur de ma machine est quadric�ur, �a devrait donc le faire !
    Fichiers attach�s Fichiers attach�s

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Probl�me de lenteur d'un thread
    Par augur67700 dans le forum Threads & Processus
    R�ponses: 10
    Dernier message: 31/05/2013, 23h52
  2. Probl�me serveur multi-thread
    Par hebus44 dans le forum Entr�e/Sortie
    R�ponses: 2
    Dernier message: 14/11/2007, 22h32
  3. Probl�me Seveur multi-thread
    Par Doom2Darkness dans le forum C++
    R�ponses: 14
    Dernier message: 05/06/2007, 19h32
  4. problme de multi thread
    Par L4BiN dans le forum Concurrence et multi-thread
    R�ponses: 22
    Dernier message: 25/04/2007, 16h47
  5. R�ponses: 11
    Dernier message: 14/02/2006, 00h26

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