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