Tùy thuộc vào ứng dụng của bạn, bạn nên thận trọng khi sử dụng LCGs mà không xem xét liệu các luồng (một luồng trên mỗi luồng) sẽ trùng lặp hay không. Bạn có thể thực hiện một bước nhảy vọt với LCG, nhưng sau đó bạn sẽ cần phải có một LCG thời gian đủ dài để đảm bảo rằng trình tự không lặp lại.
Một ví dụ leapfrog có thể là:
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);
...
}
Nhưng rồi thời gian của máy phát điện đó có lẽ là không đủ trong hầu hết các trường hợp.
Thành thật mà nói, tôi sẽ xem xét sử dụng thư viện của bên thứ ba chẳng hạn như NAG. Có một số máy tạo hàng loạt trong SDK cũng vậy, nhưng đó có thể không phải là những gì bạn đang tìm kiếm trong trường hợp này.
EDIT
Vì đây chỉ đã lên-bình chọn, tôi hình dung nó có giá trị cập nhật kể rằng cuRAND, như đã đề cập bởi câu trả lời gần đây hơn cho câu hỏi này, có sẵn và cung cấp một số máy phát điện và phân phối. Đó chắc chắn là nơi dễ nhất để bắt đầu.
Một số thông tin hữu ích: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch37.html – Jesper