В зависимости от вашего приложения вы должны с осторожностью использовать LCG, не учитывая, будут ли потоки (один поток на поток) перекрываться. Вы могли бы реализовать перепрыгивание с LCG, но тогда вам понадобится достаточно длинный период LCG, чтобы последовательность не повторялась.
Примером чехарды может быть:
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);
...
}
Но тогда период этого генератора, вероятно, будет недостаточным в большинстве случаев.
Если честно, я бы посмотрел на использование сторонней библиотеки, такой как NAG . В SDK также есть несколько генераторов пакетов, но в данном случае это, вероятно, не то, что вам нужно.
EDIT
Поскольку за это только что проголосовали, я думаю, что стоит обновить, чтобы упомянуть, что cuRAND , как уже упоминалось в более поздних ответах на этот вопрос, доступно и предоставляет ряд генераторов и дистрибутивов. Это определенно самое легкое место для начала.