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 :

Multi-threading et dictionary.


Sujet :

C#

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 14
    Points
    14
    Par défaut Multi-threading et dictionary.
    Bonjour,

    Je travaille actuellement sur une application très gourmande en calcul, en fait il s'agit d'algorithme génétiques.
    Une première étape a été de vouloir suivre graphiquement à l'aide de zedGraph la façon dont évoluait ma population. J'ai donc lancé la partie de mon code gérant l'algo génétique dans un nouveau thread, et je récupère périodiquement des données concernant l'état de l'algo via un callBack.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // Callback
    public delegate void PointsDessin(int numGeneration, int Fitnessmax, int Fitnessmoy, int Distinct);
     
    public void dessine(int numGeneration, int Fitnessmax, int Fitnessmoy, int Distinct)
    {
    zgc.GraphPane.CurveList["Fitnessmax"].AddPoint(numGeneration, champion * multiplicateurY);
    zgc.GraphPane.CurveList["Fitnessmoy"].AddPoint(numGeneration, moyen * multiplicateurY);
    zgc.GraphPane.CurveList["Distinct"].AddPoint(numGeneration, distinct);
     
    refreshCourbes();
    }
    Ca ça marche bien, je construit dynamiquement mes courbes et je les affiche, sans freeze de mon WinForm. Pour info, j'ai en abscisse le nombre de générations, et en ordonnée 3 valeurs (Fitness la plus haute, Fitness moyenne de la population, nombre "d'individus" différents.)

    Maintenant, je voudrais pouvoir lancer plusieurs Threads gérant chacun une instance de mon algo, et moyenner leurs résultats.
    J'avais pensé à cette solution :
    - créer, par exemple pour la Fitnessmax, un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int nombreDeThreads = 2;
    int[][] Fitnessmax = new int [nombreDeThreads][];
    // suivie évidemment d'une boucle pour fixer la taille de chaque élément.
    pour chaque courbe.

    - Lors de la création du Thread, donner un numéro unique au thread via sa propriété name, et lors de l'appel du callback y ajouter ce numéro de thread,
    - Du coup j'aurais pu faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    public delegate void PointsDessin(int ThreadId, int numGeneration, int Fitnessmax, int Fitnessmoy, int Distinct);
     
    public void dessine(int ThreadId, int numGeneration, int Fitnessmax, int Fitnessmoy, int Distinct)
    {
    Fitnessmax[ThreadId][numGeneration] = Fitnessmax;
    // même chose pour Fitnessmoy et Distinct avec leurs tableaux de tableaux respectifs....
    // puis mettre à jour mes courbes avec un timer par exemple
     
    }
    La question que je me pose, c'est que pour moi en théorie je ne devrais pas avoir de problèmes de concurrence entre threads dans ma fonction dessine, car effectivement ils peuvent aller en exécuter le code en même temps, mais puisque qu'ils écriront chacun dans leur Fitnessmax[] identifié par ThreadId on n'aura pas de problème de recouvrement de données.
    Seulement ce que je vois un peu partout c'est qu'il vaudrait mieux locker mon tableau de tableau Fitnessmax[][] chaque fois que j'écris dedans. Cela m'ennuie pour des raisons de performance.

    Auriez-vous un avis éclairé sur la question?

    Si je ne suis pas très clair, n'hésitez pas à me demander des précisions ; les extraits de code que j'ai mis (et allégés) sont peut-être un peu justes.

    Ivan.

  2. #2
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 175
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 175
    Points : 25 116
    Points
    25 116
    Par défaut
    la lecture d'une meme variable sur plusieurs threads ne posent pas de problème

    ce qui pose problème c'est pas exemple la modification d'une collection (add, remove ...) pendant qu'il y en a un qui parcours la collection
    ou encore l'écriture d'une variable par rapport à sa valeur, si plusieurs thread font i = i + 1 ca sera fossé de temps en temps

    donc si tes threads ne modifie qu'un element du tableau chacun, je ne pense pas qu'il y aura des soucis

    enfin le mieux c'est de tester avec plein de threads, tu verras vite si ca coince !


    NB :
    pour du thread safe, il y a syncklock en vb.net (lock tout court en c# je crois) (tout le monde attend tant c'est pas déverrouillé
    mais aussi les readerwriterlock (et le nouveau de 2008 préfixé de slim), ces locks permettent de ne pas bloquer dans certains et de bloquer dans d'autres, les verrous dit "read" sont non bloquant, les verrous dit "write" sont bloquants, le write bloque les reads et les autres write et ne rentre que lorsque tout le monde a déverrouillé

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 14
    Points
    14
    Par défaut
    Ok, merci pour ta réponse, de toute façon comme tu dis le mieux c'est de tester.
    Fallait seulement que je rentre à la maison pour ça, au boulot je suis en punition depuis un an à faire du pl/sql...

    Je tâcherai de revenir poster sur le résultat de mes tests.

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    16
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Seine Maritime (Haute Normandie)

    Informations forums :
    Inscription : Décembre 2007
    Messages : 16
    Points : 14
    Points
    14
    Par défaut
    Ca ma l'air de bien fonctionner finalement.

    J'ai effectivement plusieurs threads qui écrivent dans le même Dictionary<int, List<int>>, où la clé du dictionnaire est un identifiant unique et le List<int> est ma liste de points, le tout sans problèmes.

    Par contre j'ai changé de stratégie niveau affichage : au lieu d'appeler mes threads depuis mon Form et d'y mettre un timer pour actualiser mes courbes jusqu'au plus petit numéro de génération atteint par le thread le moins avancé, j'ai créé une classe chargé de lancer les threads et de collecter les données qu'ils remontent, et qui signale via un évènement personnalisé à mon Form qu'il y a de nouveaux points à afficher.

    J'ai mis un peu de temps à monter mon truc à cause d'un problème assez vicieux : j'utilise un peu partout dans mon projet une classe statique contenant un Random....
    Or la classe Random n'est pas thread-safe, et je ne faisais pas de lock quand je faisais un Random.Next.
    J'obtenais des résultats complètements déconnants... dur dur de trouver la cause car quand on veut débugguer sous VS2008 une méthode appelée par plusieurs threads, le curseur de débogage saute allègrement d'une ligne à l'autre, en avant comme en arrière dans le désordre le plus total

    Bref, plutôt que de faire un lock chaque fois que je fais un Random.Next sur ma classe statique, j'en ai mis privé dans la classe du thread.

  5. #5
    Expert éminent sénior Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 175
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 175
    Points : 25 116
    Points
    25 116
    Par défaut
    pour le debuggage multithread il parrait qu'il y a un moyen de choisir le thread qu'on veut débugger et de pas voir les autres, peut etre dans la fenetre d'affichage des threads ...

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

Discussions similaires

  1. Tri multi-threadé
    Par Tifauv' dans le forum C
    Réponses: 8
    Dernier message: 28/06/2007, 09h00
  2. Réponses: 2
    Dernier message: 15/05/2004, 18h33
  3. Réponses: 16
    Dernier message: 30/01/2004, 11h05
  4. [VB6][active x] faire du multi-thread avec vb
    Par pecheur dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 20/05/2003, 12h01
  5. [Kylix] exception qtinft.dll et multi-threading
    Par leclaudio25 dans le forum EDI
    Réponses: 3
    Dernier message: 27/03/2003, 18h09

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