J'essaie de mettre en œuvre la classe suivante: Je veux que la classe fonctionne dans un environnement multithread. Chaque thread aura sa propre instance d'objet code> Moteur Code> et il passera le moteur afin de générer numéros aléatoires uniformément la manière C ++ 11, la mise en œuvre du Le problème est que je Ne comprenez pas les distributions C ++ 11. Je sais que les moteurs de nombres aléatoires C ++ 11 peuvent être très gros objets (peu de kilo-octets), mais qu'en est-il des distributions? Au début, je pensais que les distributions sont simplement des foncteurs simples, où Ma question est la suivante: p> Les distributions ont-elles un état interne? Si oui pourquoi? La norme dis-elle quelque chose de la taille de cet état? P> li>
est-ce une bonne idée de faire une mise en œuvre comme moi? Y a-t-il une meilleure façon? p> li>
ol> p> code> sur des objets de n'importe quelle classe qui a un comportement randomisé. P>
generateNiformRandomNumber code> devrait être quelque chose comme ceci: p>
opérateur () code> est une fonction
pure const code>, mais il semble que ce ne soit ni
pur code> ni
const code>. Selon le Référence , chaque instance de distribution a un
réinitialiser () Code> Fonction de membre. Cela signifie qu'il a un état interne potentiellement important ou peut-être une cache. P>
4 Réponses :
Regarde vers les docs pour le Politique de modèle RandomNumberDistribution ... p>
réinitialise l'état interne de l'objet de distribution. Après un appel à
Cette fonction, le prochain appel à l'opérateur () sur l'objet de distribution
ne sera pas dépendant des appels précédents à l'opérateur (). P>
blockQuote>
Cela implique que les appels à réinitialiser () code>: strong> p>
opérateur () code> peuvent modifier l'état qui effets appels ultérieurs vers
opérateur () code>. C'est à la fois pourquoi
réinitialiser () code> existe et pourquoi
opérateur () code> n'est pas
const code>. P>
Uniform_real_distribution code> doit être un petit foncteur simple, comme vous l'avez dit. Il serait probablement de tenir le 2
réel code> s, il a été construit avec et rien d'autre. Et
réinitialiser () code> ne devrait rien faire pour celui-là. P>
Une distribution peut très bien et aura généralement un certain état. La norme ne donne aucune restriction ici. Je peux penser à quelques raisons que l'état pourrait être utilisé: p>
Une distribution de nombres aléatoires a souvent des paramètres pour le configurer. Par exemple, une distribution normale a des paramètres méchants et de variance. Ceux-ci font partie de son état parce qu'ils doivent être tenus entre des invocations. P> li>
La distribution est mise en œuvre en termes d'autre distribution. Vous pouvez vraiment penser à cela comme un paramètre plus complexe. Par exemple, mon Distribution bêta Mise en œuvre maintient deux distributions gamma qui ont chacune leur propre configuration. P> li>
La distribution pourrait changer avec le temps. Il n'y a rien à dire que les invocations répétées d'une distribution doivent être indépendantes. Ceci est l'endroit où la fonction code> réinitialiser code> est entrée. La plupart des distributions ont des appels indépendants vers Votre implémentation semble bien. Un opérateur () code> et donc la fonction
réinitialiser code> ne fait rien (son la définition est vide). Toutefois, si vos appels sont dépendants,
réinitialiser code> doit ramener la distribution à un état où le prochain appel est indépendant. P> LI>
ol>
uniforme_real_distribution
Oui, les distributions peuvent avoir des états internes. Ils seront généralement petits, mais si vous êtes préoccupé par la taille, vérifiez-le. P>
la spécification pour Les utilisations ultérieures de D ne dépendent pas des valeurs produites par aucun moteur avant d'invoquer la réinitialisation. P>
blockQuote>
qui implique que les invocations normalement de Par exemple, une distribution Bernoulli n'a peut-être pas besoin d'un bit pour produire un résultat tandis qu'un moteur donné fournit 32 bits à la fois, la distribution peut donc mettre en cache les 32 bits et ne pas invoquer à nouveau tout moteur jusqu'à ce que 32 valeurs aient été générées. p>
Un autre exemple est une distribution (j'oublie qui) où l'algorithme commun produit naturellement deux valeurs à la fois. La distribution peut donc enregistrer la deuxième valeur pour l'appel suivant. P>
Donc oui, les distributions peuvent avoir un état interne. La norme ne place pas les exigences de la taille de cet état. P>
Si vous demandez s'il serait correct de partager une distribution entre les threads, ce n'est pas une bonne idée. Pour une chose, c'est une course de données et entraîne un comportement non défini, sauf si vous ajoutez une synchronisation ou de rendre la distribution constante (laquelle, même si vous pouvez le faire avec votre implémentation de la bibliothèque standard, n'est pas portable). Deuxièmement, la norme ne fait que des garanties lorsque vous utilisez les distributions et les moteurs d'une manière particulière et partageant une distribution entre plusieurs moteurs n'est pas la voie. Il est peu probable que le partage d'une distribution produira réellement de mauvaises données, mais l'OMI, c'est toujours une bonne idée de ne pas le faire. Au lieu de cela, vous pourriez avoir chaque thread conserver à la fois son propre moteur et sa propre distribution. P> réinitialiser () code> états: p>
opérateur () code> peuvent dépendre des valeurs produites par les moteurs utilisés dans l'invocation antérieure de
opérateur () code>. C'est-à-dire qu'une distribution peut mettre en cache ou autrement dépendre des résultats précédents du moteur. P>
À titre d'exemple, j'ai mis en place un Distribution bêta dont l'état est en réalité deux distributions gamma.
Réinitialiser CODE> Ne fait rien parce que ce n'est que l'exigence est que toutes les valeurs suivantes sont indépendantes des utilisations précédentes des moteurs.
@sftrabbit donc est
réinitialiser () code> là-bas au cas où une personne fait une distribution qui accumule l'état lorsque vous appelez
opérateur () code>? Par exemple, chaque appel ultérieur à
opérateur () code> pourrait vous donner une plage croissante ... qui explique également pourquoi
opérateur () code> n'est-il pas conçu?
@Dave Oui, il n'y a aucune raison que la distribution ne peut pas changer car vous continuez à appeler
opérateur () code>. Cela signifie simplement que les valeurs résultantes dépendent des invocations précédentes.