Actual source code: curand.c
1: #include <petsc/private/randomimpl.h>
2: #include <curand.h>
4: #define CHKERRCURAND(stat) \
5: do { \
6: if (PetscUnlikely(stat != CURAND_STATUS_SUCCESS)) { \
7: if (((stat == CURAND_STATUS_INITIALIZATION_FAILED) || (stat == CURAND_STATUS_ALLOCATION_FAILED)) && PetscCUDAInitialized) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_GPU_RESOURCE,"cuRAND error %d. Reports not initialized or alloc failed; this indicates the GPU has run out resources",(int)stat); \
8: else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_GPU,"cuRand error %d",(int)stat); \
9: } \
10: } while (0)
12: typedef struct {
13: curandGenerator_t gen;
14: } PetscRandom_CURAND;
16: PetscErrorCode PetscRandomSeed_CURAND(PetscRandom r)
17: {
18: curandStatus_t cerr;
19: PetscRandom_CURAND *curand = (PetscRandom_CURAND*)r->data;
22: cerr = curandSetPseudoRandomGeneratorSeed(curand->gen,r->seed);CHKERRCURAND(cerr);
23: return(0);
24: }
26: PETSC_INTERN PetscErrorCode PetscRandomCurandScale_Private(PetscRandom,size_t,PetscReal*,PetscBool);
28: PetscErrorCode PetscRandomGetValuesReal_CURAND(PetscRandom r, PetscInt n, PetscReal *val)
29: {
30: curandStatus_t cerr;
31: PetscRandom_CURAND *curand = (PetscRandom_CURAND*)r->data;
32: size_t nn = n < 0 ? (size_t)(-2*n) : n; /* handle complex case */
35: #if defined(PETSC_USE_REAL_SINGLE)
36: cerr = curandGenerateUniform(curand->gen,val,nn);CHKERRCURAND(cerr);
37: #else
38: cerr = curandGenerateUniformDouble(curand->gen,val,nn);CHKERRCURAND(cerr);
39: #endif
40: if (r->iset) {
41: PetscErrorCode PetscRandomCurandScale_Private(r,nn,val,(PetscBool)(n<0));
42: }
43: return(0);
44: }
46: PetscErrorCode PetscRandomGetValues_CURAND(PetscRandom r, PetscInt n, PetscScalar *val)
47: {
51: #if defined(PETSC_USE_COMPLEX)
52: /* pass negative size to flag complex scaling (if needed) */
53: PetscRandomGetValuesReal_CURAND(r,-n,(PetscReal*)val);
54: #else
55: PetscRandomGetValuesReal_CURAND(r,n,val);
56: #endif
57: return(0);
58: }
60: PetscErrorCode PetscRandomDestroy_CURAND(PetscRandom r)
61: {
62: PetscErrorCode ierr;
63: curandStatus_t cerr;
64: PetscRandom_CURAND *curand = (PetscRandom_CURAND*)r->data;
67: cerr = curandDestroyGenerator(curand->gen);CHKERRCURAND(cerr);
68: PetscFree(r->data);
69: return(0);
70: }
72: static struct _PetscRandomOps PetscRandomOps_Values = {
73: PetscRandomSeed_CURAND,
74: NULL,
75: NULL,
76: PetscRandomGetValues_CURAND,
77: PetscRandomGetValuesReal_CURAND,
78: PetscRandomDestroy_CURAND,
79: NULL
80: };
82: /*MC
83: PETSCCURAND - access to the CUDA random number generator
85: Level: beginner
87: .seealso: PetscRandomCreate(), PetscRandomSetType()
88: M*/
90: PETSC_EXTERN PetscErrorCode PetscRandomCreate_CURAND(PetscRandom r)
91: {
92: PetscErrorCode ierr;
93: curandStatus_t cerr;
94: PetscRandom_CURAND *curand;
97: PetscCUDAInitializeCheck();
98: PetscNewLog(r,&curand);
99: cerr = curandCreateGenerator(&curand->gen,CURAND_RNG_PSEUDO_DEFAULT);CHKERRCURAND(cerr);
100: /* https://docs.nvidia.com/cuda/curand/host-api-overview.html#performance-notes2 */
101: cerr = curandSetGeneratorOrdering(curand->gen,CURAND_ORDERING_PSEUDO_SEEDED);CHKERRCURAND(cerr);
102: PetscMemcpy(r->ops,&PetscRandomOps_Values,sizeof(PetscRandomOps_Values));
103: PetscObjectChangeTypeName((PetscObject)r,PETSCCURAND);
104: r->data = curand;
105: r->seed = 1234ULL; /* taken from example */
106: PetscRandomSeed_CURAND(r);
107: return(0);
108: }