Reputation: 737
I have a cuda application where I want to generate random numbers between 0 and 1. I have written a dummy code where a matrix of size 8x256 would be filled up by random numbers generated by kernel. My original matrix would be something like 8XBIG_NUMBER. But probably I am missing something in my code because of which I am not able to produce the desired result.I am posting my code below.
void main(int argc,char* argv[])
{
float *test_var,*dev_test;
curandState *state;
test_var = (float *)malloc(8*256*sizeof(float));
memset(test_var,0,8*256*sizeof(float));
cudaMalloc((void **)&dev_test,8*256*sizeof(float));
cudaMemcpy(dev_test,test_var,8*256*sizeof(float),cudaMemcpyHostToDevice);
dim3 gridDim(1,256/32,1);
dim3 blockDim(8,32,1);
cudaMalloc((void **)&state,8*256*sizeof(curandState));
setup_kernel<<<gridDim,blockDim>>>(state,unsigned(time(NULL)));
test_kernel<<<gridDim,blockDim>>>(state,dev_test);
cudaMemcpy(test_var,dev_test,8*256*sizeof(float),cudaMemcpyDeviceToHost);
system("PAUSE");
for (int i=0;i<256;i++)
{ for (int j=0;j<8;j++)
{ printf("%f\t",test_var[i*8+j]);
}
printf("\n");
}
cudaFree(dev_test);
cudaFree(state);
free(test_var);
exit(0);
}
__global__ void setup_kernel(curandState *state,unsigned long seed)
{
int id_col = threadIdx.x + blockDim.x*blockIdx.x;
int id_row = threadIdx.y+blockDim.y*blockIdx.y;
curand_init(seed,(id_row*8+id_col),0,&state[id_row*8+id_col]);
}
__global__ void test_kernel(curandState *state,float *dev_test)
{
int id_col = threadIdx.x + blockDim.x*blockIdx.x;
int id_row = threadIdx.y+blockDim.y*blockIdx.y;
curandState local_state = state[id_row*8+id_col];
dev_test[id_row*8+id_col] = curand(&local_state);
state[id_row*8+id_col] = local_state;
}
I want to generate a random number between 0 and 1 for each of those cells in the matrix. I would really appreciate of anyone's assistance. Thank you
Upvotes: 1
Views: 4793
Reputation: 151829
If you refer to the curand documentation, you'll note the declaration given for the device api function you are using:
__device__ unsigned int curand (curandState_t *state)
This particular API call returns an unsigned int
. So you're not going to get floating point values unless you modify it somehow.
Since it returns unsigned int
values, one possible modification would simply be to scale the result:
dev_test[id_row*8+id_col] = curand(&local_state)/(float)(0x0FFFFFFFFUL);
This modification should give you floating point values between 0 and 1. However this is rather crude for a variety of reasons. As suggested in the comments, it makes more sense to select one of the device generators that will do this for you, such as:
dev_test[id_row*8+id_col] = curand_uniform(&local_state);
I'm not an expert on this, but it seems that a multinomial distribution is fundamentally a discrete distribution. Therefore, you will need some method to convert a continuous-valued distribution to a discrete one, if you intend to start with floating point random numbers between 0 and 1. Wikipedia gives a method for doing this starting with continuous-valued random numbers between 0 and 1, and based on my read of that method, the curand_uniform
distribution/generator would be a reasonable starting point.
Upvotes: 4