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 :

addition atomic de float ?


Sujet :

Threads & Processus C++

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 106
    Points : 63
    Points
    63
    Par défaut addition atomic de float ?
    Bonjour,

    Je cherche depuis une semaine, hélas sans succès, comment additionner 2 floats de manière atomique (plus précisement, comment ajouter une emplacement mémoire float à un autre emplacement mémoire float). Par "atomique", j'entend que cette opération puisse être effectuée depuis plusieurs threads différents sur le même emplacement mémoire, sans avoir recours à un mutex (qui ferait perdre trop de temps).
    Et j'ai juste besoin de faire une addition, pas d'implémenter toute une classe complète dédié à la gestion atomique de float (si jamais ca peut simplifier le problème...)

    Merci

  2. #2
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Peut-être que le mot clé volatile sera suffisant.

    Mais si l'addition nécessite une synchronization pour une raison ou pour une autre, cela ne résoudra pas le problème. Disons que si un thread fait une addition en même temps qu'un autre thread mais que l'ordre pour l'addition n'a pas d'importance, le mot clé volatile peut être utile ici.

    Le mot clé volatile signifie au compilateur de ne pas optimiser l'emplacement mémoire de la variable. Par exemple, lorsque deux threads utilisent la même variable, celui-ci peut positionner cette variable dans des registres propres aux threads. Du coup il y a deux copies de ta variable, pour des raisons d'optimisation. Le premier thread fait l'addition et la variable retourne à son emplacement d'origine. Le second thread fait l'addition, on va dire que c'est le dernier à s'exécuter, et la variable va retourner à son emplacement d'origine, écrasant la dernière valeur.

    Avec le mot clé volatile, la variable ne possédant pas de copie, le thread 1 fera l'addition et le thread 2 fera l'addition sur le résultat de l'addition du thread 1. Peut-être que c'est le resultat que tu souhaites.

    Mais si tu devais être certain que l'addition commence d'abord par le thread 1, puis le thread 2, dans cet ordre, une synchronisation devient indispensable.

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 106
    Points : 63
    Points
    63
    Par défaut
    L'ordre des additions n'a aucune importance, donc d'après ta description volatile pourrait répondre à mon problème;
    Par contre je ne saisis pas bien comment l'utiliser en pratique, voila un pseudo-code minimaliste qui correspond à mon cas pratique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    float destinationvalue=0.f;
    float addvaluethread1=2.f;
    float addvaluethread2=3.f;
     
    thread(float *destinationvalue, float *addvalue)
    {
       *destinationvalue+=*addvalue;
    }
    thread étant appelé en parallèle avec &destinationvalue, mais 2 &addvalue différents: au final j'attend que destinationvalue soit égal à 2+3=5, peu importe l'ordre des additions.
    Comment changerai tu cet exemple pour que volatile soit effectif ?

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    106
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 106
    Points : 63
    Points
    63
    Par défaut
    Bon j'ai essayé différents cas de figure avec volatile, malheureusement les threads se marchent quand meme sur les pieds, mon résultat final ne correspond pas à la somme de toutes les valeurs ajoutés...
    L'article wikipedia souligne d'ailleurs le fait que volatile n'est pas vraiment prévu pour protéger des variables d'un acces simultané en multithread: http://en.wikipedia.org/wiki/Volatile_variable

  5. #5
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Points : 4 732
    Points
    4 732
    Par défaut
    Volatile ne sert a rien ici et est hors propros. Il empêche juste le compilateur d'optimiser du code en fonction d'une variable qui POUR LUI lui ne semble ne jamais évoluer mais en fait si (variable décrivant l'état d'un bumper sur une carte électronique par exemple).

    Sinon pour une réponse précise, il faut du contexte, tu fais quoi, tu veux faire quoi, avec quels outils ?

    Car une solution pourrait se trouver dans std::atomic.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  6. #6
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    En effet cela ne marche pas. Je viens de comprendre pourquoi. J'utilise volatile, mais en conjonction avec InterlockedIncrement, et c'est finalement cette dernière qui s'occupe de l'aspect atomique. Le mot clé volatile permet d'éviter une optimisation indésirable du compilateur.

    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
    #include <Windows.h>
    #include <iostream>
     
    class CMyClass{
     
    public:
        CMyClass() : lValue(0){}
        volatile long lValue;
    };
     
    DWORD WINAPI MyThreadFunction(LPVOID lpParam){
     
        CMyClass* theClass = (CMyClass*)lpParam;
     
        /*for(int i = 0; i < 100000; i++)
           theClass->lValue += 1;*/
     
        for(int i = 0; i < 100000; i++)
            InterlockedIncrement(&theClass->lValue);
     
        return 0L;
    }
     
    void main(){
     
        HANDLE hThread[3];
        CMyClass theClass;
     
        for(int i = 0; i < 3; i++)
            hThread[i] = CreateThread(NULL, 0, MyThreadFunction, (LPVOID)&theClass, 0,NULL);
     
        WaitForMultipleObjects(3, hThread, TRUE, INFINITE);
     
     
        for(int i = 0; i < 3; i++)
            CloseHandle(hThread[i]);
     
        std::cout << theClass.lValue << std::endl;
     
        char c;
        std::cin >> c;
    }
    J'ai vu que sous Windows tu as des fonctions pour l'addition atomique :

    http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx

    C'est pour Windows et je n'ai pas vu de fonction d'addition atomique pour des float.

  7. #7
    Membre émérite
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 764
    Points : 2 705
    Points
    2 705
    Par défaut
    Tu devrais aller voir le code de Loki, dans lequel a été défini la fonction suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    static IntType AtomicAdd(volatile IntType& lval, IntType val);

Discussions similaires

  1. Addition sur des floats
    Par Invité dans le forum C
    Réponses: 9
    Dernier message: 26/02/2010, 06h55
  2. [FLOAT] Problème sur addition et soustraction
    Par BerBiX dans le forum Java ME
    Réponses: 5
    Dernier message: 10/10/2008, 17h33
  3. ORA 01722, addition de float
    Par triworld19 dans le forum Oracle
    Réponses: 6
    Dernier message: 29/11/2007, 11h01
  4. addition entre float
    Par clairette dans le forum Langage
    Réponses: 6
    Dernier message: 28/06/2006, 12h17
  5. [Math]Addition de deux float : résultat faux !!!
    Par toctof dans le forum Général Java
    Réponses: 4
    Dernier message: 20/05/2005, 11h02

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