Random Number Generator in ManagedCuda

Jan 26, 2015 at 8:36 PM
I am trying to use a random number generator for threads using ManagedCUDA.
I know that Managed cuda also has a library called CudaRand but I do not know
how to use it.

Can anyone give me an example of using this library to generate random numbers
with a specific mean (e.g. 0) and std (e.g. 0.01)?
Random number generator will be called to generate random numbers
for different threads of the blocks and we do not know how many random numbers
we need until the end of program.
Coordinator
Jan 26, 2015 at 10:00 PM
I guess you got a bit confused by the two different CURAND-APIs: There's a host and a device API.
The host API can be used to compute a lot of different random values that are then used for later computation: managedCUDA provides a wrapper of this API within CudaRand.
But if you need random numbers on a per thread basis, you need the device API and there's no need for a wrapper to use it from C# as only kernels can access it. All you need to do is to stick with the example codes given in the CURAND-documentation PDF starting on page 20.

Hope it helps
Michael
Jan 27, 2015 at 12:12 AM
Edited Jan 27, 2015 at 7:05 PM
Thanks for your reply.

yes I want to use device API and for this, I need to do the following steps.

step 1: allocate memory for results on device
CudaDeviceVariable<double> d_output = new CudaDeviceVariable<double>(64*64);
step 2: Allocate space for prng states on device
???

step 3: invoke InitKernels method to creates new context and load a module ....
InitKernels();//
for example:
static void InitKernels()
{
            CudaContext cntxt = new CudaContext();           
            CUmodule cumodule = cntxt.LoadModule(@"C:\\kernel.cu\\Debug\\kernel.ptx");
            generate_kernel = new CudaKernel("Generate_kernel", cumodule, cntxt);
            kernel_generator = new CudaKernel("Setup_kernel", cumodule, cntxt);
 }
step4: call the kernel
int threadsPerBlock=64;
int numberofBlock=64;

kernel_generator.BlockDimensions = threadsPerBlock;
kernel_generator.GridDimensions = numberofBlock;
kernel_generator.Run( ???)

generate_kernel.BlockDimensions = threadsPerBlock;
generate_kernel.GridDimensions = numberofBlock;
generate_kernel.Run(   ??? ,d_output.DevicePointer);
suppose this is my kernels to generate random number between 1 and -1:
extern "C"  
{
    
    __global__ void Setup_kernel(curandState *state)
    {
        int idx=threadIdx.x+blockIdx.x*blockDim.x;
        curand_init(1234,idx,0,&state[idx]);
    }
    __global__ void Generate_kernel(curandState *state,double* result)
    {
        double x;
        double2 xx;
        int sign=1;
        int idx=threadIdx.x+blockIdx.x*blockDim.x;
        curandState localState=state[idx];
        x = curand_uniform_double( & localState );
        xx=curand_normal2_double( & localState );
        if (xx.x<xx.y)
        {
            sign=-1;
        } 
        result[idx]=x*sign;
        state[idx] = localState;
    }

}

int main ()
{
    return 0;
}
Would you please help me what I should use for cuda state in step2 and step 4? (I put ??? in the places that I do not know.)
Also, if there is anything wrong in this example code, please let me know.

Thanks,
Saeed
Marked as answer by saeedm on 2/2/2015 at 3:32 PM
Jan 27, 2015 at 7:19 AM
Edited Jan 27, 2015 at 7:21 AM
curandState is acually an alias for the type curandStateXORWOW wich is defined in the curand_kernel.h header file.
curandStateXORWOW is a struct with sizeof(curandStateXORWOW) = 44.
Therefore you need to allocate
threadsPerBlock*numberofBlock*44
bytes of memory on the device and pass the pointer to this block to your kernels.

for example:
CudaDeviceVariable<byte> d_curandState = new CudaDeviceVariable<byte>(threadsPerBlock*numberofBlock*44);

kernel_generator.Run(d_curandState.DevicePointer);

generate_kernel.Run(d_curandState.DevicePointer ,d_output.DevicePointer);
Marked as answer by saeedm on 2/2/2015 at 3:32 PM
Jan 27, 2015 at 7:30 PM
Thanks a lot for your help. Yes this works. But I tried sizeof(curandStateXORWOW) and it gives me 48.

So I learned how to generate random numbers using device API. But I still do not know how to use host API
to generate random number via Managed Cuda. Can you give me an example of this?
Jan 27, 2015 at 7:50 PM
saeedm wrote:
Thanks a lot for your help. Yes this works. But I tried sizeof(curandStateXORWOW) and it gives me 48.
of coarse you are correct, the size is 48, i do not know how i came up with 44 :)
So I learned how to generate random numbers using device API. But I still do not know how to use host API
to generate random number via Managed Cuda. Can you give me an example of this?
unfortunatelly i am not familiar with the managedCuda wrapper for the curand host API. maybe kunzmi can help with that?
Jan 27, 2015 at 8:04 PM
RoBiK wrote:
saeedm wrote:
Thanks a lot for your help. Yes this works. But I tried sizeof(curandStateXORWOW) and it gives me 48.
of coarse you are correct, the size is 48, i do not know how i came up with 44 :)
So I learned how to generate random numbers using device API. But I still do not know how to use host API
to generate random number via Managed Cuda. Can you give me an example of this?
unfortunatelly i am not familiar with the managedCuda wrapper for the curand host API. maybe kunzmi can help with that?
thanks for your quick reply.
Coordinator
Jan 27, 2015 at 9:08 PM
To use the host API you need a reference to CudaRand and in C# something like:
//Create a sequence of random numbers using GPU
CudaRandDevice randDev = new CudaRandDevice(GeneratorType.PseudoDefault);

//Alloc Memory
CudaDeviceVariable<double> randomNumbers = new CudaDeviceVariable<double>(10000);

//Set seed (and maybe other settings)
randDev.SetPseudoRandomGeneratorSeed(123456789);

//generate the sequence: e.g. Normal distribution
double mean = 0;
double std = 0.3;
randDev.GenerateNormal(randomNumbers, mean, std);

//copy to host
double[] randomNumbersOnHost = randomNumbers;
That's actually more or less all to get a random sequence, whereas you can find all the possible settings and generator types in the documentation of CURAND.

Cheers,
Michael
Marked as answer by saeedm on 2/2/2015 at 3:32 PM
Jan 27, 2015 at 9:44 PM
Thanks Michael, This really helps.