Question

J'ai eu du mal avec cela toute la journée, j'essaie d'obtenir un générateur de nombres aléatoires pour les discussions dans mon code CUDA. J'ai parcouru tous les forums et oui, ce sujet est assez courant, mais j'ai passé des heures à essayer de démêler toutes sortes de codes, mais en vain. Si quelqu'un connaît une méthode simple, probablement un noyau périphérique qui peut être appelé pour renvoyer un nombre aléatoire compris entre 0 et 1, ou un entier que je peux transformer, je vous en serais très reconnaissant.

Encore une fois, j'espère utiliser le nombre aléatoire dans le noyau, tout comme rand () par exemple.

Merci d'avance

Était-ce utile?

La solution

Je ne suis pas sûr de comprendre pourquoi vous avez besoin de quelque chose de spécial. Tout PRNG traditionnel devrait porter plus ou moins directement. Une congruentielle linéaire devrait fonctionner correctement. Avez-vous des propriétés spéciales que vous essayez d’établir?

Autres conseils

Si vous êtes intéressé, vous pouvez le faire via CANDA .

Je pense que toute discussion sur cette question doit répondre à la demande originale de Zenna, à savoir une implémentation de niveau de thread . En particulier, une fonction de périphérique pouvant être appelée à partir d'un noyau ou d'un fil . Désolé si j'ai trop utilisé le " en gras " mais je pense vraiment que les réponses à ce jour ne répondent pas tout à fait à ce qui est recherché ici.

La bibliothèque CUAND est votre meilleur choix. J'apprécie que les gens veuillent réinventer la roue (cela permet d'apprécier et d'utiliser plus correctement les bibliothèques tierces), mais les générateurs de nombres hautes performances de haute qualité sont nombreux et bien testés. La meilleure information que je puisse recommander concerne la documentation de la bibliothèque GSL sur les différents générateurs, ici: http://www.gnu.org/software/gsl/manual/html_node/Random-number-generator-algorithms.html

Pour tout code sérieux, il est préférable d’utiliser l’un des principaux algorithmes utilisés par les mathématiciens / informaticiens pour rechercher les faiblesses systémiques. Le " mersenne twister " est quelque chose avec un point (boucle de répétition) de l'ordre de 10 ^ 6000 (algorithme MT19997 signifie "Mersenne Twister 2 ^ 19997") qui a été spécialement adapté pour que Nvidia puisse être utilisé à un niveau de thread dans les threads de la même chaîne à l'aide de thread identifie les appels en tant que graines. Voir le papier ici: http: / /developer.download.nvidia.com/compute/cuda/2_2/sdk/website/projects/MersenneTwister/doc/MersenneTwister.pdf . Je travaille actuellement à la mise en œuvre de cette bibliothèque en utilisant quelque chose et si je le fais fonctionner correctement, je posterai mon code. Nvidia a quelques exemples sur son site de documentation pour la boîte à outils CUDA actuelle.

NOTE: Pour mémoire, je ne travaille pas pour Nvidia, mais je vais admettre que la documentation et la conception de leurs abstractions pour CUDA sont quelque chose qui m’a impressionné jusqu’à présent.

En fonction de votre application, vous devez vous méfier des LCG sans vous demander si les flux (un flux par thread) vont se chevaucher. Vous pouvez mettre en œuvre un saut de loi avec LCG, mais vous devrez alors disposer d’une période suffisamment longue pour que la séquence ne se répète pas.

Un exemple de saute-mouton pourrait être:

template <typename ValueType>
__device__ void leapfrog(unsigned long &a, unsigned long &c, int leap)
{
    unsigned long an = a;
    for (int i = 1 ; i < leap ; i++)
        an *= a;
    c = c * ((an - 1) / (a - 1));
    a = an;
}

template <typename ValueType>
__device__ ValueType quickrand(unsigned long &seed, const unsigned long a, const unsigned long c)
{
    seed = seed * a;
    return seed;
}

template <typename ValueType>
__global__ void mykernel(
    unsigned long *d_seeds)
{
    // RNG parameters
    unsigned long a = 1664525L;
    unsigned long c = 1013904223L;
    unsigned long ainit = a;
    unsigned long cinit = c;
    unsigned long seed;

    // Generate local seed
    seed = d_seeds[bid];
    leapfrog<ValueType>(ainit, cinit, tid);
    quickrand<ValueType>(seed, ainit, cinit);
    leapfrog<ValueType>(a, c, blockDim.x);

    ...
}

Mais la période de ce générateur est probablement insuffisante dans la plupart des cas.

Pour être honnête, j'aimerais utiliser une bibliothèque tierce, telle que NAG . Il existe également des générateurs de lots dans le SDK, mais ce n’est probablement pas ce que vous recherchez dans ce cas.

MODIFIER

Étant donné que cela vient d'être voté, je pense qu'il vaut la peine de mettre à jour cette mention pour indiquer CANDA , comme mentionné par des réponses plus récentes à cette question, est disponible et fournit un certain nombre de générateurs et de distributions. C’est vraiment le meilleur endroit pour commencer.

La meilleure façon de procéder consiste à écrire votre propre périphérique , en voici une

.
void RNG()
{   
    unsigned int m_w = 150;
    unsigned int m_z = 40;

    for(int i=0; i < 100; i++)
    {
        m_z = 36969 * (m_z & 65535) + (m_z >> 16);
        m_w = 18000 * (m_w & 65535) + (m_w >> 16);

        cout <<(m_z << 16) + m_w << endl;  /* 32-bit result */
    }
}

Cela vous donnera 100 nombres aléatoires avec un résultat 32 bits.

Si vous voulez des nombres aléatoires compris entre 1 et 1000, vous pouvez également utiliser le résultat% 1000 , soit au point de consommation, soit au point de génération:

((m_z << 16) + m_w)%1000

La modification des valeurs de départ de m_w et m_z (dans l'exemple 150 et 40) vous permet d'obtenir un résultat différent à chaque fois. Vous pouvez utiliser threadIdx.x comme l'un d'entre eux, ce qui devrait vous donner différentes séries pseudo-aléatoires à chaque fois.

Je voulais ajouter que cela fonctionne 2 fois plus vite que la fonction rand (), et fonctionne très bien;)

Il existe un paquet MDGPU (GPL) qui inclut une implémentation de la fonction GNU rand48 () pour CUDA ici .

Je l'ai trouvé (assez facilement, en utilisant Google, que je suppose que vous avez essayé :-) sur les forums NVidia ici .

Je n’ai pas trouvé de bon générateur de nombres parallèles pour CUDA, mais j’ai trouvé un générateur de nombres aléatoires parallèles basé sur des recherches universitaires: http://sprng.cs.fsu.edu/

Vous pouvez essayer Mersenne Twister pour GPU

Il est basé sur le Fast Mersenne Twister (SFMT) orienté SIMD, un générateur de nombres aléatoires assez rapide et fiable. Il passe les tests Marsaglias DIEHARD pour les générateurs de nombres aléatoires.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top