1a4af0ceeSJacob Faibussowitsch #include <petsc/private/deviceimpl.h>
2d6cc7855SJacob Faibussowitsch #include <petsc/private/randomimpl.h>
30e6b6b59SJacob Faibussowitsch #include <petscdevice_cuda.h>
4808ba619SStefano Zampini
5808ba619SStefano Zampini typedef struct {
6808ba619SStefano Zampini curandGenerator_t gen;
7808ba619SStefano Zampini } PetscRandom_CURAND;
8808ba619SStefano Zampini
PetscRandomSeed_CURAND(PetscRandom r)966976f2fSJacob Faibussowitsch static PetscErrorCode PetscRandomSeed_CURAND(PetscRandom r)
10d71ae5a4SJacob Faibussowitsch {
11808ba619SStefano Zampini PetscRandom_CURAND *curand = (PetscRandom_CURAND *)r->data;
12808ba619SStefano Zampini
13808ba619SStefano Zampini PetscFunctionBegin;
149566063dSJacob Faibussowitsch PetscCallCURAND(curandSetPseudoRandomGeneratorSeed(curand->gen, r->seed));
153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
16808ba619SStefano Zampini }
17808ba619SStefano Zampini
18808ba619SStefano Zampini PETSC_INTERN PetscErrorCode PetscRandomCurandScale_Private(PetscRandom, size_t, PetscReal *, PetscBool);
19808ba619SStefano Zampini
PetscRandomGetValuesReal_CURAND(PetscRandom r,PetscInt n,PetscReal * val)2066976f2fSJacob Faibussowitsch static PetscErrorCode PetscRandomGetValuesReal_CURAND(PetscRandom r, PetscInt n, PetscReal *val)
21d71ae5a4SJacob Faibussowitsch {
22808ba619SStefano Zampini PetscRandom_CURAND *curand = (PetscRandom_CURAND *)r->data;
23bcdedc73SJed Brown size_t nn = n < 0 ? (size_t)(-2 * n) : (size_t)n; /* handle complex case */
24808ba619SStefano Zampini
25808ba619SStefano Zampini PetscFunctionBegin;
26808ba619SStefano Zampini #if defined(PETSC_USE_REAL_SINGLE)
279566063dSJacob Faibussowitsch PetscCallCURAND(curandGenerateUniform(curand->gen, val, nn));
28808ba619SStefano Zampini #else
299566063dSJacob Faibussowitsch PetscCallCURAND(curandGenerateUniformDouble(curand->gen, val, nn));
30808ba619SStefano Zampini #endif
3148a46eb9SPierre Jolivet if (r->iset) PetscCall(PetscRandomCurandScale_Private(r, nn, val, (PetscBool)(n < 0)));
323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
33808ba619SStefano Zampini }
34808ba619SStefano Zampini
PetscRandomGetValues_CURAND(PetscRandom r,PetscInt n,PetscScalar * val)3566976f2fSJacob Faibussowitsch static PetscErrorCode PetscRandomGetValues_CURAND(PetscRandom r, PetscInt n, PetscScalar *val)
36d71ae5a4SJacob Faibussowitsch {
37808ba619SStefano Zampini PetscFunctionBegin;
38808ba619SStefano Zampini #if defined(PETSC_USE_COMPLEX)
39808ba619SStefano Zampini /* pass negative size to flag complex scaling (if needed) */
409566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValuesReal_CURAND(r, -n, (PetscReal *)val));
41808ba619SStefano Zampini #else
429566063dSJacob Faibussowitsch PetscCall(PetscRandomGetValuesReal_CURAND(r, n, val));
43808ba619SStefano Zampini #endif
443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
45808ba619SStefano Zampini }
46808ba619SStefano Zampini
PetscRandomDestroy_CURAND(PetscRandom r)4766976f2fSJacob Faibussowitsch static PetscErrorCode PetscRandomDestroy_CURAND(PetscRandom r)
48d71ae5a4SJacob Faibussowitsch {
49808ba619SStefano Zampini PetscRandom_CURAND *curand = (PetscRandom_CURAND *)r->data;
50808ba619SStefano Zampini
51808ba619SStefano Zampini PetscFunctionBegin;
529566063dSJacob Faibussowitsch PetscCallCURAND(curandDestroyGenerator(curand->gen));
539566063dSJacob Faibussowitsch PetscCall(PetscFree(r->data));
543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
55808ba619SStefano Zampini }
56808ba619SStefano Zampini
57808ba619SStefano Zampini static struct _PetscRandomOps PetscRandomOps_Values = {
58267267bdSJacob Faibussowitsch PetscDesignatedInitializer(seed, PetscRandomSeed_CURAND),
59267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvalue, NULL),
60267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvaluereal, NULL),
61267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvalues, PetscRandomGetValues_CURAND),
62267267bdSJacob Faibussowitsch PetscDesignatedInitializer(getvaluesreal, PetscRandomGetValuesReal_CURAND),
63267267bdSJacob Faibussowitsch PetscDesignatedInitializer(destroy, PetscRandomDestroy_CURAND),
64808ba619SStefano Zampini };
65808ba619SStefano Zampini
66808ba619SStefano Zampini /*MC
67811af0c4SBarry Smith PETSCCURAND - access to the CUDA random number generator from a `PetscRandom` object
68808ba619SStefano Zampini
69808ba619SStefano Zampini Level: beginner
70808ba619SStefano Zampini
71c31d2375SBarry Smith Note:
72c31d2375SBarry Smith This random number generator is available when PETSc is configured with ``./configure --with-cuda=1``
73c31d2375SBarry Smith
74811af0c4SBarry Smith .seealso: `PetscRandomCreate()`, `PetscRandomSetType()`, `PetscRandomType`
75808ba619SStefano Zampini M*/
76808ba619SStefano Zampini
PetscRandomCreate_CURAND(PetscRandom r)77d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscRandomCreate_CURAND(PetscRandom r)
78d71ae5a4SJacob Faibussowitsch {
79808ba619SStefano Zampini PetscRandom_CURAND *curand;
80*eb58fe77SHansol Suh PetscDeviceContext dctx;
81*eb58fe77SHansol Suh cudaStream_t *stream;
82808ba619SStefano Zampini
83808ba619SStefano Zampini PetscFunctionBegin;
849566063dSJacob Faibussowitsch PetscCall(PetscDeviceInitialize(PETSC_DEVICE_CUDA));
85*eb58fe77SHansol Suh PetscCall(PetscDeviceContextGetCurrentContextAssertType_Internal(&dctx, PETSC_DEVICE_CUDA));
86*eb58fe77SHansol Suh PetscCall(PetscDeviceContextGetStreamHandle(dctx, (void **)&stream));
874dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&curand));
889566063dSJacob Faibussowitsch PetscCallCURAND(curandCreateGenerator(&curand->gen, CURAND_RNG_PSEUDO_DEFAULT));
89*eb58fe77SHansol Suh PetscCallCURAND(curandSetStream(curand->gen, *stream));
90808ba619SStefano Zampini /* https://docs.nvidia.com/cuda/curand/host-api-overview.html#performance-notes2 */
919566063dSJacob Faibussowitsch PetscCallCURAND(curandSetGeneratorOrdering(curand->gen, CURAND_ORDERING_PSEUDO_SEEDED));
92aea10558SJacob Faibussowitsch r->ops[0] = PetscRandomOps_Values;
939566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)r, PETSCCURAND));
94808ba619SStefano Zampini r->data = curand;
959566063dSJacob Faibussowitsch PetscCall(PetscRandomSeed_CURAND(r));
963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
97808ba619SStefano Zampini }
98