1a4963045SJacob Faibussowitsch #pragma once 20e6b6b59SJacob Faibussowitsch 30e6b6b59SJacob Faibussowitsch #include <petscdevice.h> 40e6b6b59SJacob Faibussowitsch #include <petscpkg_version.h> 50e6b6b59SJacob Faibussowitsch 61850900dSBarry Smith /* MANSEC = Sys */ 71850900dSBarry Smith 80e6b6b59SJacob Faibussowitsch #if defined(__NVCC__) || defined(__CUDACC__) 90e6b6b59SJacob Faibussowitsch #define PETSC_USING_NVCC 1 100e6b6b59SJacob Faibussowitsch #endif 110e6b6b59SJacob Faibussowitsch 120e6b6b59SJacob Faibussowitsch #if PetscDefined(HAVE_CUDA) 130e6b6b59SJacob Faibussowitsch #include <cuda.h> 140e6b6b59SJacob Faibussowitsch #include <cuda_runtime.h> 150e6b6b59SJacob Faibussowitsch #include <cublas_v2.h> 162695cf96SNuno Nobre #define DISABLE_CUSPARSE_DEPRECATED 172695cf96SNuno Nobre #include <cusparse.h> 180e6b6b59SJacob Faibussowitsch #include <cusolverDn.h> 190e6b6b59SJacob Faibussowitsch #include <cusolverSp.h> 200e6b6b59SJacob Faibussowitsch #include <cufft.h> 212695cf96SNuno Nobre #include <curand.h> 225268dc8aSHong Zhang #include <nvml.h> // NVML comes with the NVIDIA GPU driver 230e6b6b59SJacob Faibussowitsch 240e6b6b59SJacob Faibussowitsch /* cuBLAS does not have cublasGetErrorName(). We create one on our own. */ 250e6b6b59SJacob Faibussowitsch PETSC_EXTERN const char *PetscCUBLASGetErrorName(cublasStatus_t); /* PETSC_EXTERN since it is exposed by the CHKERRCUBLAS macro */ 260e6b6b59SJacob Faibussowitsch PETSC_EXTERN const char *PetscCUSolverGetErrorName(cusolverStatus_t); 270e6b6b59SJacob Faibussowitsch PETSC_EXTERN const char *PetscCUFFTGetErrorName(cufftResult); 280e6b6b59SJacob Faibussowitsch 290e6b6b59SJacob Faibussowitsch /* REMOVE ME */ 300e6b6b59SJacob Faibussowitsch #define WaitForCUDA() cudaDeviceSynchronize() 310e6b6b59SJacob Faibussowitsch 320e6b6b59SJacob Faibussowitsch /* CUDART_VERSION = 1000 x major + 10 x minor version */ 330e6b6b59SJacob Faibussowitsch 340e6b6b59SJacob Faibussowitsch /* Could not find exactly which CUDART_VERSION introduced cudaGetErrorName. At least it was in CUDA 8.0 (Sep. 2016) */ 350e6b6b59SJacob Faibussowitsch #if PETSC_PKG_CUDA_VERSION_GE(8, 0, 0) 360e6b6b59SJacob Faibussowitsch #define PetscCallCUDAVoid(...) \ 370e6b6b59SJacob Faibussowitsch do { \ 380e6b6b59SJacob Faibussowitsch const cudaError_t _p_cuda_err__ = __VA_ARGS__; \ 390e6b6b59SJacob Faibussowitsch PetscCheckAbort(_p_cuda_err__ == cudaSuccess, PETSC_COMM_SELF, PETSC_ERR_GPU, "cuda error %d (%s) : %s", (PetscErrorCode)_p_cuda_err__, cudaGetErrorName(_p_cuda_err__), cudaGetErrorString(_p_cuda_err__)); \ 400e6b6b59SJacob Faibussowitsch } while (0) 410e6b6b59SJacob Faibussowitsch 420e6b6b59SJacob Faibussowitsch #define PetscCallCUDA(...) \ 430e6b6b59SJacob Faibussowitsch do { \ 440e6b6b59SJacob Faibussowitsch const cudaError_t _p_cuda_err__ = __VA_ARGS__; \ 450e6b6b59SJacob Faibussowitsch PetscCheck(_p_cuda_err__ == cudaSuccess, PETSC_COMM_SELF, PETSC_ERR_GPU, "cuda error %d (%s) : %s", (PetscErrorCode)_p_cuda_err__, cudaGetErrorName(_p_cuda_err__), cudaGetErrorString(_p_cuda_err__)); \ 460e6b6b59SJacob Faibussowitsch } while (0) 470e6b6b59SJacob Faibussowitsch #else /* PETSC_PKG_CUDA_VERSION_GE(8,0,0) */ 480e6b6b59SJacob Faibussowitsch #define PetscCallCUDA(...) \ 490e6b6b59SJacob Faibussowitsch do { \ 500e6b6b59SJacob Faibussowitsch const cudaError_t _p_cuda_err__ = __VA_ARGS__; \ 510e6b6b59SJacob Faibussowitsch PetscCheck(_p_cuda_err__ == cudaSuccess, PETSC_COMM_SELF, PETSC_ERR_GPU, "cuda error %d", (PetscErrorCode)_p_cuda_err__); \ 520e6b6b59SJacob Faibussowitsch } while (0) 530e6b6b59SJacob Faibussowitsch 540e6b6b59SJacob Faibussowitsch #define PetscCallCUDAVoid(...) \ 550e6b6b59SJacob Faibussowitsch do { \ 560e6b6b59SJacob Faibussowitsch const cudaError_t _p_cuda_err__ = __VA_ARGS__; \ 570e6b6b59SJacob Faibussowitsch PetscCheckAbort(_p_cuda_err__ == cudaSuccess, PETSC_COMM_SELF, PETSC_ERR_GPU, "cuda error %d", (PetscErrorCode)_p_cuda_err__); \ 580e6b6b59SJacob Faibussowitsch } while (0) 590e6b6b59SJacob Faibussowitsch #endif /* PETSC_PKG_CUDA_VERSION_GE(8,0,0) */ 600e6b6b59SJacob Faibussowitsch #define CHKERRCUDA(...) PetscCallCUDA(__VA_ARGS__) 610e6b6b59SJacob Faibussowitsch 620e6b6b59SJacob Faibussowitsch #define PetscCUDACheckLaunch \ 630e6b6b59SJacob Faibussowitsch do { \ 640e6b6b59SJacob Faibussowitsch /* Check synchronous errors, i.e. pre-launch */ \ 650e6b6b59SJacob Faibussowitsch PetscCallCUDA(cudaGetLastError()); \ 660e6b6b59SJacob Faibussowitsch /* Check asynchronous errors, i.e. kernel failed (ULF) */ \ 670e6b6b59SJacob Faibussowitsch PetscCallCUDA(cudaDeviceSynchronize()); \ 680e6b6b59SJacob Faibussowitsch } while (0) 690e6b6b59SJacob Faibussowitsch 700e6b6b59SJacob Faibussowitsch #define PetscCallCUBLAS(...) \ 710e6b6b59SJacob Faibussowitsch do { \ 720e6b6b59SJacob Faibussowitsch const cublasStatus_t _p_cublas_stat__ = __VA_ARGS__; \ 730e6b6b59SJacob Faibussowitsch if (PetscUnlikely(_p_cublas_stat__ != CUBLAS_STATUS_SUCCESS)) { \ 740e6b6b59SJacob Faibussowitsch const char *name = PetscCUBLASGetErrorName(_p_cublas_stat__); \ 750e6b6b59SJacob Faibussowitsch if (((_p_cublas_stat__ == CUBLAS_STATUS_NOT_INITIALIZED) || (_p_cublas_stat__ == CUBLAS_STATUS_ALLOC_FAILED)) && PetscDeviceInitialized(PETSC_DEVICE_CUDA)) { \ 760e6b6b59SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_GPU_RESOURCE, \ 770e6b6b59SJacob Faibussowitsch "cuBLAS error %d (%s). " \ 780e6b6b59SJacob Faibussowitsch "Reports not initialized or alloc failed; " \ 790e6b6b59SJacob Faibussowitsch "this indicates the GPU may have run out resources", \ 800e6b6b59SJacob Faibussowitsch (PetscErrorCode)_p_cublas_stat__, name); \ 810e6b6b59SJacob Faibussowitsch } else { \ 820e6b6b59SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_GPU, "cuBLAS error %d (%s)", (PetscErrorCode)_p_cublas_stat__, name); \ 830e6b6b59SJacob Faibussowitsch } \ 840e6b6b59SJacob Faibussowitsch } \ 850e6b6b59SJacob Faibussowitsch } while (0) 860e6b6b59SJacob Faibussowitsch #define CHKERRCUBLAS(...) PetscCallCUBLAS(__VA_ARGS__) 870e6b6b59SJacob Faibussowitsch 880e6b6b59SJacob Faibussowitsch #if (CUSPARSE_VER_MAJOR > 10 || CUSPARSE_VER_MAJOR == 10 && CUSPARSE_VER_MINOR >= 2) /* According to cuda/10.1.168 on OLCF Summit */ 890e6b6b59SJacob Faibussowitsch #define PetscCallCUSPARSE(...) \ 900e6b6b59SJacob Faibussowitsch do { \ 910e6b6b59SJacob Faibussowitsch const cusparseStatus_t _p_cusparse_stat__ = __VA_ARGS__; \ 920e6b6b59SJacob Faibussowitsch if (PetscUnlikely(_p_cusparse_stat__)) { \ 930e6b6b59SJacob Faibussowitsch const char *name = cusparseGetErrorName(_p_cusparse_stat__); \ 940e6b6b59SJacob Faibussowitsch const char *descr = cusparseGetErrorString(_p_cusparse_stat__); \ 950e6b6b59SJacob Faibussowitsch PetscCheck((_p_cusparse_stat__ != CUSPARSE_STATUS_NOT_INITIALIZED) && (_p_cusparse_stat__ != CUSPARSE_STATUS_ALLOC_FAILED), PETSC_COMM_SELF, PETSC_ERR_GPU_RESOURCE, \ 960e6b6b59SJacob Faibussowitsch "cuSPARSE errorcode %d (%s) : %s.; " \ 970e6b6b59SJacob Faibussowitsch "this indicates the GPU has run out resources", \ 980e6b6b59SJacob Faibussowitsch (int)_p_cusparse_stat__, name, descr); \ 990e6b6b59SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_GPU, "cuSPARSE errorcode %d (%s) : %s", (int)_p_cusparse_stat__, name, descr); \ 1000e6b6b59SJacob Faibussowitsch } \ 1010e6b6b59SJacob Faibussowitsch } while (0) 1020e6b6b59SJacob Faibussowitsch #else /* (CUSPARSE_VER_MAJOR > 10 || CUSPARSE_VER_MAJOR == 10 && CUSPARSE_VER_MINOR >= 2) */ 1030e6b6b59SJacob Faibussowitsch #define PetscCallCUSPARSE(...) \ 1040e6b6b59SJacob Faibussowitsch do { \ 1050e6b6b59SJacob Faibussowitsch const cusparseStatus_t _p_cusparse_stat__ = __VA_ARGS__; \ 1060e6b6b59SJacob Faibussowitsch PetscCheck(_p_cusparse_stat__ == CUSPARSE_STATUS_SUCCESS, PETSC_COMM_SELF, PETSC_ERR_GPU, "cuSPARSE errorcode %d", (PetscErrorCode)_p_cusparse_stat__); \ 1070e6b6b59SJacob Faibussowitsch } while (0) 1080e6b6b59SJacob Faibussowitsch #endif /* (CUSPARSE_VER_MAJOR > 10 || CUSPARSE_VER_MAJOR == 10 && CUSPARSE_VER_MINOR >= 2) */ 1090e6b6b59SJacob Faibussowitsch #define CHKERRCUSPARSE(...) PetscCallCUSPARSE(__VA_ARGS__) 1100e6b6b59SJacob Faibussowitsch 1110e6b6b59SJacob Faibussowitsch #define PetscCallCUSOLVER(...) \ 1120e6b6b59SJacob Faibussowitsch do { \ 1130e6b6b59SJacob Faibussowitsch const cusolverStatus_t _p_cusolver_stat__ = __VA_ARGS__; \ 1140e6b6b59SJacob Faibussowitsch if (PetscUnlikely(_p_cusolver_stat__ != CUSOLVER_STATUS_SUCCESS)) { \ 1150e6b6b59SJacob Faibussowitsch const char *name = PetscCUSolverGetErrorName(_p_cusolver_stat__); \ 1160e6b6b59SJacob Faibussowitsch if (((_p_cusolver_stat__ == CUSOLVER_STATUS_NOT_INITIALIZED) || (_p_cusolver_stat__ == CUSOLVER_STATUS_ALLOC_FAILED) || (_p_cusolver_stat__ == CUSOLVER_STATUS_INTERNAL_ERROR)) && PetscDeviceInitialized(PETSC_DEVICE_CUDA)) { \ 1170e6b6b59SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_GPU_RESOURCE, \ 1180e6b6b59SJacob Faibussowitsch "cuSolver error %d (%s). " \ 1190e6b6b59SJacob Faibussowitsch "This indicates the GPU may have run out resources", \ 1200e6b6b59SJacob Faibussowitsch (PetscErrorCode)_p_cusolver_stat__, name); \ 1210e6b6b59SJacob Faibussowitsch } else { \ 1220e6b6b59SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_GPU, "cuSolver error %d (%s)", (PetscErrorCode)_p_cusolver_stat__, name); \ 1230e6b6b59SJacob Faibussowitsch } \ 1240e6b6b59SJacob Faibussowitsch } \ 1250e6b6b59SJacob Faibussowitsch } while (0) 1260e6b6b59SJacob Faibussowitsch #define CHKERRCUSOLVER(...) PetscCallCUSOLVER(__VA_ARGS__) 1270e6b6b59SJacob Faibussowitsch 1280e6b6b59SJacob Faibussowitsch #define PetscCallCUFFT(...) \ 1290e6b6b59SJacob Faibussowitsch do { \ 1300e6b6b59SJacob Faibussowitsch const cufftResult_t _p_cufft_stat__ = __VA_ARGS__; \ 1310e6b6b59SJacob Faibussowitsch if (PetscUnlikely(_p_cufft_stat__ != CUFFT_SUCCESS)) { \ 1320e6b6b59SJacob Faibussowitsch const char *name = PetscCUFFTGetErrorName(_p_cufft_stat__); \ 1330e6b6b59SJacob Faibussowitsch if (((_p_cufft_stat__ == CUFFT_SETUP_FAILED) || (_p_cufft_stat__ == CUFFT_ALLOC_FAILED)) && PetscDeviceInitialized(PETSC_DEVICE_CUDA)) { \ 1340e6b6b59SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_GPU_RESOURCE, \ 1350e6b6b59SJacob Faibussowitsch "cuFFT error %d (%s). " \ 1360e6b6b59SJacob Faibussowitsch "Reports not initialized or alloc failed; " \ 1370e6b6b59SJacob Faibussowitsch "this indicates the GPU has run out resources", \ 1380e6b6b59SJacob Faibussowitsch (PetscErrorCode)_p_cufft_stat__, name); \ 1390e6b6b59SJacob Faibussowitsch } else { \ 1400e6b6b59SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_GPU, "cuFFT error %d (%s)", (PetscErrorCode)_p_cufft_stat__, name); \ 1410e6b6b59SJacob Faibussowitsch } \ 1420e6b6b59SJacob Faibussowitsch } \ 1430e6b6b59SJacob Faibussowitsch } while (0) 1440e6b6b59SJacob Faibussowitsch #define CHKERRCUFFT(...) PetscCallCUFFT(__VA_ARGS__) 1450e6b6b59SJacob Faibussowitsch 1460e6b6b59SJacob Faibussowitsch #define PetscCallCURAND(...) \ 1470e6b6b59SJacob Faibussowitsch do { \ 1480e6b6b59SJacob Faibussowitsch const curandStatus_t _p_curand_stat__ = __VA_ARGS__; \ 1490e6b6b59SJacob Faibussowitsch if (PetscUnlikely(_p_curand_stat__ != CURAND_STATUS_SUCCESS)) { \ 1500e6b6b59SJacob Faibussowitsch if (((_p_curand_stat__ == CURAND_STATUS_INITIALIZATION_FAILED) || (_p_curand_stat__ == CURAND_STATUS_ALLOCATION_FAILED)) && PetscDeviceInitialized(PETSC_DEVICE_CUDA)) { \ 1510e6b6b59SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_GPU_RESOURCE, \ 1520e6b6b59SJacob Faibussowitsch "cuRAND error %d. " \ 1530e6b6b59SJacob Faibussowitsch "Reports not initialized or alloc failed; " \ 1540e6b6b59SJacob Faibussowitsch "this indicates the GPU has run out resources", \ 1550e6b6b59SJacob Faibussowitsch (PetscErrorCode)_p_curand_stat__); \ 1560e6b6b59SJacob Faibussowitsch } else { \ 1570e6b6b59SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_GPU, "cuRand error %d", (PetscErrorCode)_p_curand_stat__); \ 1580e6b6b59SJacob Faibussowitsch } \ 1590e6b6b59SJacob Faibussowitsch } \ 1600e6b6b59SJacob Faibussowitsch } while (0) 1610e6b6b59SJacob Faibussowitsch #define CHKERRCURAND(...) PetscCallCURAND(__VA_ARGS__) 1620e6b6b59SJacob Faibussowitsch 1630e6b6b59SJacob Faibussowitsch PETSC_EXTERN cudaStream_t PetscDefaultCudaStream; // The default stream used by PETSc 1640e6b6b59SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscCUBLASGetHandle(cublasHandle_t *); 1650e6b6b59SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscCUSOLVERDnGetHandle(cusolverDnHandle_t *); 1665c127019SJunchao Zhang PETSC_EXTERN PetscErrorCode PetscGetCurrentCUDAStream(cudaStream_t *); 1670e6b6b59SJacob Faibussowitsch 1680e6b6b59SJacob Faibussowitsch #endif // PETSC_HAVE_CUDA 1690e6b6b59SJacob Faibussowitsch 17015af11aaSJacob Faibussowitsch // these can also be defined in petscdevice_hip.h so we undef and define them *only* if the 17115af11aaSJacob Faibussowitsch // current compiler is NVCC. In this case if petscdevice_hip.h is included first, the macros 17215af11aaSJacob Faibussowitsch // would already be defined, but they would be empty since we cannot be using HCC at the same 17315af11aaSJacob Faibussowitsch // time. 1740e6b6b59SJacob Faibussowitsch #if PetscDefined(USING_NVCC) 17515af11aaSJacob Faibussowitsch #undef PETSC_HOST_DECL 17615af11aaSJacob Faibussowitsch #undef PETSC_DEVICE_DECL 17715af11aaSJacob Faibussowitsch #undef PETSC_KERNEL_DECL 17815af11aaSJacob Faibussowitsch #undef PETSC_SHAREDMEM_DECL 17915af11aaSJacob Faibussowitsch #undef PETSC_FORCEINLINE 18015af11aaSJacob Faibussowitsch #undef PETSC_CONSTMEM_DECL 18115af11aaSJacob Faibussowitsch 1820e6b6b59SJacob Faibussowitsch #define PETSC_HOST_DECL __host__ 1830e6b6b59SJacob Faibussowitsch #define PETSC_DEVICE_DECL __device__ 1840e6b6b59SJacob Faibussowitsch #define PETSC_KERNEL_DECL __global__ 1850e6b6b59SJacob Faibussowitsch #define PETSC_SHAREDMEM_DECL __shared__ 1860e6b6b59SJacob Faibussowitsch #define PETSC_FORCEINLINE __forceinline__ 1870e6b6b59SJacob Faibussowitsch #define PETSC_CONSTMEM_DECL __constant__ 18815af11aaSJacob Faibussowitsch #endif 18915af11aaSJacob Faibussowitsch 190*beceaeb6SBarry Smith #if !defined(PETSC_HOST_DECL) // use HOST_DECL as canary 1910e6b6b59SJacob Faibussowitsch #define PETSC_HOST_DECL 1920e6b6b59SJacob Faibussowitsch #define PETSC_DEVICE_DECL 1930e6b6b59SJacob Faibussowitsch #define PETSC_KERNEL_DECL 1940e6b6b59SJacob Faibussowitsch #define PETSC_SHAREDMEM_DECL 1950e6b6b59SJacob Faibussowitsch #define PETSC_FORCEINLINE inline 1960e6b6b59SJacob Faibussowitsch #define PETSC_CONSTMEM_DECL 19715af11aaSJacob Faibussowitsch #endif 1980e6b6b59SJacob Faibussowitsch 199*beceaeb6SBarry Smith #if !defined(PETSC_DEVICE_DEFINED_DECLS_PRIVATE) 20015af11aaSJacob Faibussowitsch #define PETSC_DEVICE_DEFINED_DECLS_PRIVATE 2010e6b6b59SJacob Faibussowitsch #define PETSC_HOSTDEVICE_DECL PETSC_HOST_DECL PETSC_DEVICE_DECL 2020e6b6b59SJacob Faibussowitsch #define PETSC_DEVICE_INLINE_DECL PETSC_DEVICE_DECL PETSC_FORCEINLINE 2030e6b6b59SJacob Faibussowitsch #define PETSC_HOSTDEVICE_INLINE_DECL PETSC_HOSTDEVICE_DECL PETSC_FORCEINLINE 20415af11aaSJacob Faibussowitsch #endif 205