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 :

Threads et nombre aléatoire


Sujet :

C++

  1. #41
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Citation Envoyé par Moi-même
    Et le comportement observé correspond au fonctionnement habituel des fonctions non-réentrantes de la CRT de Microsoft: Les données statiques [de la CRT] sont locales à un thread, les fonctions sont donc thread-safe (mais pas réentrantes).
    Renseigne-toi sur les spécificités de Windows et des compilateurs prévus pour, avant de partir d'exemples incompatibles (POSIX).
    Et notamment, sur l'attribut __declspec(thread).

    PS: À aucun moment je n'ai contesté que les données était faussées sous POSIX : Je dis seulement qu'elle ne le seront pas sous Windows, même si ce n'est pas explicitement documenté pour cette fonction-là : En règle générale, les fonctions non-réentrantes de Microsoft sont thread-safe.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  2. #42
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    PS: À aucun moment je n'ai contesté que les données était faussées sous POSIX : Je dis seulement qu'elle ne le seront pas sous Windows, même si ce n'est pas explicitement documenté pour cette fonction-là : En règle générale, les fonctions non-réentrantes de Microsoft sont thread-safe.[/QUOTE]

    Non, t'as dis "probablement" et "probable"
    Et tu te restreint dorénavant à Windows, alors que le programme risque d'avoir des données faussées sous tout système. (Windows compris, jusqu'à preuve du contraire)

    Encore une fois: je ne dis rien d'autres que les données peuvent être faussée d'un thread à l'autre. Rien de plus.

  3. #43
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    En effet, c'est très probable connaissant les habitudes de Microsoft.
    Qu'il en soit autrement :
    1. Serait une incohérence par rapport au reste de la CRT (oui, j'ai dit "en règle générale") et serait considéré comme un bug,
    2. Rendrait les faits constatés exponentiellement improbables et exponentiellement difficiles à reproduire: Modifier la charge du système modifierait le comportement.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #44
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    "probablement" puis "ne le seront pas" et maintenant "très probable connaissant les habitudes de Microsoft"...
    Alors que je ne fais que pointer du doigt les risques de l'utilisation multi-thread de rand().
    (C'est pas un bon point pour ma confiance de Microsoft)

  5. #45
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Ben oui.
    Tout ce qui n'est pas explicitement documenté est probabiliste.
    La probabilité d'un bug n'est pas nulle, non plus.
    Citation Envoyé par Douglas Adams
    Ce n’est pas impossible, seulement très, très, très improbable
    En effet, si variable partagée il y a, il reste une chance infime pour que par miracle, chaque appel à rand() ait été fait exactement simultanément, si bien que chaque thread récupère la valeur avant que l'autre l'incrémente, et ce pour toute la durée de la boucle, et quelle que soit la charge du système.
    Mais alors, bonne chance pour reproduire ça...

    PS: On sait qu'on ne peut logiquement pas utiliser rand() en multithread sans prendre en compte le système. Et là, le comportement observé lui-même dépendait du système et n'est pas reproductible (là encore, très très très improbable, évidemment) sur un système où la variable est partagée.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #46
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    Bah au moins on doit être d'accord pour dire que POSIX est mieux documenté sur rand()... (C'est pas un bon point pour ma confiance de Microsoft)

    Citation Envoyé par Médinoc
    En effet, si variable partagée il y a, il reste une chance infime pour que par miracle, chaque appel à rand() ait été fait exactement simultanément, si bien que chaque thread récupère la valeur avant que l'autre l'incrémente, et ce pour toute la durée de la boucle, et quelle que soit la charge du système.
    Mais alors, bonne chance pour reproduire ça...
    Bah ça peut dépendre de la fréquence d'appel à la fonction rand(), et de son implémentation.
    Si par exemple deux vecteurs sont initialisés en même temps, c'est peut-être pas négligeable, puisque la fonction rand() lit la variable statique, calcule une nouvelle valeur aléatoire et récrit la variable statique.

  7. #47
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Mieux documenté pour son implémentation de rand().
    Comme nous parlons de comportement multi-thread, tout est dépendant de l'implémentation.

    PS: À quelle heure pars-tu déjeuner ? J'ai faim moi...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #48
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    Citation Envoyé par Médinoc
    Mieux documenté pour son implémentation de rand().
    J'ai fais exprès de restreindre à la doc sur rand(). J'ai pas envie de débattre sur les autres fonctions!

    ok, on arrête là

  9. #49
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    Citation Envoyé par Charlemagne
    Bah ça peut dépendre de la fréquence d'appel à la fonction rand(), et de son implémentation.
    Si par exemple deux vecteurs sont initialisés en même temps, c'est peut-être pas négligeable, puisque la fonction rand() lit la variable statique, calcule une nouvelle valeur aléatoire et récrit la variable statique.
    Ça, c'est testable : Nous POUVONS décaler artificiellement pour s'assurer que les vecteurs ne soient pas initialisés en même temps.
    Et là, si les séquences sont à nouveau identiques, nous aurons une preuve tangible que cela ne dépend pas d'une race condition.

    Je testerai cela si j'ai le temps...

    Edit: OK, à plus tard.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #50
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    Et là, si les séquences sont à nouveau identiques, nous aurons une preuve tangible que cela ne dépend pas d'une race condition.
    C'est pas identiques mais faussées. Et même si c'était totalement différent ça prouverait rien du tout, les valeurs sont peut-être dépendantes. Et puis rand() est intrinsèquement lui-même faussé puisque je sais que rand() était jugé comme pas suffisamment pseudo-aléatoire par certains collègues qui avaient besoin de pas mal de données (ils avaient des artéfactes dans le programme, et ont utilisé une librairie mathématique plus précise).

    Si tu fais le test, fais le pour toi ou par curiosité, moi je m'en moque (j'utilise pas la fonction rand). Bon j'arrête.

  11. #51
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    DE RETOUR!
    Mais mon cher, la question est justement sur le mot "identiques" : C'est ce qui m'a permis toutes ces suppositions sur l'implémentation probable de rand() chez Microsoft.

    Si les valeurs n'avaient pas été identiques, jamais je ne me serais permis la suggestion de mon premier post...

    Quoi qu'il en fût, plutôt que de faire un programme de test, je suis directement allé regarder dans le code source de la CRT Microsoft (ce code source est fourni avec Visual). Ce code stocke sa graine aléatoire dans :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    _getptd()->_holdrand
    
    Avec la fonction _getptd() ainsi déclarée :
    _ptiddata __cdecl _getptd(void);  /* return address of per-thread CRT data */
    Nous avons donc confirmation que l'implémentation Microsoft de rand() utilise du thread-local storage, et est donc thread-safe.
    Naturellement, cela ne dit rien sur les autres implémentations.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #52
    Inactif  
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    743
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 743
    Par défaut
    Je disais que srand n'était pas SUFFISANT pour assurer la validité des suites aléatoires de 2 threads et j'incitais à la prudence.
    Si tu dis vrai pour le stockage de la "graine" sous Windows alors rand() est "très probablement" thread-safe pour Windows. Dommage qu'il faille s'en assurer dans les sources...

  13. #53
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    En effet, ce serait loin d'être suffisant sous POSIX. Mais ça l'est sous Windows avec la CRT de Microsoft.

    Dommage en effet. Cela aurait dû être documenté. Je pense que ceux qui ont fait la doc ont oublié que rand() faisait partie des fonctions non-réentrantes au même titre que strtok()...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #54
    Membre Expert
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Par défaut [debutant]
    Juste une queston hors sujet, qu'est-ce qu'une fonction réentrante?

  15. #55
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    J'ignore la "vraie" définition, mais ça veut plus ou moins dire que son résultat (effets de bord compris) sera le même si les paramètres (pour des pointeurs, valeurs pointées comprises) sont les mêmes. Et ce, indépendamment des appels précédents à cette fonction.

    Ce qui n'est clairement pas le cas de rand(), puisque ces paramètres sont toujours void, et sa valeur de retour change tout le temps.

    Ce n'est pas non plus le cas de strtok() si le premier paramètre est NULL : On aura beau sauvegarder la chaîne modifiable passée en paramètre et la restaurer, au prochain appel le résultat ne sera pas le même, car la fonction strtok() garde un pointeur en mémoire.
    La fonction strtok_r() est une version réentrante de strtok(), car elle fait de ce pointeur un paramètre. Alors, le résultat de strtok_r() ne dépend plus que de ses paramètres, et en passant deux fois les mêmes paramètres (pas seulement les pointeurs, mais aussi les valeurs pointées), on obtient deux fois les mêmes résultats.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #56
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 393
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 393
    Par défaut
    La fonction POSIX rand_r() est réentrante pour la même raison : la graine courante est devenue un paramètre, et si tu passes deux fois la même graine, tu auras deux fois la même valeur et deux fois la même "nouvelle graine".

    Réentrant signifie également qu'une fonction n'est pas génée par un appel récursif (c'est possible pour des fonctions qui prennent des pointeurs de fonction en paramètre, comme sort()).

    D'une manière générale, "réentrant" c'est mieux que "thread-safe", mais ici "thread-safe" n'implique pas qu'on puisse accéder dans deux threads simultanés à la même variable : Ça indique généralement au contraire que les variables ne sont PAS partagées entre les threads.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  17. #57
    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 coyotte507
    Juste une queston hors sujet, qu'est-ce qu'une fonction réentrante?
    reentrante veut dire qu'une fonction peut avoir plusieurs executions en cours (3 grandes causes: les interruptions/exceptions, la recursivite, le multithread).

  18. #58
    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 Médinoc
    J'ignore la "vraie" définition, mais ça veut plus ou moins dire que son résultat (effets de bord compris) sera le même si les paramètres (pour des pointeurs, valeurs pointées comprises) sont les mêmes.
    Ca c'est une fonction pure. Une fonction peut etre reentrante sans etre pure.

  19. #59
    Membre Expert
    Avatar de coyotte507
    Profil pro
    Inscrit en
    Octobre 2006
    Messages
    1 327
    Détails du profil
    Informations personnelles :
    Âge : 34
    Localisation : France

    Informations forums :
    Inscription : Octobre 2006
    Messages : 1 327
    Par défaut
    Merci pour vos réponses

  20. #60
    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
    Pour faire simple j'ai un rand() dans la méthode Run qui sert à générer un int aléatoire pour appeler la méthode Sleep() et cependant mes 2 Threads qui s'executent en parallèle génèrent la même valeur.

    Un petite explication ?
    rand() n'est pas une fonction réentrante.
    Sinon à part ça, c'est parfaitement normal. Un générateur de nombres pseudo-aléatoires est parfaitement déterministe. C'est sa 'seed' qui le rend aléatoire.

+ Répondre à la discussion
Cette discussion est résolue.
Page 3 sur 4 PremièrePremière 1234 DernièreDernière

Discussions similaires

  1. p'tite question de cryptage ( nombre aléatoire )
    Par smyley dans le forum Algorithmes et structures de données
    Réponses: 53
    Dernier message: 08/11/2004, 10h07
  2. Nombres aléatoires
    Par Mat 74 dans le forum Assembleur
    Réponses: 20
    Dernier message: 29/08/2004, 13h31
  3. recherche algo de génération de nombre aléatoire
    Par Pascale38 dans le forum MFC
    Réponses: 2
    Dernier message: 26/01/2004, 14h20
  4. Nombre aléatoire en SQL
    Par sqlnet dans le forum Langage SQL
    Réponses: 8
    Dernier message: 19/08/2003, 12h38
  5. Générer un nombre aléatoire entre 0 et 1 (INCLUS !!!)
    Par haypo dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 22/08/2002, 16h30

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