2017-04-25 67 views
0

我知道這可能是一個轉發,但我還沒有找到滿意的答案。使用cuRand從均勻分佈中生成隨機整數的正確方法是什麼?

我設法從範圍0到n使用curand_uniform實數生成整數,但我想知道是否有更好的方法來確保統計數字是統一分佈的。

__global__ void generate_kernel(int n, curandState *state, int *result) 
{ int id = blockIdx.x * blockDim.x + threadIdx.x; 
    unsigned int x; 
    if (id < n) 
    { curandState localState = state[id];    

     float aux = curand_uniform(&localState) * n; 
     x = aux ; 

     state[id] = localState; 
     result[id] = x; 
    } 
} 

那麼,有沒有我應該使用乘以ncurand_uniform()整數部分的一些其他的事情嗎?順便說一句,我有n線程,每個線程都有自己的不同狀態和種子。每個線程生成一個值並將其保存在results陣列上。

回答

0

你說每個線程都有自己的種子。這意味着每個線程都有自己的一組隨機數。所以在你的內核中,一致性將以線程爲基礎達到,要獲得統一生成的數字,你必須多次調用上述內核。但是,如果你的意圖是隻有一次調用這個內核和期待n均勻分佈的值,每個n線程應該有相同的種子值,與不同的序列或偏移值。有關示例代碼的詳細信息,您可以查看this article

此外,還有一些微妙的回報值curand_uniform。從cuRAND文檔§3.1.4,它說:

__device__ float 
curand_uniform (curandState_t *state) 

此函數返回的僞隨機序列漂浮均勻分佈 0.0和1.0之間。它可能會從0.0返回到1.0,其中包含 1.0,排除0.0.

而且你的代碼是:

unsigned int x = curand_uniform(&localState) * n; 

鑄造整數型向零(link)截斷。因此從理論上講,只有curand_uniform返回的值是1.0(這是一種罕見的情況),您將得到n。但是,當curand_uniform返回的值(我會將此返回值表示爲y)爲k/n <= y < (k+1)/n時,您將得到k, (0 < k < n),如果0 < y < 1/n您將獲得0。所以生成的數字不是從整數0n的均勻分佈。

但請注意,這是所有的理論解釋。我有posted some sample code。它只是將整數轉換爲代碼並構建直方圖以查看數字如何分佈。我已經在底部發布了程序的輸出,並且您會看到直方圖看起來像從整數0n-1均勻分佈。 curand_uniform返回1.0似乎是一個非常罕見的情況(不出現100000試驗!)的情況。

從理論上講,你會得到從均勻分佈1整數n如果使用吊頂功能,因爲如果(k-1)/n < y <= k/n,然後ceilf(y * n)k1 <= k <= n

unsigned int x = ceilf(curand_uniform(&localState) * n); 

code I posted也涵蓋了上述情況。你可以運行它,會看到類似這樣的結果(n = 10在這種情況下):也

Histogram for the generated random numbers (with casting) 
0 : 9993 
1 : 9926 
2 : 10138 
3 : 10131 
4 : 9980 
5 : 9967 
6 : 9979 
7 : 10054 
8 : 9921 
9 : 9911 
10 :  0 
Histogram for the generated random numbers (with ceiling) 
0 :  0 
1 : 10036 
2 : 10033 
3 : 9899 
4 : 9952 
5 : 9960 
6 : 9892 
7 : 10167 
8 : 9839 
9 : 10198 
10 : 10024 

注意state[id] = localState;是在你的代碼冗餘。