2
votes

Existe-t-il un générateur de nombres aléatoires qui peut sauter / supprimer N tirages dans O (1)?

Existe-t-il un générateur de nombres pseudo-aléatoires (non cryptographique) qui peut sauter / supprimer N tirages en O (1), ou peut-être O (log N) mais plus petit que O (N).


Surtout pour les applications parallèles, il serait avantageux d'avoir un générateur du type ci-dessus. Image que vous souhaitez générer un tableau de nombres aléatoires. On pourrait écrire un programme parallèle pour cette tâche et amorcer le générateur de nombres aléatoires pour chaque thread indépendamment. Cependant, les nombres dans le tableau ne seraient alors pas les mêmes que pour le cas séquentiel (sauf pour la première moitié peut-être).

Si un générateur de nombres aléatoires du type ci-dessus existait, le premier thread pourrait seed avec la graine utilisée pour l'implémentation séquentielle. Le deuxième thread pourrait également amorcer avec cette graine, puis déposer / sauter N / 2 échantillons qui sont générés par le premier thread. Le tableau de sortie serait alors identique au cas série (test facile) mais toujours généré en moins de temps. Voici un pseudo code.

#define _POSIX_C_SOURCE 1
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>

void rand_r_skip(unsigned int *p_seed, int N)
{
    /* Stupid O(N) Implementation */
    for (int i = 0; i < N; i++)
    {
        rand_r(p_seed);
    }
}

int main()
{
    int N = 1000000;
    unsigned int seed = 1234;
    int *arr = (int *)malloc(sizeof(int) * N);

#pragma omp parallel firstprivate(N, seed, arr) num_threads(2)
    {
        if (omp_get_thread_num() == 1)
        {
            // skip the samples, obviously doesn't exist
            rand_r_skip(&seed, N / 2);
        }
#pragma omp for schedule(static)
        for (int i = 0; i < N; i++)
        {
            arr[i] = rand_r(&seed);
        }
    }
    return 0;
}

Merci à tous pour votre aide. Je sais qu'il pourrait y avoir une preuve qu'un tel générateur ne peut pas exister et être "pseudo-aléatoire" en même temps. Je suis très reconnaissant pour tous les conseils sur où trouver de plus amples informations.


3 commentaires

Un candidat évident serait tout chiffrement cryptographique symétrique en mode compteur.


@ChrisDodd: oui, et ce serait O (1) à sauter. Bien sûr, la génération est relativement chère à moins que vous ne réduisiez le chiffre à quelques tours seulement.


Merci pour vos commentaires.


3 Réponses :


2
votes

Bien sûr. Linear Conguential Generator et ses descendants pourraient ignorer la génération de N nombres dans O (log (N)) heure. Il est basé sur l'article de F.Brown, lien .

Voici une implémentation de l'idée, C ++ 11.

/ p>


2 commentaires

Merci pour la réponse rapide.


@LukasKoestler vous êtes les bienvenus. N'oubliez pas que LCG n'est pas considéré comme un RNG de haute qualité. Mais les RNG basés sur LCG avec une meilleure qualité - PCG, je crois - partagent cette capacité O (log (N)) à aller de l'avant. pcg-random.org



2
votes

Comme l'a aimablement indiqué Severin Pappadeux, les implémentations C , C ++ et Haskell d'un La variante PCG développée par ME O'Neill fournit une interface pour ce jump-ahead / jump-back < / strong> fonctionnalité: ici .

Les noms des fonctions sont: advanced et backstep , qui ont été brièvement documentés hereat et hereat , respectivement

Citation de la page Web (consultée au moment de la rédaction):

... un générateur de nombres aléatoires est comme un livre qui répertorie page après page des nombres statistiquement aléatoires. La graine nous donne un point de départ, mais parfois il est utile de pouvoir avancer ou reculer dans la séquence, et de pouvoir le faire efficacement.

L'implémentation C ++ du schéma de génération PCG fournit une avance pour sauter efficacement en avant et en arrière pour sauter efficacement en arrière.


0 commentaires

0
votes

Chris Dodd a écrit ce qui suit:

Un candidat évident serait tout chiffrement cryptographique symétrique en mode compteur.


0 commentaires