2 votes

L'aléatoire avec une certaine graine semble toujours aléatoire

J'ai un programme qui fait un usage intensif de nombres aléatoires pour décider de ce qu'il doit faire, et qui a de nombreux chemins d'exécution basés sur la sortie du PRNG. Après m'être arraché les cheveux en essayant de le déboguer, j'ai décidé de faire en sorte que tous les appels au PRNG fassent référence à la même instance Random, qui a été ensemencée avec un nombre codé en dur lors de l'instanciation. Ainsi, à chaque fois que je lance le programme, le même bug devrait apparaître. Malheureusement, j'obtiens toujours des bugs différents à chaque fois que je l'exécute (bien qu'il semble se comporter presque de la même manière).

J'ai cherché dans le code de nombreuses fois des appels manqués à Math.random() et je vous assure qu'il n'y en a pas.

Des idées ?

Editar : J'ai confirmé que les nombres générés sont les mêmes, pourtant le comportement est toujours non déterministe. Ce programme n'est pas multithreadé. Toujours complètement déconcerté.

Le PRNG se comporte donc comme prévu, mais le non-déterminisme persiste. De quelles manières le non-déterminisme peut-il être introduit par inadvertance dans un programme ?

3voto

Lynden Shields Points 453

Ok je piense en J'ai localisé ma source de non-déterminisme. J'étais en train d'itérer sur un HashSet à un moment donné. Le HashSet aurait été rempli par les mêmes choses dans le même ordre, mais parce que je n'ai pas spécifié la méthode de hachage de la classe qui est ajoutée au HashSet, il serait par défaut un certain hachage en fonction de l'emplacement de la mémoire de chaque instance.

Changer chaque instance de HashSet en LinkedHashSet semble pour me donner des résultats cohérents depuis une trentaine d'exécutions maintenant, alors qu'auparavant il ne me donnait le même comportement que quelques fois d'affilée.

2voto

npe Points 6521

OK, donc ça ressemble à un vaudou. Essayez de créer un PRNG personnalisé qui englobe un fichier Random et enregistre les appels avec des traces de pile.

public class CustomRNG {

    private static Logger logger = Logger.getLogger(CustomRNG.class.getName());
    private static Random random = new Random(1234);

    public int nextInt() {

       int val = random.nextInt();
       log(val);

       return val;
    }

    private void log(int value) {
        logger.log(Level.INFO, "value: " + value, new Throwable());
    }
}

Cela enregistrera chaque appel à nextInt, y compris la valeur et une trace de la pile (ajoutez le comptage des appels si vous le souhaitez). Essayez d'exécuter votre application plusieurs fois et voyez à quel point (stacktrace) cela diverge.

0voto

mikera Points 63056

Causes possibles de la persistance du non-déterminisme (par ordre décroissant de probabilité) :

  • Vous n'avez pas remplacé todo les appels PRNG avec la même instance aléatoire. Vous voudrez probablement vérifier cela d'abord :-) Un bon IDE devrait vous aider à retrouver toutes les références à la classe Random.
  • Il existe des effets temporels causés par la concurrence (par exemple, il est important de savoir quel thread appelle le PRNG en premier).
  • Vous avez une certaine forme d'entrée externe dans le système (par exemple, entrée de l'utilisateur ? actions prises sur la base de la minuterie du système ?)
  • Une bibliothèque que vous utilisez comporte un élément non déterministe qui affecte le comportement de votre programme (par exemple, certains algorithmes de tri utilisent des nombres aléatoires qui peuvent affecter l'ordre des résultats qu'ils renvoient).
  • Vous vous heurtez à une sorte de contrainte environnementale (par exemple, une erreur OutOfMemoryError ou IOException qui se produit parfois mais qui est attrapée et récupérée de différentes manières, ou le GC qui décide d'effacer certaines références molles/faibles).
  • Rayons cosmiques / erreurs matérielles corrompant la mémoire

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X