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 :

programmation multithread en C++


Sujet :

C++

  1. #21
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Pour lire une variable partagee entre plusieurs threads, il faut d'abord
    qu'elle soit en memoire et pas assignee a un registre. Et la, il n'y a
    jamais de probleme en C ou en C++: les API des threads et les regles de ces
    langages sont telles que si la variable est accessible par plusieurs
    threads, elle doit se trouver en memoire.

    Il faut aussi que les acces a ces variables soient entourees par les
    instructions de barrieres memoires pertinentes. Pas tellement de secret,
    soit le compilateur les ajoute tout seul (seul cas potentiel que je
    connaisse pour le C et le C++: utilisation de volatile sous Windows avec
    les compilateurs de MS d'apres ce que j'ai compris; et encore je me demande
    si le document que j'ai lu ne decrit pas l'intention de MS pour les
    compilateurs futurs plus que la situation actuelle), soit on les mets
    explicitements (par des fonctions intrinseques, par l'utilisation de
    l'assembleur ou par effet de bord des fonctions de synchronisation de
    l'OS). Si on ne le fait pas, le processeur peut se mettre a faire
    des optimisations qui font qu'on accede pas aux bonnes valeurs ou pas dans
    le bon ordre.

    Finalement, il faut que le compilateur n'optimise pas de telle
    maniere que les precautions precedentes soient inutiles (que ce soit en
    reorganisant le code, en conservant dans des registres ou dans l'autres
    zones de la memoire des resultats qui devraient etre recalcules). Donc le
    compilateur doit etre place en mode multi-thread.

    volatile (en C et en C++ et hors compilos MS; en Java c'est different) ne
    sert a rien dans tout ceci pour du multithread. Plus precisement, il
    resoud uniquement le dernier point et de maniere moins efficace que
    necessaire. volatile a ete concu pour l'acces a des IO mappees en memoire
    -- donc pour des drivers -- et n'est pas utile en dehors (voir par exemple
    les messages de John Mashey sur le sujet sur comp.arch).

  2. #22
    screetch
    Invité(e)
    Par défaut
    Pour le code atomique il y en a tres peu, en fait il suffit de jeter un coup d'oeil aux fonctions de l'APi windows InterlockedXXX, je crois qu'a peu de chose pres tu auras la liste. En gros ca sert pour des choses simples, par exemple une classe de refcounting utilise ces primitives sur les refcount pour avoir un refcounting thread-safe.

    Ensuite, si tu utilises volatile tes donnees resteront bien en memoire, pas dans le registre CPU.

    Pour les memory barrier, le compilateur ne reordonnera pas ca, mais pour etre franc je ne sais pas pourquoi. Principalement parce que la memory barrier est une instruction asm et que le compilo va en quelques sortes "flusher" ses instructions pour mettre les tiennes.
    Ici je connais pas la reponse, c'est au dela de mes competences, mais sois sur que meme si le compilo a reordonne des instructions, il ne mettra pas l'ecriture que tu as demande avant la memory barrier... apres (j'espere etre clair)

    Pour le cache CPU, ton seul role est de verifier que ca ne reste pas en registre a cause de l'optim (CF exemple du vecteur) auquel cas il faudra passer la donner sensible en volatile. Ce qui fait partie du cache memoire du processeur (des processeurs d'ailleurs) fonctionne, c'est a dire que dans un environnement multi core ils sauront partager la memoire correctement. Un processeur peut "savoir" ce que l'autre a en cache, et ce qui a ete modifie.
    Lorsque tu as modifie une valeur, le processeur la maintient dans son cache sans l'ecrire. Lorsque l'autre processeur demande la valeur en memoire, il sait que le processeur 1 possede une valeur a jour, il la demande.

    Cela se traduit par une perte importante de perf dans ce cas (en gros le CPU1 est tout content il l'a en cache, le CPU2 doit traverser tous les caches, causer du pays au CPU1, la donnee traverse tous les caches du CPU1 pour tomber en memoire centrale puis le CPU2 la fait remonter jusqu'au registre). C'est l'horreur mais c'est le CPU qui gere ca.

    Pour debugger une application multithread, tu fais comme moi, tu vas voir l'equipe techos qui gere le multithread et tu leur cause du pays!!!

    serieusement le cas de bug le plus frequent est l'cces a une donnee mal verouillee ce qui se traduit par un comportement zarbi a l'execution => chercher qui y accede sans la verouiller.
    Nous utilisons des tests automatiques qui finissent par trouver les bugs.
    Un autre cas frequent de bug est l'interlocking : j'attends que le thread 2 finisse mais le thread 2 attends le thread 1, bref on risque pas de s'en sortir.
    Pour ocntrer cela, je crois qu'il existe un outil de SysInternals qui peut t'afficher la liste des threads qui possedent les mutex/semaphore. En general ce qui se passe c'est que tu lock deux mutex d'affilee mais l'autre trhead aussi, mais il les lock dans l'ordre inverse.

    En gros

    A.lock()
    B. lock()

    et pour le second thread

    B.lock()
    A.lock()

    alors mettons que je lock A, ensuite c'est au tour du thread 2, il lock B, il me rend la main, je veux locker B mais je peux pas, je dois attendre, et le thread 2 va attendre que je libere A.

    Pour cela il faut definir un ordre de locking.

    Les libs aident a faire intervenir ce genre de probleme en forcant un "yield" apres avoir locke, comme ca tu favorises les chances d'un autre thread de voler un lock dont tu aurais besoin. Ca permet de voir ce genre de probleme plus vite. Des fois aussi apres le lock on endort le thread sur une longue (100 millisecondes) periode ce qui augmente une fois de plus les chances qu'il se fasse voler un thread vital et se retrouve en dead lock

    Kekya d'autre encore...

    Apres on tombe plutot sur des problemes de performance a cause des priorites

    un thread 1 a une priorite tres faible, il est execute peu souvent.
    Un thread 2 a une priorite tres forte
    un thread 3 aussi

    le thread 1 vole le mutex A
    le thread 2 en a besoin; malheureusement le thread 1 l'a => le thread 2 est en pause
    le thread 3 a une forte priorite, donc il tourne tout le temps
    le thread 1 n'a pas le temps de lacher son lock, et il bloque le thread 2 qui lu iavait une forte priorite.


    Selon les libs, i lexiste des solutions, l'une d'ntre elle consistant a augenter la priorite de thread1 a celle de thread2 si celui ci demande le lock : alors thread1, "conscient" qu'il bloque un autre thread, va avoir plus de temps CPU et lacher le lock plus vite.

    J'ai pas fait le tour, ce ne sont que quelques possibilites c'est tellement dur le multithread

  3. #23
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    Pour lire une variable partagee entre plusieurs threads, il faut d'abord
    qu'elle soit en memoire et pas assignee a un registre. Et la, il n'y a
    jamais de probleme en C ou en C++: les API des threads et les regles de ces
    langages sont telles que si la variable est accessible par plusieurs
    threads, elle doit se trouver en memoire.

    Il faut aussi que les acces a ces variables soient entourees par les
    instructions de barrieres memoires pertinentes. Pas tellement de secret,
    soit le compilateur les ajoute tout seul (seul cas potentiel que je
    connaisse pour le C et le C++: utilisation de volatile sous Windows avec
    les compilateurs de MS d'apres ce que j'ai compris; et encore je me demande
    si le document que j'ai lu ne decrit pas l'intention de MS pour les
    compilateurs futurs plus que la situation actuelle), soit on les mets
    explicitements (par des fonctions intrinseques, par l'utilisation de
    l'assembleur ou par effet de bord des fonctions de synchronisation de
    l'OS). Si on ne le fait pas, le processeur peut se mettre a faire
    des optimisations qui font qu'on accede pas aux bonnes valeurs ou pas dans
    le bon ordre.

    Finalement, il faut que le compilateur n'optimise pas de telle
    maniere que les precautions precedentes soient inutiles (que ce soit en
    reorganisant le code, en conservant dans des registres ou dans l'autres
    zones de la memoire des resultats qui devraient etre recalcules). Donc le
    compilateur doit etre place en mode multi-thread.

    volatile (en C et en C++ et hors compilos MS; en Java c'est different) ne
    sert a rien dans tout ceci pour du multithread. Plus precisement, il
    resoud uniquement le dernier point et de maniere moins efficace que
    necessaire. volatile a ete concu pour l'acces a des IO mappees en memoire
    -- donc pour des drivers -- et n'est pas utile en dehors (voir par exemple
    les messages de John Mashey sur le sujet sur comp.arch).
    Dans ce cas tu vas m'expliquer pourquoi le programme que j'ai ecrit plus haut avec un vector attend indefiniment :-/

    VOLATILE CA SERT!!!!!!!

    La definition de volatile c'est que la valeur peut etre changer a l'exterieur du contexte d'execution actuelle et que l'on ne peut pas faire de suppsoition sur la persistance de la donnee. Cela peut etre du au fait que c'est une IO mappee, au fait qu'un autre thread le modifie, cela n'a pas d'importance. Le resultat est que le compilateur doit recuperer la valeur de la memoire a chaque fois qu'il l'utilise car un facteur exterieur peut l'avoir changé.

  4. #24
    Membre émérite
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    780
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2006
    Messages : 780
    Par défaut
    je déconseillerais peut-être de programmer en multithread en faisant juste des while( a )

  5. #25
    screetch
    Invité(e)
    Par défaut
    on a plus le droit aux boucles while dans la programmation multithread ?

  6. #26
    Membre émérite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    1 064
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2005
    Messages : 1 064
    Par défaut
    Citation Envoyé par Jean-Marc.Bourguet Voir le message
    En l'absence de doc, on ne peut que supposer que ce c'est pas safe.

    (Par exemple, qu'est-ce qui t'indique que la gestion de la memoire par les allocateurs est thread-safe?)
    C'est possible, mais on pourrait aussi dire la mème chose pour malloc et free. Et si ces fonctions ne sont pas thread safe,... la seule conclusion qu'on peut en tirer,... c'est qu'il est impossible de faire du multithread en C et C++. Alors sérieux, tu connais un seul développeur de compilo qui oserait fournir une bibliothèque standard 100% inutilisable dans un environnement pro (tout le monde a besoin de threads)? Normalement les allocateurs réutilisent new ou mallocs. Si ils devaient être tunés plus en profondeur, le multithread serait tout de même à l'ordre du jour.
    Il n'y a pas que le standard, il y a aussi la loi du marché qui oblige les concepteurs à faire un bon boulot!

  7. #27
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par screetch Voir le message
    Dans ce cas tu vas m'expliquer pourquoi le programme que j'ai ecrit plus haut avec un vector attend indefiniment :-/
    J'ai pas vu un programme complet. Suivant ce qu'il y a autour, ou tu te trompes car ça fonctionne, ou tu te trompes car volatile ne règle pas le problème.

    VOLATILE CA SERT!!!!!!!
    Ca sert à rien de crier. Ca ne change pas le fait que volatile ne sert à rien en ce qui concerne le multithread.

    La definition de volatile c'est que la valeur peut etre changer a l'exterieur du contexte d'execution actuelle et que l'on ne peut pas faire de suppsoition sur la persistance de la donnee. Cela peut etre du au fait que c'est une IO mappee, au fait qu'un autre thread le modifie, cela n'a pas d'importance. Le resultat est que le compilateur doit recuperer la valeur de la memoire a chaque fois qu'il l'utilise car un facteur exterieur peut l'avoir changé.
    Le problème, à nouveau, c'est que ça ne suffit pas, il faut en plus les instructions de barrière mémoire pour assurer la cohérence entre les caches dans les systèmes multiprocesseurs.

  8. #28
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par zais_ethael Voir le message
    C'est possible, mais on pourrait aussi dire la mème chose pour malloc et free. Et si ces fonctions ne sont pas thread safe,... la seule conclusion qu'on peut en tirer,... c'est qu'il est impossible de faire du multithread en C et C++. Alors sérieux, tu connais un seul développeur de compilo qui oserait fournir une bibliothèque standard 100% inutilisable dans un environnement pro (tout le monde a besoin de threads)? Normalement les allocateurs réutilisent new ou mallocs. Si ils devaient être tunés plus en profondeur, le multithread serait tout de même à l'ordre du jour.
    Il n'y a pas que le standard, il y a aussi la loi du marché qui oblige les concepteurs à faire un bon boulot!
    Les versions de la bibliothèque standard qui sont aptes à être utilisées en multithread l'indiquent dans leur doc. Et il faut généralement l'indiquer lors de la compilation (soit flag du compilateur, soit define, soit les deux). Et fournir plusieurs versions de la bibliothèque est une chose qui se fait.

  9. #29
    screetch
    Invité(e)
    Par défaut
    les barrieres memoires ne servent pas a ca.

    VOLATILE a lui tout seul effectue cela.

    Les barrieres memoires, comme je l'ai explique plus haut, empechent le controleur memoire de reordonnancer les instructions d'ecriture en memoire (en partie)

    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
    #include <cstdio>
    #include <windows.h>
     
    struct ThreadData
    {
    	bool ready;
    	int  data;
    };
     
     
    int thread1(ThreadData* data)
    {
    	printf("before : %d\n", data->data);
    	while(! data->ready) /* wait*/;
    	printf("after : %d\n", data->data);
    	return 0;
    }
     
     
    int main(int argc, char *argv[])
    {
    	ThreadData data;
    	data.ready = false;
    	data.data = 0;
    	HANDLE t = CreateThread(0, 12000, (LPTHREAD_START_ROUTINE)thread1, (void*)&data, 0, 0);
    	if(!t)
    		return 1;
    	Sleep(2000);
    	data.data = 12;
    	data.ready = true;
    	WaitForSingleObject(t, INFINITE);
    	return 0;
    }
    essaye ce code, en release, sous visual studio, ou avec mingw.

    Passe les variables en volatile, cela marchera.

    http://en.wikipedia.org/wiki/Memory_barrier

    Je le repete (j'espere pour la derniere fois) : volatile et les memory barriers ne sont pas lies bien qu'utilises conjointement; ils ne resolvent pas le meme probleme; accessoirement meme corrige comme plus haut, le programme a besoin de memry barriers; neanmoins sans volatile il part dans une boucle infinie et ce n'est PAS un probleme de reordonnancement de l'ecriture memoire.........

  10. #30
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    loufoque, me dire que j'ai rien compris, tout en me proposant ensuite des solutions basées sur la chance, merci bien je m'en passerais. L'objectif du topic est de trouver des solutions, de la doc, etc . . ., et si ton but est de me dire, laisse tomber tu est trop con pour comprendre, passe ton chemin.
    Malheureusement pour toi, tu ne comprends pas le français, et c'est dommage.
    J'ai dit que volatile était à ne surtout pas utiliser.

    Je t'ai expliqué comment fonctionnaient les mutexes et les verrous et t'ait plutôt conseillé d'utiliser de la transmission de messages.
    Je t'ai redirigé vers un message que j'ai écrit aujourd'hui même où j'ai expliqué certaines choses plus en profondeur.

    Bref, que te faut-il de plus ? Probablement des outils concrets.
    Pour créer des threads, tu as boost.thread. Pour gérer les messages, tu peux par exemple utiliser carrément des tubes ou similaire, ça reste le plus simple, et ça s'intègre bien avec tout ce qui est réseau (du moins sous linux). Tu peux peut-être aussi trouver un moyen de stocker des données dans une queue concurrente qui peut te servir pour faire une queue de messages. En simple il y a aussi tout ce qui est appel de fonction asynchrone, active object etc. Si tu veux un framework de transmission de message complet, regarde du côté de Channel ou Join. Il y aussi tout ce qui est dérivé de MPI.
    Personnellement, je programme relativement peu d'applications concurrentes en C++, préférant Erlang pour ce genre de truc. Il y a en fait beaucoup de projets différents pour la transmission de message mais aucun standard établi.

    Si tu préfères les mutexes et les verrous, boost.thread devrait avoir tout ce dont tu as besoin.

  11. #31
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Citation Envoyé par screetch Voir le message
    serieusement le cas de bug le plus frequent est l'cces a une donnee mal verouillee ce qui se traduit par un comportement zarbi a l'execution => chercher qui y accede sans la verouiller.
    Ce cas ne se produit jamais si on utilise des patterns éprouvés, dont par ex la boîte aux lettres est le plus simple à mettre en place, comme il a déjà été cité précédemment par loufoque notamment.
    Mais comme ça n'a pas eu l'air de paraître lumineux j'en remets une couche
    Comme souvent pour éviter de mettre en place une solution douloureuse (comment déboguer des threads qui s'entrelacent) le plus efficace est d'éviter le problème (ne pas les entrelacer par construction).
    C'est vrai que la littérature n'est pas spécialement abondante sur le sujet mais il y a tout de même le Patterns for Concurrent and Networked Objects qui est un classique...

    Peut-être que dans 0,01% des cas on avoir besoin de gérer soit même un mutex sur une variable, mais c'est la porte ouverte à toutes les fenêtres !

    Personnellement quand je peux éviter une compléxité inutile je n'hésite pas.

    MAT.

  12. #32
    Membre éprouvé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Par défaut
    Oh, oui tu as raison. En fait je comptait creer un sorte de "thread manager" pour mon application, dans laquelle je me casse la tete une fois pour toutes sur ce probleme.

    Pas question de coller des locks ou des signaux partout dans le programme, c'est le moyen ideal d'en oublier un, et de passer des heures a débugguer.

    loufoque > bon, sans rancunes ? Je t'en veux pas en fait, tu as de bons conseils .

    Mat007 > Merci pour le lien, ca a l'air tres complet et je pense que ca va m'apporter pas mal de solutions. je vais passer un peu de temps a decortiquer ca.

  13. #33
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Citation Envoyé par screetch Voir le message
    les barrieres memoires ne servent pas a ca.
    VOLATILE a lui tout seul effectue cela.

    Les barrieres memoires, comme je l'ai explique plus haut, empechent le controleur memoire de reordonnancer les instructions d'ecriture en memoire (en partie)
    Elles n'empèchent pas le reordonnancement. Ce qu'elles font, c'est plus faible que cela, elles iimposent des contraintes (lesquelles précisément dépend de l'instruction utilisée) sur l'ordre dans lequels les processeurs d'un système voient les effets des différentes instructions. Ce qui impose une synchronisation des caches qui peut ne pas avoir lieu sans elles.

    Passe les variables en volatile, cela marchera.
    Ca ne marchera pas sur un bi processeurs alpha.

    Je le repete (j'espere pour la derniere fois) : volatile et les memory barriers ne sont pas lies bien qu'utilises conjointement; ils ne resolvent pas le meme probleme;
    Nous sommes presque d'accord. Je pense qu'ils ne doivent pas être utilisé conjointement. Le problème pour lequel volatile a été conçu c'est un problème monothread avec soit intervention extérieure, soit signaux.

    Le problème pour lequel les barrières mémoires ont été conçues, c'est celui de la synchronisation entre processeurs.

    Oui, il faut que le compilateur n'optimise pas en contrecarrant l'effet de ces instructions -- je l'ai écrit plus haut. Oui volatile est un moyen si on l'applique assez généreusement. Mais il faut trop. Et il n'est pas nécessaire si le compilateur utilisé sait qu'il y a une barrière mémoire. Compare avec gcc sur x86 ce qui est généré avec et sans l'appel a __builtin_ia32_mfence (il faut -msse2 pour que le builtin soit compris) dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    int f(char* ptr) {
      while (!*ptr)
        __builtin_ia32_mfence(); 
    }
    Sans l'appel, l'optimiseur génère une boucle infinie, avec il sait qu'il doit relire.

    accessoirement meme corrige comme plus haut, le programme a besoin de memry barriers; neanmoins sans volatile il part dans une boucle infinie et ce n'est PAS un probleme de reordonnancement de l'ecriture memoire.........
    Allez, on approche. Tu admets maintenant que volatile n'est pas suffisant. Bientôt tu vas comprendre qu'il n'est pas nécessaire.

  14. #34
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    À noter que les builtins de GCC pour faire des opérations atomiques (fetch and add, compare and swap) font bien sûr une memory barrier.
    http://gcc.gnu.org/onlinedocs/gcc-4....tomic-Builtins

  15. #35
    screetch
    Invité(e)
    Par défaut
    Les memory barriers en elles memes forcent des choses (pour ne pas les nommer, comment ecrire la memoire).

    L'effet pervers de ce que tu dis c'est que EN PLUS le fait de mettre une memory barrier change le comportement du compilateur qui alors arrete d'effectuer des optis. Ce qui se passe :

    - En mode mono proc, les intrinsic sont remplaces par des NOP mais les optis de registres ont disparus comme si j'avais marque toute les variables externes/statiques
    - En mode multi proc, la readwritebarriere (intrinsic de GCC et intrinsic de Visual) non seulement desactive l'opti mais EN PLUS rajoute la (vraie) memory barrier qui va empecher le reordonnencement de la memoire.

    On a donc si je resume :
    - La memory barrier intrinsique qui propage du volatile et insere la memory barrier "CPU"
    - La memory barrier CPU qui empeche le reordonnencement
    - Le mot cle volatile qui fait a la paluche ce que fait en auto la MemoryBarrier intrinsic.

    Cela vient du fait que nous ne nommons pas une memory barrier de la meme facon. De plus je ne me base pas sur les intrinsic du compilateur pour definir le comportement. Une memory barrier "de cpu" (le type qui ne change pas l'etat du compilateur) peut etre effectuee sur n'importe quel compilo en assembleur meme sans l'intrinsic.

    Ce dont tu parles est compilateur specifique (et pas specifique au langage) malheureusement. Cela fonctionnerait-il sur BCBuilder ?

  16. #36
    Expert confirmé

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Par défaut
    Ce dont tu parles est compilateur specifique (et pas specifique au langage) malheureusement. Cela fonctionnerait-il sur BCBuilder ?
    Pour le moment, le langage ne connaît rien des threads. Dans C++0X, on est en train d'ajouter les threads et il y aura un modèle de mémoire et des primitives de synchonisations (voir http://www.open-std.org/jtc1/sc22/wg...007/n2381.html et les autres documents du comité); les compilateurs vont devoir alors générer du code qui les respectent et en tenir compte lors des optimisations.

  17. #37
    screetch
    Invité(e)
    Par défaut
    sachant que BCBuilder est deja peu compatible (surtout pour les templates) et genere du code i386 (et pas du i486 hein) je suppose que meme apres l'harmonisation des compilateurs au standard C++0x il sera encore a la masse.

    Je pense que nous pouvons arriver a un compromis en disant que je defendais le principe de la volatilite plus que le mot cle, et que tu englobais la volatilite dans les read/write barrier ce qui est plutot le fait du compilo que celui de l'instruction asm.

    Nous pouvons donc appeler ca un match nul ?

    belle joute ^^

  18. #38
    Membre éprouvé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Par défaut
    Il y a des dates qui sont avancées ? Pour gcc par exemple ?

    Sinon, est-ce que les bibliotheaques genre pthread ou bien Boost.threah declenche des memory barrier a certains moments ? et si oui, quand (je viens de fouiner dans la doc de Boost.thread, et j'ai pas trouvé) ?

  19. #39
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Seul le spinlock a besoin de ce genre de choses. En général, le spinlock reste néanmoins implémenté par la bibliothèque d'interfaçage que fournit le système, tel que pthread.
    Les autres types de verrous, de par leur nature, ne peuvent être gérés par l'ordonnanceur des threads (le noyau en général). En effet le thread est mis en sommeil puis est réveillé ultérieurement.

  20. #40
    Membre éprouvé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Par défaut
    Prennons un exemple :

    J'ai une donnée paratgée entre plusieurs threads. J'utilise un mutex pour en proteger l'acces.

    Le thread 1 lock le mutex. Il fait ensuite ses petites affaires avec la ressource.
    Pendant ce temps, le thread 2 lock lui aussi le mutex. Il est donc mis en attente jusqu'a ce que le thread 1 libere celui-ci.
    Le thread 1 libere le mutex. A ce moment la, le thread 2 commence a modifier a son tour la ressource.

    Et c'est la ou ca peut poser probleme sans memory barrier. Qui nous dis que le thread 1 a tout bien remis en memoire avant de liberer le mutex ? S'il ne l'avait pas fait, le thread 2 va droit a la catastrophe (un seg fault si c'est de la liste chainée la ressource par exemple).

    D'ou la question. Est-ce que je dois faire moi meme la memory barrier quand j'utilise un mutex, ou bein est-ce que la lib le fait a ma place ?

Discussions similaires

  1. Qt et la programmation multithread
    Par yan dans le forum Multithreading
    Réponses: 1
    Dernier message: 06/10/2011, 23h58
  2. question sur un programme multithread
    Par blueLight dans le forum Windows
    Réponses: 10
    Dernier message: 17/07/2008, 09h23
  3. Programmation multithread pour débutant
    Par oodini dans le forum C++
    Réponses: 5
    Dernier message: 07/03/2008, 14h14
  4. temps d'execution d'un programme multithread
    Par La taupe dans le forum C
    Réponses: 2
    Dernier message: 10/01/2007, 17h44
  5. Programmation multithreads ?
    Par rulianf dans le forum C++
    Réponses: 2
    Dernier message: 03/02/2006, 20h17

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