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

Multithreading Discussion :

qrand : toujours le même nombre 'aléatoire" dans tous les fils


Sujet :

Multithreading

  1. #1
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations forums :
    Inscription : Août 2013
    Messages : 6
    Points : 2
    Points
    2
    Par défaut qrand : toujours le même nombre 'aléatoire" dans tous les fils
    Bonjour à tous,
    j'ai un problème de qrand qui génère toujours le même nombre. Pourtant j'utilise une seule fois qsrand pour initialiser le RNG. Voilà l'organisation du code :
    Il y a 2 threads qui font chacun des calculs,

    1-ils sont crées et initialisés depuis main (qsrand est appelé à l'initialisation de chaque thread)
    2-ensuite ils sont executés (run) en même temps
    3-le premier qui a fini attend l'autre (wait)
    4-des opérations de synchro des données des thread sont faites
    5-ils sont à nouveaux exécutés (run), on recommence donc à 2-

    etc etc

    Dans le run de chaque thread, j'ai besoin de nbr aléatoires mais c'est toujours les mêmes qui sont générés.
    Pourriez vous me dire où ça cloche ? c'est comme si à chaque run il y avait un appel à qsrand avec le même seed, ce qui n'est pas dans mon code.
    Merci !

  2. #2
    Futur Membre du Club
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2013
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2013
    Messages : 2
    Points : 6
    Points
    6
    Par défaut
    Bonjour,

    Il faut initialiser qsrand de la sorte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    qsrand(static_cast<uint>(QTime::currentTime().msec()));

  3. #3
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations forums :
    Inscription : Août 2013
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    bonjour,
    c'est dèjà ce que je fais dans l'initialisation des threads, mais les nombres crées à chaque run (plusieurs centaines d'appels aux run) sont tjrs les mêmes. C'est à dire que les nombres générés par le run N et le run N+1 sont les mêmes.

  4. #4
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2017
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Mai 2017
    Messages : 18
    Points : 27
    Points
    27
    Par défaut
    qsrand() une seule fois (peut-être dans le main) puis qrand() ?
    Je comprends que tu initialises dans le tread ...
    Si non, il faut que ton tread soit au dessus de la milliseconde
    .msec()
    Et encore :
    Note that the accuracy depends on the accuracy of the underlying operating system; not all systems provide 1-millisecond accuracy.

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2017
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Mai 2017
    Messages : 18
    Points : 27
    Points
    27
    Par défaut
    Cela doit rester portable ?

  6. #6
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations forums :
    Inscription : Août 2013
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Pas d'utilité de portabilité, c'est destiné à windows.
    Mettre qsrand() dans le run ne peut pas marcher : les run ont une durée d’exécution très constante et de l'ordre de quelque millisecondes. Donc on aurait plus de caractère aléatoire.

    A mon avis il y a quelque chose que je ne vois pas, genre une initialisation systématique du RNG à chaque run, et qu'il faudrait désactiver.
    j'aimerais bien comprendre...

  7. #7
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2017
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Mai 2017
    Messages : 18
    Points : 27
    Points
    27
    Par défaut
    Alors, a mon avis, tu devrais utiliser srand de windows, ne serait-ce que pour tester.
    Perso, j'ai vu des rafraichissements de timer largement au dessus de 100 ms.
    Je cherchais un truc plus rapide, mais c'est compliqué avec Qt.
    Je n'ai eu que des problèmes sur ce sujet ... ce qui n'est pas anormal.
    Si tu fais mieux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     void seedRandom()
      962 {
      963     static bool randomSeeded = false;
      964     if (!randomSeeded) {
      965         if (!QTest::seedSet) {
      966             QElapsedTimer timer;
      967             timer.start();
      968             QTest::seed = timer.msecsSinceReference();
      969         }
      970         qsrand(QTest::seed);
      971         randomSeeded = true;
      972     }
      973 }

  8. #8
    Membre confirmé
    Profil pro
    Développeur informatique
    Inscrit en
    Mai 2012
    Messages
    163
    Détails du profil
    Informations personnelles :
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2012
    Messages : 163
    Points : 624
    Points
    624
    Par défaut
    Pourquoi ne pas utiliser les threads c++11 (seed_seq ou random_device) ?

    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
        random_device rd;
     
        mt19937 engine1(rd());
        uniform_int_distribution<int> dist1(1, 100);
     
        mt19937 engine2(rd());
        uniform_int_distribution<int> dist2(1, 100);
     
        auto f = [] (mt19937 &e, uniform_int_distribution<int> &d, int &x) {x=d(e);};
     
        for (int i=0; i<10; i++) {
            int x1, x2;
            thread th(f, ref(engine1), ref(dist1), ref(x1));
            f(engine2, dist2, x2);
            th.join();
            cout << x1 << " " << x2 << endl;
        }

  9. #9
    Candidat au Club
    Homme Profil pro
    Inscrit en
    Août 2013
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Morbihan (Bretagne)

    Informations forums :
    Inscription : Août 2013
    Messages : 6
    Points : 2
    Points
    2
    Par défaut
    Bonjour tous,
    lambe021 : j'avais commencé avec le srand et rand du C, mais le problème était déjà le même : chaque thread.start semble réinitialiser le RNG.
    Ensuite je suis passé à qrand et qsrand de Qt, car il est "thread safe", mais ça n'a rien changé : toujours les mêmes nombres sont produits à chaque nouvelle exécution de run.

    Je ne souhaite pas utiliser la fonction d'initialisation du RNG pour obtenir de l'aléatoire, ce n'est pas l'esprit d'un RNG. On utilise cette fonction pour reproduit les mêmes séries de nombres aléatoires. Et en plus comme l'initialisation va être faite à une fréquence quasi constante, on n'aura pas le caractère aléatoire.

  10. #10
    Nouveau membre du Club
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mai 2017
    Messages
    18
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Mai 2017
    Messages : 18
    Points : 27
    Points
    27
    Par défaut
    J'ai fait quelques testes de mon coté et, effectivement, cela devrait marcher.
    Je viens de voir cela :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    qsrand(QThread::currentThreadId());
    int a = (int)qrand() % 100;
    Je vais essayer de compiler le projet.
    http://tvaira.free.fr/projets/activi...qt-threads.pdf

    Chez moi, cela marche :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    qsrand((int) QThread::currentThreadId());
    int a = (int)qrand() % 100;
    Avec l'architecture du projet du dessus.

  11. #11
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Je présume que tu as une classe qui dérive de quelque chose comme de QApplication, de QMainWindow, ou quelque chose du genre?

    Place Qsrand dans le constructeur de cette classe (ou dans n'importe quelle fonction appelée par le constructeur dont tu auras la certitude qu'elle ne sera plus jamais appelée par la suite), et ton problème sera réglé, sous réserve, bien sur, que dex (ou plusieurs) threads ne demandent pas un nombre aléatoire "en même temps" (c'est à dire avant qu'un délais correspondant au délais le plus court représentable sur ton système ne se soit écoulé)
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Réponses: 1
    Dernier message: 29/03/2014, 20h55
  2. Réponses: 5
    Dernier message: 12/12/2010, 23h04
  3. [AC-2007] Copie d'un champ dans tous les enregistrements (même champ)
    Par toumack dans le forum IHM
    Réponses: 6
    Dernier message: 26/09/2009, 23h31
  4. Augmenter le nombre de fenêtres dans tous les programmes xp
    Par pierrot67 dans le forum Windows XP
    Réponses: 2
    Dernier message: 17/07/2007, 12h19

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