xref: /petsc/src/sys/classes/random/impls/curand/curand.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
1a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h>
2d6cc7855SJacob Faibussowitsch #include <petsc/private/randomimpl.h>
3808ba619SStefano Zampini #include <curand.h>
4808ba619SStefano Zampini 
5808ba619SStefano Zampini typedef struct {
6808ba619SStefano Zampini   curandGenerator_t gen;
7808ba619SStefano Zampini } PetscRandom_CURAND;
8808ba619SStefano Zampini 
99371c9d4SSatish Balay PetscErrorCode PetscRandomSeed_CURAND(PetscRandom r) {
10808ba619SStefano Zampini   PetscRandom_CURAND *curand = (PetscRandom_CURAND *)r->data;
11808ba619SStefano Zampini 
12808ba619SStefano Zampini   PetscFunctionBegin;
139566063dSJacob Faibussowitsch   PetscCallCURAND(curandSetPseudoRandomGeneratorSeed(curand->gen, r->seed));
14808ba619SStefano Zampini   PetscFunctionReturn(0);
15808ba619SStefano Zampini }
16808ba619SStefano Zampini 
17808ba619SStefano Zampini PETSC_INTERN PetscErrorCode PetscRandomCurandScale_Private(PetscRandom, size_t, PetscReal *, PetscBool);
18808ba619SStefano Zampini 
199371c9d4SSatish Balay PetscErrorCode PetscRandomGetValuesReal_CURAND(PetscRandom r, PetscInt n, PetscReal *val) {
20808ba619SStefano Zampini   PetscRandom_CURAND *curand = (PetscRandom_CURAND *)r->data;
215162e2cfSBarry Smith   size_t              nn     = n < 0 ? (size_t)(-2 * n) : n; /* handle complex case */
22808ba619SStefano Zampini 
23808ba619SStefano Zampini   PetscFunctionBegin;
24808ba619SStefano Zampini #if defined(PETSC_USE_REAL_SINGLE)
259566063dSJacob Faibussowitsch   PetscCallCURAND(curandGenerateUniform(curand->gen, val, nn));
26808ba619SStefano Zampini #else
279566063dSJacob Faibussowitsch   PetscCallCURAND(curandGenerateUniformDouble(curand->gen, val, nn));
28808ba619SStefano Zampini #endif
29*48a46eb9SPierre Jolivet   if (r->iset) PetscCall(PetscRandomCurandScale_Private(r, nn, val, (PetscBool)(n < 0)));
30808ba619SStefano Zampini   PetscFunctionReturn(0);
31808ba619SStefano Zampini }
32808ba619SStefano Zampini 
339371c9d4SSatish Balay PetscErrorCode PetscRandomGetValues_CURAND(PetscRandom r, PetscInt n, PetscScalar *val) {
34808ba619SStefano Zampini   PetscFunctionBegin;
35808ba619SStefano Zampini #if defined(PETSC_USE_COMPLEX)
36808ba619SStefano Zampini   /* pass negative size to flag complex scaling (if needed) */
379566063dSJacob Faibussowitsch   PetscCall(PetscRandomGetValuesReal_CURAND(r, -n, (PetscReal *)val));
38808ba619SStefano Zampini #else
399566063dSJacob Faibussowitsch   PetscCall(PetscRandomGetValuesReal_CURAND(r, n, val));
40808ba619SStefano Zampini #endif
41808ba619SStefano Zampini   PetscFunctionReturn(0);
42808ba619SStefano Zampini }
43808ba619SStefano Zampini 
449371c9d4SSatish Balay PetscErrorCode PetscRandomDestroy_CURAND(PetscRandom r) {
45808ba619SStefano Zampini   PetscRandom_CURAND *curand = (PetscRandom_CURAND *)r->data;
46808ba619SStefano Zampini 
47808ba619SStefano Zampini   PetscFunctionBegin;
489566063dSJacob Faibussowitsch   PetscCallCURAND(curandDestroyGenerator(curand->gen));
499566063dSJacob Faibussowitsch   PetscCall(PetscFree(r->data));
50808ba619SStefano Zampini   PetscFunctionReturn(0);
51808ba619SStefano Zampini }
52808ba619SStefano Zampini 
53808ba619SStefano Zampini static struct _PetscRandomOps PetscRandomOps_Values = {
54267267bdSJacob Faibussowitsch   PetscDesignatedInitializer(seed, PetscRandomSeed_CURAND),
55267267bdSJacob Faibussowitsch   PetscDesignatedInitializer(getvalue, NULL),
56267267bdSJacob Faibussowitsch   PetscDesignatedInitializer(getvaluereal, NULL),
57267267bdSJacob Faibussowitsch   PetscDesignatedInitializer(getvalues, PetscRandomGetValues_CURAND),
58267267bdSJacob Faibussowitsch   PetscDesignatedInitializer(getvaluesreal, PetscRandomGetValuesReal_CURAND),
59267267bdSJacob Faibussowitsch   PetscDesignatedInitializer(destroy, PetscRandomDestroy_CURAND),
60808ba619SStefano Zampini };
61808ba619SStefano Zampini 
62808ba619SStefano Zampini /*MC
63808ba619SStefano Zampini    PETSCCURAND - access to the CUDA random number generator
64808ba619SStefano Zampini 
651179163eSBarry Smith   PETSc must be ./configure with the option --with-cuda to use this random number generator.
661179163eSBarry Smith 
67808ba619SStefano Zampini   Level: beginner
68808ba619SStefano Zampini 
69db781477SPatrick Sanan .seealso: `PetscRandomCreate()`, `PetscRandomSetType()`
70808ba619SStefano Zampini M*/
71808ba619SStefano Zampini 
729371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscRandomCreate_CURAND(PetscRandom r) {
73808ba619SStefano Zampini   PetscRandom_CURAND *curand;
74808ba619SStefano Zampini 
75808ba619SStefano Zampini   PetscFunctionBegin;
769566063dSJacob Faibussowitsch   PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
779566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(r, &curand));
789566063dSJacob Faibussowitsch   PetscCallCURAND(curandCreateGenerator(&curand->gen, CURAND_RNG_PSEUDO_DEFAULT));
79808ba619SStefano Zampini   /* https://docs.nvidia.com/cuda/curand/host-api-overview.html#performance-notes2 */
809566063dSJacob Faibussowitsch   PetscCallCURAND(curandSetGeneratorOrdering(curand->gen, CURAND_ORDERING_PSEUDO_SEEDED));
819566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(r->ops, &PetscRandomOps_Values, sizeof(PetscRandomOps_Values)));
829566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)r, PETSCCURAND));
83808ba619SStefano Zampini   r->data = curand;
84808ba619SStefano Zampini   r->seed = 1234ULL; /* taken from example */
859566063dSJacob Faibussowitsch   PetscCall(PetscRandomSeed_CURAND(r));
86808ba619SStefano Zampini   PetscFunctionReturn(0);
87808ba619SStefano Zampini }
88