En fonction de votre application, vous devez être prudent d'utiliser LCGs sans tenir compte si les flux (un flux par thread) se chevaucheront. Vous pourriez implémenter une saute-mouton avec LCG, mais alors vous devriez avoir un LCG de période suffisamment long pour vous assurer que la séquence ne se répète pas.
Un saute-mouton par exemple 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 insuffisant dans la plupart des cas.
Pour être honnête, je regarderais en utilisant une bibliothèque tierce telle que NAG. Il y a aussi des générateurs de lots dans le SDK, mais ce n'est probablement pas ce que vous recherchez dans ce cas.
EDIT
Depuis ce vient de se lever, a voté, je figure, il vaut la peine de la mise à jour de mentionner que cuRAND, comme l'a mentionné des réponses plus récentes à cette question, est disponible et fournit un certain nombre de générateurs et distributions. C'est certainement l'endroit le plus facile à commencer.
Quelques informations utiles: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch37.html – Jesper