Actual source code: cd_cupm.cxx
1: #include "../denseqn.h"
2: #include <petsc/private/cupminterface.hpp>
3: #include <petsc/private/cupmobject.hpp>
5: namespace Petsc
6: {
8: namespace device
9: {
11: namespace cupm
12: {
14: namespace impl
15: {
17: template <DeviceType T>
18: struct UpperTriangular : CUPMObject<T> {
19: PETSC_CUPMOBJECT_HEADER(T);
21: static PetscErrorCode SolveInPlace(PetscDeviceContext, PetscBool, PetscInt, const PetscScalar[], PetscInt, PetscScalar[], PetscInt) noexcept;
22: static PetscErrorCode SolveInPlaceCyclic(PetscDeviceContext, PetscBool, PetscInt, PetscInt, PetscInt, const PetscScalar[], PetscInt, PetscScalar[], PetscInt) noexcept;
23: };
25: template <DeviceType T>
26: PetscErrorCode UpperTriangular<T>::SolveInPlace(PetscDeviceContext dctx, PetscBool hermitian_transpose, PetscInt N, const PetscScalar A[], PetscInt lda, PetscScalar x[], PetscInt stride) noexcept
27: {
28: cupmBlasInt_t n;
29: cupmBlasHandle_t handle;
30: auto A_ = cupmScalarPtrCast(A);
31: auto x_ = cupmScalarPtrCast(x);
33: PetscFunctionBegin;
34: if (!N) PetscFunctionReturn(PETSC_SUCCESS);
35: PetscCall(PetscCUPMBlasIntCast(N, &n));
36: PetscCall(GetHandlesFrom_(dctx, &handle));
37: PetscCall(PetscLogGpuTimeBegin());
38: PetscCallCUPMBLAS(cupmBlasXtrsv(handle, CUPMBLAS_FILL_MODE_UPPER, hermitian_transpose ? CUPMBLAS_OP_C : CUPMBLAS_OP_N, CUPMBLAS_DIAG_NON_UNIT, n, A_, lda, x_, stride));
39: PetscCall(PetscLogGpuTimeEnd());
41: PetscCall(PetscLogGpuFlops(1.0 * N * N));
42: PetscCall(PetscDeviceContextSynchronizeIfWithBarrier_Internal(dctx));
43: PetscFunctionReturn(PETSC_SUCCESS);
44: }
46: template <DeviceType T>
47: PetscErrorCode UpperTriangular<T>::SolveInPlaceCyclic(PetscDeviceContext dctx, PetscBool hermitian_transpose, PetscInt m, PetscInt oldest, PetscInt next, const PetscScalar A[], PetscInt lda, PetscScalar x[], PetscInt stride) noexcept
48: {
49: PetscInt N = next - oldest;
50: PetscInt oldest_index = oldest % m;
51: PetscInt next_index = next % m;
52: cupmBlasInt_t n_old, n_new;
53: cupmBlasPointerMode_t pointer_mode;
54: cupmBlasHandle_t handle;
55: auto sone = cupmScalarCast(1.0);
56: auto minus_one = cupmScalarCast(-1.0);
57: auto A_ = cupmScalarPtrCast(A);
58: auto x_ = cupmScalarPtrCast(x);
60: PetscFunctionBegin;
61: if (!N) PetscFunctionReturn(PETSC_SUCCESS);
62: PetscCall(PetscCUPMBlasIntCast(m - oldest_index, &n_old));
63: PetscCall(PetscCUPMBlasIntCast(next_index, &n_new));
64: PetscCall(GetHandlesFrom_(dctx, &handle));
65: PetscCall(PetscLogGpuTimeBegin());
66: PetscCallCUPMBLAS(cupmBlasGetPointerMode(handle, &pointer_mode));
67: PetscCallCUPMBLAS(cupmBlasSetPointerMode(handle, CUPMBLAS_POINTER_MODE_HOST));
68: if (!hermitian_transpose) {
69: if (n_new > 0) PetscCallCUPMBLAS(cupmBlasXtrsv(handle, CUPMBLAS_FILL_MODE_UPPER, CUPMBLAS_OP_N, CUPMBLAS_DIAG_NON_UNIT, n_new, A_, lda, x_, stride));
70: if (n_new > 0 && n_old > 0) PetscCallCUPMBLAS(cupmBlasXgemv(handle, CUPMBLAS_OP_N, n_old, n_new, &minus_one, &A_[oldest_index], lda, x_, stride, &sone, &x_[oldest_index], stride));
71: if (n_old > 0) PetscCallCUPMBLAS(cupmBlasXtrsv(handle, CUPMBLAS_FILL_MODE_UPPER, CUPMBLAS_OP_N, CUPMBLAS_DIAG_NON_UNIT, n_old, &A_[oldest_index * (lda + 1)], lda, &x_[oldest_index], stride));
72: } else {
73: if (n_old > 0) PetscCallCUPMBLAS(cupmBlasXtrsv(handle, CUPMBLAS_FILL_MODE_UPPER, CUPMBLAS_OP_C, CUPMBLAS_DIAG_NON_UNIT, n_old, &A_[oldest_index * (lda + 1)], lda, &x_[oldest_index], stride));
74: if (n_new > 0 && n_old > 0) PetscCallCUPMBLAS(cupmBlasXgemv(handle, CUPMBLAS_OP_C, n_old, n_new, &minus_one, &A_[oldest_index], lda, &x_[oldest_index], stride, &sone, x_, stride));
75: if (n_new > 0) PetscCallCUPMBLAS(cupmBlasXtrsv(handle, CUPMBLAS_FILL_MODE_UPPER, CUPMBLAS_OP_C, CUPMBLAS_DIAG_NON_UNIT, n_new, A_, lda, x_, stride));
76: }
77: PetscCallCUPMBLAS(cupmBlasSetPointerMode(handle, pointer_mode));
78: PetscCall(PetscLogGpuTimeEnd());
80: PetscCall(PetscLogGpuFlops(1.0 * N * N));
81: PetscCall(PetscDeviceContextSynchronizeIfWithBarrier_Internal(dctx));
82: PetscFunctionReturn(PETSC_SUCCESS);
83: }
85: #if PetscDefined(HAVE_CUDA)
86: template struct UpperTriangular<DeviceType::CUDA>;
87: #endif
89: #if PetscDefined(HAVE_HIP)
90: template struct UpperTriangular<DeviceType::HIP>;
91: #endif
93: } // namespace impl
95: } // namespace cupm
97: } // namespace device
99: } // namespace Petsc
101: PETSC_INTERN PetscErrorCode MatUpperTriangularSolveInPlace_CUPM(PetscBool hermitian_transpose, PetscInt n, const PetscScalar A[], PetscInt lda, PetscScalar x[], PetscInt stride)
102: {
103: using ::Petsc::device::cupm::impl::UpperTriangular;
104: using ::Petsc::device::cupm::DeviceType;
105: PetscDeviceContext dctx;
106: PetscDeviceType device_type;
108: PetscFunctionBegin;
109: PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
110: PetscCall(PetscDeviceContextGetDeviceType(dctx, &device_type));
111: switch (device_type) {
112: #if PetscDefined(HAVE_CUDA)
113: case PETSC_DEVICE_CUDA:
114: PetscCall(UpperTriangular<DeviceType::CUDA>::SolveInPlace(dctx, hermitian_transpose, n, A, lda, x, stride));
115: break;
116: #endif
117: #if PetscDefined(HAVE_HIP)
118: case PETSC_DEVICE_HIP:
119: PetscCall(UpperTriangular<DeviceType::HIP>::SolveInPlace(dctx, hermitian_transpose, n, A, lda, x, stride));
120: break;
121: #endif
122: default:
123: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported device type %s", PetscDeviceTypes[device_type]);
124: }
125: PetscFunctionReturn(PETSC_SUCCESS);
126: }
128: PETSC_INTERN PetscErrorCode MatUpperTriangularSolveInPlaceCyclic_CUPM(PetscBool hermitian_transpose, PetscInt m, PetscInt oldest, PetscInt next, const PetscScalar A[], PetscInt lda, PetscScalar x[], PetscInt stride)
129: {
130: using ::Petsc::device::cupm::impl::UpperTriangular;
131: using ::Petsc::device::cupm::DeviceType;
132: PetscDeviceContext dctx;
133: PetscDeviceType device_type;
135: PetscFunctionBegin;
136: PetscCall(PetscDeviceContextGetCurrentContext(&dctx));
137: PetscCall(PetscDeviceContextGetDeviceType(dctx, &device_type));
138: switch (device_type) {
139: #if PetscDefined(HAVE_CUDA)
140: case PETSC_DEVICE_CUDA:
141: PetscCall(UpperTriangular<DeviceType::CUDA>::SolveInPlaceCyclic(dctx, hermitian_transpose, m, oldest, next, A, lda, x, stride));
142: break;
143: #endif
144: #if PetscDefined(HAVE_HIP)
145: case PETSC_DEVICE_HIP:
146: PetscCall(UpperTriangular<DeviceType::HIP>::SolveInPlaceCyclic(dctx, hermitian_transpose, m, oldest, next, A, lda, x, stride));
147: break;
148: #endif
149: default:
150: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Unsupported device type %s", PetscDeviceTypes[device_type]);
151: }
152: PetscFunctionReturn(PETSC_SUCCESS);
153: }