xref: /petsc/include/petscdevice.h (revision 030f984af8d8bb4c203755d35bded3c05b3d83ce)
1*030f984aSJacob Faibussowitsch #if !defined(PETSCDEVICE_H)
2*030f984aSJacob Faibussowitsch #define PETSCDEVICE_H
3*030f984aSJacob Faibussowitsch 
4*030f984aSJacob Faibussowitsch #include <petscsys.h>
5*030f984aSJacob Faibussowitsch #include <petscdevicetypes.h>
6*030f984aSJacob Faibussowitsch 
7*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_CUDA)
8*030f984aSJacob Faibussowitsch #include <cuda.h>
9*030f984aSJacob Faibussowitsch #include <cuda_runtime.h>
10*030f984aSJacob Faibussowitsch #include <cublas_v2.h>
11*030f984aSJacob Faibussowitsch #include <cusolverDn.h>
12*030f984aSJacob Faibussowitsch #include <cusolverSp.h>
13*030f984aSJacob Faibussowitsch #include <cufft.h>
14*030f984aSJacob Faibussowitsch 
15*030f984aSJacob Faibussowitsch PETSC_EXTERN cudaEvent_t petsc_gputimer_begin;
16*030f984aSJacob Faibussowitsch PETSC_EXTERN cudaEvent_t petsc_gputimer_end;
17*030f984aSJacob Faibussowitsch 
18*030f984aSJacob Faibussowitsch /* cuBLAS does not have cublasGetErrorName(). We create one on our own. */
19*030f984aSJacob Faibussowitsch PETSC_EXTERN const char* PetscCUBLASGetErrorName(cublasStatus_t); /* PETSC_EXTERN since it is exposed by the CHKERRCUBLAS macro */
20*030f984aSJacob Faibussowitsch PETSC_EXTERN const char* PetscCUSolverGetErrorName(cusolverStatus_t);
21*030f984aSJacob Faibussowitsch PETSC_EXTERN const char* PetscCUFFTGetErrorName(cufftResult);
22*030f984aSJacob Faibussowitsch 
23*030f984aSJacob Faibussowitsch #define WaitForCUDA() PetscCUDASynchronize ? cudaDeviceSynchronize() : cudaSuccess;
24*030f984aSJacob Faibussowitsch 
25*030f984aSJacob Faibussowitsch /* CUDART_VERSION = 1000 x major + 10 x minor version */
26*030f984aSJacob Faibussowitsch 
27*030f984aSJacob Faibussowitsch /* Could not find exactly which CUDART_VERSION introduced cudaGetErrorName. At least it was in CUDA 8.0 (Sep. 2016) */
28*030f984aSJacob Faibussowitsch #if (CUDART_VERSION >= 8000) /* CUDA 8.0 */
29*030f984aSJacob Faibussowitsch #define CHKERRCUDA(cerr)                                                \
30*030f984aSJacob Faibussowitsch   do {                                                                  \
31*030f984aSJacob Faibussowitsch     if (PetscUnlikely(cerr)) {                                          \
32*030f984aSJacob Faibussowitsch       const char *name  = cudaGetErrorName(cerr);                       \
33*030f984aSJacob Faibussowitsch       const char *descr = cudaGetErrorString(cerr);                     \
34*030f984aSJacob Faibussowitsch       SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_GPU,"cuda error %d (%s) : %s", \
35*030f984aSJacob Faibussowitsch                (int)cerr,name,descr);                                   \
36*030f984aSJacob Faibussowitsch     }                                                                   \
37*030f984aSJacob Faibussowitsch   } while (0)
38*030f984aSJacob Faibussowitsch #else
39*030f984aSJacob Faibussowitsch #define CHKERRCUDA(cerr) do {if (PetscUnlikely(cerr)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_GPU,"cuda error %d",(int)cerr);} while (0)
40*030f984aSJacob Faibussowitsch #endif /* CUDART_VERSION >= 8000 */
41*030f984aSJacob Faibussowitsch 
42*030f984aSJacob Faibussowitsch #define CHKERRCUBLAS(stat)                                              \
43*030f984aSJacob Faibussowitsch   do {                                                                  \
44*030f984aSJacob Faibussowitsch     if (PetscUnlikely(stat)) {                                          \
45*030f984aSJacob Faibussowitsch       const char *name = PetscCUBLASGetErrorName(stat);                 \
46*030f984aSJacob Faibussowitsch       if (((stat == CUBLAS_STATUS_NOT_INITIALIZED) || (stat == CUBLAS_STATUS_ALLOC_FAILED)) && PetscCUDAInitialized) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_GPU_RESOURCE,"cuBLAS error %d (%s). Reports not initialized or alloc failed; this indicates the GPU has run out resources",(int)stat,name); \
47*030f984aSJacob Faibussowitsch       else SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_GPU,"cuBLAS error %d (%s)",(int)stat,name); \
48*030f984aSJacob Faibussowitsch     }                                                                   \
49*030f984aSJacob Faibussowitsch   } while (0)
50*030f984aSJacob Faibussowitsch 
51*030f984aSJacob Faibussowitsch #define CHKERRCUSOLVER(stat)                                            \
52*030f984aSJacob Faibussowitsch   do {                                                                  \
53*030f984aSJacob Faibussowitsch     if (PetscUnlikely(stat)) {                                          \
54*030f984aSJacob Faibussowitsch       const char *name = PetscCUSolverGetErrorName(stat);               \
55*030f984aSJacob Faibussowitsch       if ((stat == CUSOLVER_STATUS_NOT_INITIALIZED) || (stat == CUSOLVER_STATUS_ALLOC_FAILED) || (stat == CUSOLVER_STATUS_INTERNAL_ERROR)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_GPU_RESOURCE,"cuSolver error %d (%s). This indicates the GPU has run out resources",(int)stat,name); \
56*030f984aSJacob Faibussowitsch       else SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_GPU,"cuSolver error %d (%s)",(int)stat,name); \
57*030f984aSJacob Faibussowitsch     }                                                                   \
58*030f984aSJacob Faibussowitsch   } while (0)
59*030f984aSJacob Faibussowitsch 
60*030f984aSJacob Faibussowitsch #define CHKERRCUFFT(res)                                                \
61*030f984aSJacob Faibussowitsch   do {                                                                  \
62*030f984aSJacob Faibussowitsch     if (PetscUnlikely(res)) {                                           \
63*030f984aSJacob Faibussowitsch       const char *name = PetscCUFFTGetErrorName(res);                   \
64*030f984aSJacob Faibussowitsch       if (((res == CUFFT_SETUP_FAILED) || (res == CUFFT_ALLOC_FAILED)) && PetscCUDAInitialized) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_GPU_RESOURCE,"cuFFT error %d (%s). Reports not initialized or alloc failed; this indicates the GPU has run out resources",(int)res,name); \
65*030f984aSJacob Faibussowitsch       else SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_GPU,"cuFFT error %d (%s)",(int)res,name); \
66*030f984aSJacob Faibussowitsch     }                                                                   \
67*030f984aSJacob Faibussowitsch   } while (0)
68*030f984aSJacob Faibussowitsch 
69*030f984aSJacob Faibussowitsch PETSC_EXTERN cudaStream_t   PetscDefaultCudaStream; /* The default stream used by PETSc */
70*030f984aSJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscCUBLASInitializeHandle(void);
71*030f984aSJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscCUSOLVERDnInitializeHandle(void);
72*030f984aSJacob Faibussowitsch 
73*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscCUBLASGetHandle(cublasHandle_t*);
74*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscCUSOLVERDnGetHandle(cusolverDnHandle_t*);
75*030f984aSJacob Faibussowitsch #endif /* PetscDefined(HAVE_CUDA) */
76*030f984aSJacob Faibussowitsch 
77*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_HIP)
78*030f984aSJacob Faibussowitsch #include <hip/hip_runtime.h>
79*030f984aSJacob Faibussowitsch #include <hipblas.h>
80*030f984aSJacob Faibussowitsch #if defined(__HIP_PLATFORM_NVCC__)
81*030f984aSJacob Faibussowitsch #include <cusolverDn.h>
82*030f984aSJacob Faibussowitsch #else /* __HIP_PLATFORM_HCC__ */
83*030f984aSJacob Faibussowitsch #include <rocsolver.h>
84*030f984aSJacob Faibussowitsch #endif /* __HIP_PLATFORM_NVCC__ */
85*030f984aSJacob Faibussowitsch 
86*030f984aSJacob Faibussowitsch #define WaitForHIP() PetscHIPSynchronize ? hipDeviceSynchronize() : hipSuccess;
87*030f984aSJacob Faibussowitsch 
88*030f984aSJacob Faibussowitsch PETSC_EXTERN hipEvent_t petsc_gputimer_begin;
89*030f984aSJacob Faibussowitsch PETSC_EXTERN hipEvent_t petsc_gputimer_end;
90*030f984aSJacob Faibussowitsch 
91*030f984aSJacob Faibussowitsch /* hipBLAS does not have hipblasGetErrorName(). We create one on our own. */
92*030f984aSJacob Faibussowitsch PETSC_EXTERN const char* PetscHIPBLASGetErrorName(hipblasStatus_t); /* PETSC_EXTERN since it is exposed by the CHKERRHIPBLAS macro */
93*030f984aSJacob Faibussowitsch 
94*030f984aSJacob Faibussowitsch #define CHKERRHIP(cerr)                                                 \
95*030f984aSJacob Faibussowitsch   do {                                                                  \
96*030f984aSJacob Faibussowitsch     if (PetscUnlikely(cerr)) {                                          \
97*030f984aSJacob Faibussowitsch       const char *name  = hipGetErrorName(cerr);                        \
98*030f984aSJacob Faibussowitsch       const char *descr = hipGetErrorString(cerr);                      \
99*030f984aSJacob Faibussowitsch       SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_LIB,"hip error %d (%s) : %s",  \
100*030f984aSJacob Faibussowitsch                (int)cerr,name,descr);                                   \
101*030f984aSJacob Faibussowitsch     }                                                                   \
102*030f984aSJacob Faibussowitsch   } while (0)
103*030f984aSJacob Faibussowitsch 
104*030f984aSJacob Faibussowitsch #define CHKERRHIPBLAS(stat)                                             \
105*030f984aSJacob Faibussowitsch   do {                                                                  \
106*030f984aSJacob Faibussowitsch     if (PetscUnlikely(stat)) {                                          \
107*030f984aSJacob Faibussowitsch       const char *name = PetscHIPBLASGetErrorName(stat);                \
108*030f984aSJacob Faibussowitsch       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB,"hipBLAS error %d (%s)",   \
109*030f984aSJacob Faibussowitsch                (int)stat,name);                                         \
110*030f984aSJacob Faibussowitsch     }                                                                   \
111*030f984aSJacob Faibussowitsch   } while (0)
112*030f984aSJacob Faibussowitsch 
113*030f984aSJacob Faibussowitsch /* TODO: SEK:  Need to figure out the hipsolver issues */
114*030f984aSJacob Faibussowitsch #define CHKERRHIPSOLVER(err)                                            \
115*030f984aSJacob Faibussowitsch   do {                                                                  \
116*030f984aSJacob Faibussowitsch     if (PetscUnlikely(err)) {                                           \
117*030f984aSJacob Faibussowitsch       SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"HIPSOLVER error %d",err); \
118*030f984aSJacob Faibussowitsch     }                                                                   \
119*030f984aSJacob Faibussowitsch   } while (0)
120*030f984aSJacob Faibussowitsch 
121*030f984aSJacob Faibussowitsch /* hipSolver does not exist yet so we work around it
122*030f984aSJacob Faibussowitsch    rocSOLVER users rocBLAS for the handle
123*030f984aSJacob Faibussowitsch  * */
124*030f984aSJacob Faibussowitsch #if defined(__HIP_PLATFORM_NVCC__)
125*030f984aSJacob Faibussowitsch typedef cusolverDnHandle_t hipsolverHandle_t;
126*030f984aSJacob Faibussowitsch typedef cusolverStatus_t   hipsolverStatus_t;
127*030f984aSJacob Faibussowitsch 
128*030f984aSJacob Faibussowitsch /* Alias hipsolverDestroy to cusolverDnDestroy */
129*030f984aSJacob Faibussowitsch PETSC_STATIC_INLINE hipsolverStatus_t hipsolverDestroy(hipsolverHandle_t *hipsolverhandle)
130*030f984aSJacob Faibussowitsch {
131*030f984aSJacob Faibussowitsch   return cusolverDnDestroy(hipsolverhandle)
132*030f984aSJacob Faibussowitsch }
133*030f984aSJacob Faibussowitsch 
134*030f984aSJacob Faibussowitsch /* Alias hipsolverCreate to cusolverDnCreate */
135*030f984aSJacob Faibussowitsch PETSC_STATIC_INLINE hipsolverStatus_t hipsolverCreate(hipsolverHandle_t *hipsolverhandle)
136*030f984aSJacob Faibussowitsch {
137*030f984aSJacob Faibussowitsch   return cusolverDnCreate(hipsolverhandle)
138*030f984aSJacob Faibussowitsch }
139*030f984aSJacob Faibussowitsch 
140*030f984aSJacob Faibussowitsch /* Alias hipsolverGetStream to cusolverDnGetStream */
141*030f984aSJacob Faibussowitsch PETSC_STATIC_INLINE hipsolverStatus_t hipsolverGetStream(hipsolverHandle_t handle, hipStream_t *stream)
142*030f984aSJacob Faibussowitsch {
143*030f984aSJacob Faibussowitsch   return cusolverDnGetStream(handle,stream);
144*030f984aSJacob Faibussowitsch }
145*030f984aSJacob Faibussowitsch 
146*030f984aSJacob Faibussowitsch /* Alias hipsolverSetStream to cusolverDnSetStream */
147*030f984aSJacob Faibussowitsch PETSC_STATIC_INLINE hipsolverStatus_t hipsolverSetStream(hipsolverHandle_t handle, hipStream_t stream)
148*030f984aSJacob Faibussowitsch {
149*030f984aSJacob Faibussowitsch   return cusolveDnSetStream(handle,stream);
150*030f984aSJacob Faibussowitsch }
151*030f984aSJacob Faibussowitsch #else /* __HIP_PLATFORM_HCC__ */
152*030f984aSJacob Faibussowitsch typedef rocblas_handle hipsolverHandle_t;
153*030f984aSJacob Faibussowitsch typedef rocblas_status hipsolverStatus_t;
154*030f984aSJacob Faibussowitsch 
155*030f984aSJacob Faibussowitsch /* Alias hipsolverDestroy to rocblas_destroy_handle */
156*030f984aSJacob Faibussowitsch PETSC_STATIC_INLINE hipsolverStatus_t hipsolverDestroy(hipsolverHandle_t  hipsolverhandle)
157*030f984aSJacob Faibussowitsch {
158*030f984aSJacob Faibussowitsch   return rocblas_destroy_handle(hipsolverhandle);
159*030f984aSJacob Faibussowitsch }
160*030f984aSJacob Faibussowitsch 
161*030f984aSJacob Faibussowitsch /* Alias hipsolverCreate to rocblas_destroy_handle */
162*030f984aSJacob Faibussowitsch PETSC_STATIC_INLINE hipsolverStatus_t hipsolverCreate(hipsolverHandle_t *hipsolverhandle)
163*030f984aSJacob Faibussowitsch {
164*030f984aSJacob Faibussowitsch   return rocblas_create_handle(hipsolverhandle);
165*030f984aSJacob Faibussowitsch }
166*030f984aSJacob Faibussowitsch 
167*030f984aSJacob Faibussowitsch /* Alias hipsolverGetStream to rocblas_get_stream */
168*030f984aSJacob Faibussowitsch PETSC_STATIC_INLINE hipsolverStatus_t hipsolverGetStream(hipsolverHandle_t handle, hipStream_t *stream)
169*030f984aSJacob Faibussowitsch {
170*030f984aSJacob Faibussowitsch   return rocblas_get_stream(handle,stream);
171*030f984aSJacob Faibussowitsch }
172*030f984aSJacob Faibussowitsch 
173*030f984aSJacob Faibussowitsch /* Alias hipsolverSetStream to rocblas_set_stream */
174*030f984aSJacob Faibussowitsch PETSC_STATIC_INLINE hipsolverStatus_t hipsolverSetStream(hipsolverHandle_t handle, hipStream_t stream)
175*030f984aSJacob Faibussowitsch {
176*030f984aSJacob Faibussowitsch   return rocblas_set_stream(handle,stream);
177*030f984aSJacob Faibussowitsch }
178*030f984aSJacob Faibussowitsch #endif /* __HIP_PLATFORM_NVCC__ */
179*030f984aSJacob Faibussowitsch PETSC_EXTERN hipStream_t    PetscDefaultHipStream; /* The default stream used by PETSc */
180*030f984aSJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscHIPBLASInitializeHandle(void);
181*030f984aSJacob Faibussowitsch PETSC_INTERN PetscErrorCode PetscHIPSOLVERInitializeHandle(void);
182*030f984aSJacob Faibussowitsch 
183*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscHIPBLASGetHandle(hipblasHandle_t*);
184*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscHIPSOLVERGetHandle(hipsolverHandle_t*);
185*030f984aSJacob Faibussowitsch #endif /* PetscDefined(HAVE_HIP) */
186*030f984aSJacob Faibussowitsch 
187*030f984aSJacob Faibussowitsch /* Cannot use the device context api without C++11 */
188*030f984aSJacob Faibussowitsch #if PetscDefined(HAVE_CXX_DIALECT_CXX11)
189*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceInitializePackage(void);
190*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceFinalizePackage(void);
191*030f984aSJacob Faibussowitsch 
192*030f984aSJacob Faibussowitsch /* PetscDevice */
193*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceCreate(PetscDeviceKind,PetscDevice*);
194*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceConfigure(PetscDevice);
195*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceDestroy(PetscDevice*);
196*030f984aSJacob Faibussowitsch 
197*030f984aSJacob Faibussowitsch /* PetscDeviceContext */
198*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextCreate(PetscDeviceContext*);
199*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextDestroy(PetscDeviceContext*);
200*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextSetDevice(PetscDeviceContext,PetscDevice);
201*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextGetDevice(PetscDeviceContext,PetscDevice*);
202*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextSetStreamType(PetscDeviceContext,PetscStreamType);
203*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextGetStreamType(PetscDeviceContext,PetscStreamType*);
204*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextSetUp(PetscDeviceContext);
205*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextDuplicate(PetscDeviceContext,PetscDeviceContext*);
206*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextQueryIdle(PetscDeviceContext,PetscBool*);
207*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextWaitForContext(PetscDeviceContext,PetscDeviceContext);
208*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextFork(PetscDeviceContext,PetscInt,PetscDeviceContext**);
209*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextJoin(PetscDeviceContext,PetscInt,PetscDeviceContextJoinMode,PetscDeviceContext**);
210*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextSynchronize(PetscDeviceContext);
211*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextGetCurrentContext(PetscDeviceContext*);
212*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextSetCurrentContext(PetscDeviceContext);
213*030f984aSJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscDeviceContextSetFromOptions(MPI_Comm,const char[],PetscDeviceContext);
214*030f984aSJacob Faibussowitsch #endif /* PetscDefined(HAVE_CXX_DIALECT_CXX11) */
215*030f984aSJacob Faibussowitsch #endif /* PETSCDEVICE_H */
216