Line data Source code
1 : !{\src2tex{textfont=tt}}
2 : !!****m* ABINIT/m_abi_gpu_linalg
3 : !! NAME
4 : !! m_abi_gpu_linalg
5 : !!
6 : !! FUNCTION
7 : !! Interfaces of GPU subroutines wrapper
8 : !!
9 : !! COPYRIGHT
10 : !! Copyright (C) 2011-2026 ABINIT group (FDahm)
11 : !! This file is distributed under the terms of the
12 : !! GNU General Public License, see ~abinit/COPYING
13 : !! or http://www.gnu.org/copyleft/gpl.txt .
14 : !!
15 : !! NOTES
16 : !! This is an include file.
17 : !!
18 : !! SOURCE
19 :
20 : !!***
21 :
22 : #ifndef HAVE_GPU
23 :
24 : !!****f* m_abi_gpu_linalg/gpu_linalg_init
25 : !! NAME
26 : !! gpu_linalg_init
27 : !!
28 : !! FUNCTION
29 : !! initialisation of linalg environnement on GPU
30 : !!
31 : !! INPUTS
32 : !!
33 : !! OUTPUT
34 : !!
35 : !! SIDE EFFECTS
36 : !! WARNING! : this routine is a dummy one when HAVE_GPU is not enabled
37 : !! the correct one is in 17_gpu_toolbox/gpu_linalg.cu
38 : !!
39 : !! SOURCE
40 :
41 0 : subroutine gpu_linalg_init()
42 :
43 :
44 0 : end subroutine gpu_linalg_init
45 : !!***
46 :
47 : !!****f* m_abi_gpu_linalg/gpu_linalg_shutdown
48 : !! NAME
49 : !! gpu_linalg_shutdown
50 : !!
51 : !! FUNCTION
52 : !! close linalg environnement on GPU
53 : !!
54 : !! INPUTS
55 : !!
56 : !! OUTPUT
57 : !!
58 : !! SIDE EFFECTS
59 : !! WARNING! : this routine is a dummy one when HAVE_GPU is not enabled
60 : !! the correct one is in 17_gpu_toolbox/gpu_linalg.cu
61 : !!
62 : !! SOURCE
63 0 : subroutine gpu_linalg_shutdown()
64 :
65 0 : end subroutine gpu_linalg_shutdown
66 : !!***
67 :
68 : !!****f* m_abi_gpu_linalg/gpu_xgemm
69 : !! NAME
70 : !! gpu_xgemm
71 : !!
72 : !! FUNCTION
73 : !! Compute a scalar-matrix-matrix product and return a scalar-matrix product on GPU
74 : !! c = alpha * op(a) * op(b) + beta * c
75 : !!
76 : !! INPUTS
77 : !! cplx = 1 if real 2 if complex
78 : !! transa= from of op(a) to be used in the matrix multiplication
79 : !! transb= from of op(b) to be used in the matrix multiplication
80 : !! m = number of rows of the matrix op(a) and of the matrix c
81 : !! n = number of rows of the matrix op(b) and the number of columns of the matrix c
82 : !! k = number of columns of the matrix op(a) and the number of rows of the matrix op(b)
83 : !! alpha = alpha scalar coefficient for matrix op(a)
84 : !! a_gpu = pointer to gpu memory location of matrix a
85 : !! lda = first dimension of a
86 : !! b_gpu = pointer to gpu memory location of matrix b
87 : !! ldb = first dimension of b
88 : !! beta = beta scalar coefficient for matrix c
89 : !! c_gpu = pointer to gpu memory location of matrix c
90 : !! ldc = first dimension of c
91 : !!
92 : !! OUTPUT
93 : !! c = c matrix
94 : !!
95 : !! SIDE EFFECTS
96 : !! WARNING! : this routine is a dummy one when HAVE_GPU is not enabled
97 : !! the correct one is in 17_gpu_toolbox/gpu_linalg.cu
98 : !!
99 : !! SOURCE
100 :
101 0 : subroutine gpu_xgemm(cplx,transa,transb,m,n,k,alpha,a_gpu,lda,b_gpu,ldb,beta,c_gpu,ldc)
102 :
103 : !Arguments ------------------------------------
104 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
105 : complex(dp),intent(in) :: alpha,beta
106 : character(len=1),intent(in) :: transa,transb
107 : type(c_ptr),intent(in) :: a_gpu,b_gpu
108 : type(c_ptr),intent(inout) :: c_gpu
109 : !Local variables ------------------------------
110 : type(c_ptr) :: cptr
111 : ! *********************************************************************
112 :
113 : if (.false.) then
114 : cptr=a_gpu;cptr=b_gpu;cptr=c_gpu
115 : write(std_out,*) transa,transb,cplx,lda,ldb,ldc,m,n,k,alpha,beta
116 : end if
117 :
118 0 : end subroutine gpu_xgemm
119 : !!***
120 :
121 : !!****f* m_abi_gpu_linalg/gpu_xtrsm
122 : !! NAME
123 : !! gpu_xtrsm
124 : !!
125 : !! FUNCTION
126 : !! Solves a matrix equation (one matrix operand is triangular) on GPU.
127 : !! The xtrsm routines solve one of the following matrix equations
128 : !! op(a)*x = alpha*b
129 : !! or
130 : !! x*op(a) = alpha*b,
131 : !!
132 : !! INPUTS
133 : !! cplx= 1 if real 2 if complex
134 : !! side= Specifies whether op(a) appears on the left or right of x for
135 : !! the operation to be performed as follows:
136 : !! L or l op(a)*x = alpha*b
137 : !! R or r x*op(a) = alpha*b
138 : !! uplo= Specifies whether the matrix a is an upper or lower triangular
139 : !! matrix as follows:
140 : !! U or u Matrix a is an upper triangular matrix.
141 : !! L or l Matrix a is a lower triangular matrix
142 : !! transa= Specifies the form of op(a) to be used in the matrix
143 : !! multiplication as follows:
144 : !! N or n op(a) = a
145 : !! T or t op(a) = a'
146 : !! C or c op(a) = conjg(a')
147 : !! diag= Specifies whether or not a is unit triangular as follows:
148 : !! U or u Matrix a is assumed to be unit triangular.
149 : !! N or n Matrix a is not assumed to be unit triangular.
150 : !! m= Specifies the number of rows of b. The value of m must be at least zero
151 : !! n= Specifies the number of columns of b. The value of n must be at least zero
152 : !! alpha= Specifies the scalar alpha. When alpha is zero, then a is not referenced and b
153 : !! need not be set before entry.
154 : !! a_gpu = pointer to gpu memory location of array a, DIMENSION (lda, k), where k is m when side = 'L' or 'l' and is n
155 : !! when side = 'R' or 'r'.
156 : !! lda= Specifies the first dimension of a as declared in the calling
157 : !! (sub)program. When side = 'L' or 'l', then lda must be at least max(1,
158 : !! m), when side = 'R' or 'r', then lda must be at least max(1, n).
159 : !! b_gpu = pointer to gpu memory location of b Array, DIMENSION (ldb,n). Before entry, the leading m-by-n part of the array
160 : !! b must contain the right-hand side matrix b.
161 : !! ldb= Specifies the first dimension of b as declared in the calling
162 : !! (sub)program. The value of ldb must be at least max(1, m).
163 : !!
164 : !! OUTPUT
165 : !! b_gpu
166 : !!
167 : !! SIDE EFFECTS
168 : !! WARNING! : this routine is a dummy one when HAVE_GPU is not enabled
169 : !! the correct one is in 17_gpu_toolbox/gpu_linalg.cu
170 : !!
171 : !! SOURCE
172 :
173 0 : subroutine gpu_xtrsm(cplx,side,uplo,transa,diag,m,n,alpha,a_gpu,lda,b_gpu,ldb)
174 :
175 : ! !Arguments ------------------------------------
176 : integer, intent(in) :: cplx,lda,ldb,m,n
177 : complex(dp), intent(in) :: alpha
178 : character(len=1), intent(in) :: side,uplo,transa,diag
179 : type(c_ptr),intent(in) :: a_gpu
180 : type(c_ptr),intent(inout) :: b_gpu
181 : !Local variables ------------------------------
182 : type(c_ptr) :: cptr
183 : ! *********************************************************************
184 :
185 : if (.false.) then
186 : cptr=a_gpu;cptr=b_gpu
187 : write(std_out,*) side,uplo,transa,diag,cplx,lda,ldb,m,n,alpha
188 : end if
189 :
190 0 : end subroutine gpu_xtrsm
191 : !!***
192 :
193 : !!****f* m_abi_gpu_linalg/gpu_xaxpy
194 : !! NAME
195 : !! gpu_xaxpy
196 : !!
197 : !! FUNCTION
198 : !! Compute a BLAS-1 AXPY operation on GPU
199 : !! y = alpha * x + y
200 : !!
201 : !! INPUTS
202 : !! cplx = 1 if real 2 if complex
203 : !! size = vector size
204 : !! alpha = scalar complex value
205 : !! x_gpu = pointer to gpu memory location of array x
206 : !! incrx = stride between consecutive elements of x
207 : !! y_gpu = pointer to gpu memory location of array y
208 : !! incry = stride between consecutive elements of y
209 : !!
210 : !! SOURCE
211 0 : subroutine gpu_xaxpy(cplx, size, alpha, x_gpu, incrx, y_gpu, incry)
212 :
213 : ! !Arguments ------------------------------------
214 : integer, intent(in) :: cplx
215 : integer, intent(in) :: size
216 : complex(dp), intent(in) :: alpha
217 : type(c_ptr), intent(in) :: x_gpu
218 : integer, intent(in) :: incrx
219 : type(c_ptr), intent(inout) :: y_gpu
220 : integer, intent(in) :: incry
221 :
222 : ABI_UNUSED((/cplx,size,incrx,incry/))
223 : ABI_UNUSED(alpha)
224 0 : ABI_UNUSED_A(x_gpu)
225 0 : ABI_UNUSED_A(y_gpu)
226 0 : end subroutine gpu_xaxpy
227 : !!***
228 :
229 : !!****f* m_abi_gpu_linalg/gpu_xcopy
230 : !! NAME
231 : !! gpu_xcopy
232 : !!
233 : !! FUNCTION
234 : !! Compute a BLAS-1 COPY operation on GPU
235 : !! y = x (copy x into y)
236 : !!
237 : !! INPUTS
238 : !! cplx = 1 if real 2 if complex
239 : !! size = input vector size
240 : !! x_gpu = pointer to gpu memory location of array x
241 : !! incrx = stride between consecutive elements of x
242 : !! y_gpu = pointer to gpu memory location of array y
243 : !! incry = stride between consecutive elements of y
244 : !!
245 : !! SOURCE
246 0 : subroutine gpu_xcopy(cplx, size, x_gpu, incrx, y_gpu, incry)
247 :
248 : ! !Arguments ------------------------------------
249 : integer, intent(in) :: cplx
250 : integer, intent(in) :: size
251 : type(c_ptr), intent(in) :: x_gpu
252 : integer, intent(in) :: incrx
253 : type(c_ptr), intent(inout) :: y_gpu
254 : integer, intent(in) :: incry
255 :
256 : ABI_UNUSED((/cplx,size,incrx,incry/))
257 0 : ABI_UNUSED_A(x_gpu)
258 0 : ABI_UNUSED_A(y_gpu)
259 0 : end subroutine gpu_xcopy
260 : !!***
261 :
262 : !!****f* m_abi_gpu_linalg/gpu_xscal
263 : !! NAME
264 : !! gpu_xscal
265 : !!
266 : !! FUNCTION
267 : !! Compute a BLAS-1 SCAL operation on GPU
268 : !! x = alpha * x
269 : !!
270 : !! INPUTS
271 : !! cplx = 1 if real 2 if complex
272 : !! size = vector size
273 : !! alpha = scalar complex value
274 : !! x_gpu = pointer to gpu memory location of array x
275 : !! incrx = stride between consecutive elements of x
276 : !!
277 : !! SOURCE
278 0 : subroutine gpu_xscal(cplx, size, alpha, x_gpu, incrx)
279 :
280 : ! !Arguments ------------------------------------
281 : integer, intent(in) :: cplx
282 : integer, intent(in) :: size
283 : complex(dp), intent(in) :: alpha
284 : type(c_ptr), intent(in) :: x_gpu
285 : integer, intent(in) :: incrx
286 :
287 : ABI_UNUSED((/cplx,size,incrx/))
288 : ABI_UNUSED(alpha)
289 0 : ABI_UNUSED_A(x_gpu)
290 0 : end subroutine gpu_xscal
291 : !!***
292 :
293 : !!****f* m_abi_gpu_linalg/gpu_xdot
294 : !! NAME
295 : !! gpu_xdot
296 : !!
297 : !! FUNCTION
298 : !! Compute blas-3 DOT on GPU
299 : !! trace(X^H*Y)
300 : !!
301 : !! INPUTS
302 : !! cplx = 1 if real 2 if complex
303 : !! N = number of elements n*s
304 : !! X = array (n,s)
305 : !! incrx = stride for X
306 : !! Y = array (n,s)
307 : !! incry = stride for Y
308 : !! alpha = output pointer
309 : !!
310 : !! SOURCE
311 0 : subroutine gpu_xdot(cplx, size, alpha, x_gpu, incrx, y_gpu, incry)
312 :
313 : ! !Arguments ------------------------------------
314 : integer, intent(in) :: cplx
315 : integer, intent(in) :: size
316 : complex(dp), intent(in) :: alpha
317 : type(c_ptr), intent(in) :: x_gpu
318 : integer, intent(in) :: incrx
319 : type(c_ptr), intent(inout) :: y_gpu
320 : integer, intent(in) :: incry
321 :
322 : ABI_UNUSED((/cplx,size,incrx,incry/))
323 : ABI_UNUSED(alpha)
324 0 : ABI_UNUSED_A(x_gpu)
325 0 : ABI_UNUSED_A(y_gpu)
326 0 : end subroutine gpu_xdot
327 : !!***
328 :
329 : !!****f* m_abi_gpu_linalg/gpu_xsygvd
330 : !! NAME
331 : !! gpu_xsygvd
332 : !!
333 : !! FUNCTION
334 : !! Compute a LAPACK SYGVD operation on GPU
335 : !! compute eigen values/vectors of a real generalized
336 : !! symmetric-definite eigenproblem
337 : !!
338 : !! See cusolver documentation
339 : !! https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-sygvd
340 : !!
341 : !! See also LAPACK doc in reference implementation:
342 : !! https://github.com/Reference-LAPACK/lapack/blob/master/SRC/dsygvd.f
343 : !!
344 : !! INPUTS
345 : !! cplx = 1 if real 2 if complex
346 : !! itype = integer, type of problem
347 : !! jobz = character, 'n'(eigenvalues only) or 'v' (eigenvalues + eigenvectors)
348 : !! uplo = character, 'u' or 'l'
349 : !! A_nrows = matrix size
350 : !! A_ptr = pointer to gpu memory location of matrix A
351 : !! lda = leading dimension of matrix A
352 : !! B_ptr = pointer to gpu memory location of matrix B
353 : !! ldb = leading dimension of matrix B
354 : !! W_ptr = pointer to gpu memory location of matrix W (output eigen values)
355 : !! work_ptr =
356 : !! lwork =
357 : !! devInfo =
358 : !!
359 : !! SOURCE
360 0 : subroutine gpu_xsygvd(cplx, itype, jobz, uplo, A_nrows, &
361 : & A_ptr, lda, &
362 : & B_ptr, ldb, &
363 : & W_ptr, &
364 : & work_ptr, lwork, &
365 : & devInfo)
366 :
367 : ! Arguments ------------------------------------
368 : integer, intent(in ) :: cplx
369 : integer, intent(in ) :: itype
370 : character(len=1),intent(in ) :: jobz
371 : character(len=1),intent(in ) :: uplo
372 : integer, intent(in ) :: A_nrows
373 : type(c_ptr), intent(in ) :: A_ptr
374 : integer, intent(in ) :: lda
375 : type(c_ptr), intent(in ) :: B_ptr
376 : integer, intent(in ) :: ldb
377 : type(c_ptr), intent(inout) :: W_ptr
378 : type(c_ptr), intent(inout) :: work_ptr
379 : integer, intent(in ) :: lwork
380 : integer, intent(inout) :: devInfo
381 :
382 : ABI_UNUSED((/cplx,itype,A_nrows,lda,ldb,lwork,devInfo/))
383 : ABI_UNUSED((/jobz,uplo/))
384 : ABI_UNUSED((/A_ptr,B_ptr,W_ptr,work_ptr/))
385 0 : end subroutine gpu_xsygvd
386 : !!***
387 :
388 : !!****f* m_abi_gpu_linalg/gpu_xsygvd_bufferSize
389 : !! NAME
390 : !! gpu_xsygvd_bufferSize
391 : !!
392 : !! FUNCTION
393 : !! Compute required size for auxiliary work buffer used internally by cusolver
394 : !! in cusolverDnDsygvd / cusolverDnZhegvd
395 : !!
396 : !! See cusolver documentation
397 : !! https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-sygvd
398 : !!
399 : !! INPUTS
400 : !! cplx = 1 if real 2 if complex
401 : !! itype = integer, type of problem
402 : !! jobz = character, 'n'(eigenvalues only) or 'v' (eigenvalues + eigenvectors)
403 : !! uplo = character, 'u' or 'l'
404 : !! A_nrows = matrix size
405 : !! A_ptr = pointer to gpu memory location of matrix A
406 : !! lda = leading dimension of matrix A
407 : !! B_ptr = pointer to gpu memory location of matrix B
408 : !! ldb = leading dimension of matrix B
409 : !! W_ptr = pointer to gpu memory location of matrix W (output eigen values)
410 : !! work_ptr =
411 : !! lwork =
412 : !! devInfo =
413 : !!
414 : !! SOURCE
415 0 : subroutine gpu_xsygvd_buffersize(cplx, itype, jobz, uplo, A_nrows, &
416 : & A_ptr, lda, &
417 : & B_ptr, ldb, &
418 : & W_ptr, &
419 : & lwork)
420 :
421 : ! Arguments ------------------------------------
422 : integer, intent(in ) :: cplx
423 : integer, intent(in ) :: itype
424 : character(len=1),intent(in ) :: jobz
425 : character(len=1),intent(in ) :: uplo
426 : integer, intent(in ) :: A_nrows
427 : type(c_ptr), intent(in ) :: A_ptr
428 : integer, intent(in ) :: lda
429 : type(c_ptr), intent(in ) :: B_ptr
430 : integer, intent(in ) :: ldb
431 : type(c_ptr), intent(inout) :: W_ptr
432 : integer, intent(in ) :: lwork
433 :
434 : ABI_UNUSED((/cplx,itype,A_nrows,lda,ldb,lwork/))
435 : ABI_UNUSED((/jobz,uplo/))
436 : ABI_UNUSED((/A_ptr,B_ptr,W_ptr/))
437 0 : end subroutine gpu_xsygvd_bufferSize
438 : !!***
439 : #endif
440 :
441 : !!***
442 :
443 : !!****f* m_abi_gpu_linalg/abi_gpu_xgemm
444 : !! NAME
445 : !! abi_gpu_xgemm
446 : !!
447 : !! FUNCTION
448 : !! Compute a scalar-matrix-matrix product and return a scalar-matrix product on GPU
449 : !! c = alpha * op(a) * op(b) + beta * c
450 : !!
451 : !! INPUTS
452 : !! cplx = 1 if real 2 if complex
453 : !! transa= from of op(a) to be used in the matrix multiplication
454 : !! transb= from of op(b) to be used in the matrix multiplication
455 : !! m = number of rows of the matrix op(a) and of the matrix c
456 : !! n = number of rows of the matrix op(b) and the number of columns of the matrix c
457 : !! k = number of columns of the matrix op(a) and the number of rows of the matrix op(b)
458 : !! alpha = alpha scalar coefficient for matrix op(a)
459 : !! a = pointer to gpu memory location of matrix a
460 : !! lda = first dimension of a
461 : !! b = pointer to gpu memory location of matrix b
462 : !! ldb = first dimension of b
463 : !! beta = beta scalar coefficient for matrix c
464 : !! c = pointer to gpu memory location of matrix c
465 : !! ldc = first dimension of c
466 : !!
467 : !! OUTPUT
468 : !! c = c matrix
469 : !!
470 : !! SOURCE
471 :
472 0 : subroutine abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc)
473 :
474 : !Arguments ------------------------------------
475 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
476 : complex(dp),intent(in) :: alpha,beta
477 : character(len=1),intent(in) :: transa,transb
478 : type(c_ptr),intent(in) :: a,b
479 : type(c_ptr),intent(in) :: c
480 : ! *********************************************************************
481 :
482 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
483 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
484 : end if
485 :
486 : #ifdef HAVE_GPU
487 : call gpu_xgemm(cplx,transa,transb,m,n,k,alpha,&
488 : a,lda,b,ldb,beta,c,ldc)
489 :
490 : if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
491 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
492 : ! Therefore, we issue a stream sync here to avoid
493 : !potential mistakes in calling context.
494 : call gpu_linalg_stream_synchronize()
495 : end if
496 :
497 : #else
498 : ! Unused if GPU code disabled
499 : ABI_UNUSED((/cplx,lda,ldb,ldc,m,n,k/))
500 : ABI_UNUSED((/alpha,beta/))
501 : ABI_UNUSED((/transa,transb/))
502 : ABI_UNUSED((/a,b,c/))
503 : #endif
504 :
505 0 : end subroutine abi_gpu_xgemm_cptr
506 : !!***
507 :
508 0 : subroutine abi_gpu_xgemm_d(cplx,transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc)
509 :
510 : !Arguments ------------------------------------
511 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
512 : complex(dp),intent(in) :: alpha,beta
513 : character(len=1),intent(in) :: transa,transb
514 : real(dp), intent(in),target :: a(*),b(*)
515 : real(dp), intent(inout),target :: c(*)
516 : ! *********************************************************************
517 :
518 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
519 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
520 : end if
521 :
522 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
523 : call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
524 : c_loc(a),lda,&
525 : c_loc(b),ldb,&
526 : beta,&
527 0 : c_loc(c),ldc)
528 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
529 : #ifdef HAVE_OPENMP_OFFLOAD
530 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
531 : call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
532 : c_loc(a),lda,&
533 : c_loc(b),ldb,&
534 : beta,&
535 : c_loc(c),ldc)
536 : !$OMP END TARGET DATA
537 : #endif
538 : else
539 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
540 : end if
541 :
542 0 : end subroutine abi_gpu_xgemm_d
543 : !!***
544 :
545 0 : subroutine abi_gpu_xgemm_z(cplx,transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc)
546 :
547 : !Arguments ------------------------------------
548 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
549 : complex(dp),intent(in) :: alpha,beta
550 : character(len=1),intent(in) :: transa,transb
551 : complex(dp),intent(in),target :: a(*),b(*)
552 : complex(dp),intent(inout),target :: c(*)
553 : ! *********************************************************************
554 :
555 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
556 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
557 : end if
558 :
559 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
560 : call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
561 : c_loc(a),lda,&
562 : c_loc(b),ldb,&
563 : beta,&
564 0 : c_loc(c),ldc)
565 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
566 : #ifdef HAVE_OPENMP_OFFLOAD
567 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
568 : call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
569 : c_loc(a),lda,&
570 : c_loc(b),ldb,&
571 : beta,&
572 : c_loc(c),ldc)
573 : !$OMP END TARGET DATA
574 : #endif
575 : else
576 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
577 : end if
578 :
579 0 : end subroutine abi_gpu_xgemm_z
580 : !!***
581 :
582 0 : subroutine abi_gpu_xgemm_2d(cplx,transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc)
583 :
584 : !Arguments ------------------------------------
585 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
586 : complex(dp),intent(in) :: alpha,beta
587 : character(len=1),intent(in) :: transa,transb
588 : real(dp), intent(in),target :: a(lda,*),b(ldb,*)
589 : real(dp), intent(inout),target :: c(ldc,*)
590 : ! *********************************************************************
591 :
592 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
593 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
594 : end if
595 :
596 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
597 : call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
598 : c_loc(a),lda,&
599 : c_loc(b),ldb,&
600 : beta,&
601 0 : c_loc(c),ldc)
602 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
603 : #ifdef HAVE_OPENMP_OFFLOAD
604 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
605 : call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
606 : c_loc(a),lda,&
607 : c_loc(b),ldb,&
608 : beta,&
609 : c_loc(c),ldc)
610 : !$OMP END TARGET DATA
611 : #endif
612 : else
613 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
614 : end if
615 :
616 0 : end subroutine abi_gpu_xgemm_2d
617 : !!***
618 :
619 0 : subroutine abi_gpu_xgemm_2z(cplx,transa,transb,m,n,k,alpha,a,lda,b,ldb,beta,c,ldc)
620 :
621 : !Arguments ------------------------------------
622 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
623 : complex(dp),intent(in) :: alpha,beta
624 : character(len=1),intent(in) :: transa,transb
625 : complex(dp),intent(in),target :: a(lda,*),b(ldb,*)
626 : complex(dp),intent(inout),target :: c(ldc,*)
627 : ! *********************************************************************
628 :
629 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
630 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
631 : end if
632 :
633 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
634 : call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
635 : c_loc(a),lda,&
636 : c_loc(b),ldb,&
637 : beta,&
638 0 : c_loc(c),ldc)
639 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
640 : #ifdef HAVE_OPENMP_OFFLOAD
641 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
642 : call abi_gpu_xgemm_cptr(cplx,transa,transb,m,n,k,alpha,&
643 : c_loc(a),lda,&
644 : c_loc(b),ldb,&
645 : beta,&
646 : c_loc(c),ldc)
647 : !$OMP END TARGET DATA
648 : #endif
649 : else
650 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
651 : end if
652 :
653 0 : end subroutine abi_gpu_xgemm_2z
654 : !!***
655 :
656 : !------------------------------------------------------------------------------
657 :
658 : !!****f* m_abi_gpu_linalg/abi_gpu_xgemm_strided
659 : !! NAME
660 : !! abi_gpu_xgemm_strided
661 : !!
662 : !! FUNCTION
663 : !! Compute a batched scalar-matrix-matrix product and return a scalar-matrix product on GPU.
664 : !! Meant to be used on non-contiguous matrixes with data is uniformly split in the same number of batches in each matrix.
665 : !! c = alpha * op(a) * op(b) + beta * c
666 : !!
667 : !! INPUTS
668 : !! cplx = 1 if real 2 if complex
669 : !! transa = from of op(a) to be used in the matrix multiplication
670 : !! transb = from of op(b) to be used in the matrix multiplication
671 : !! m = number of rows of the matrix op(a) and of the matrix c
672 : !! n = number of rows of the matrix op(b) and the number of columns of the matrix c
673 : !! k = number of columns of the matrix op(a) and the number of rows of the matrix op(b)
674 : !! alpha = alpha scalar coefficient for matrix op(a)
675 : !! a = pointer to gpu memory location of matrix a
676 : !! lda = first dimension of a
677 : !! strideC = stride between each batch in matrix a
678 : !! b = pointer to gpu memory location of matrix b
679 : !! ldb = first dimension of b
680 : !! strideC = stride between each batch in matrix b
681 : !! beta = beta scalar coefficient for matrix c
682 : !! c = pointer to gpu memory location of matrix c
683 : !! ldc = first dimension of c
684 : !! strideC = stride between each batch in matrix c
685 : !! batchCount = number of batches in any matrix
686 : !!
687 : !! OUTPUT
688 : !! c = c matrix
689 : !!
690 : !! SOURCE
691 :
692 0 : subroutine abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
693 : a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount,async,stream_id)
694 :
695 : !Arguments ------------------------------------
696 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
697 : integer,intent(in) :: strideA,strideB,strideC,batchCount
698 : logical,intent(in),optional :: async
699 : integer,intent(in),optional :: stream_id
700 : complex(dp),intent(in) :: alpha,beta
701 : character(len=1),intent(in) :: transa,transb
702 : type(c_ptr),intent(in) :: a,b
703 : type(c_ptr),intent(in) :: c
704 : !Locals ---------------------------------------
705 : logical :: async_
706 : integer :: stream_id_
707 : ! *********************************************************************
708 :
709 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
710 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
711 : end if
712 : async_=.false.
713 0 : if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) async_=.false.
714 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
715 : ! Therefore, we issue a stream sync here to avoid
716 : ! potential mistakes in calling context.
717 : if(present(async)) async_=async
718 0 : stream_id_=-1;
719 : if(present(stream_id)) then
720 : stream_id_=modulo(stream_id,32);
721 : async_=.true.
722 : end if
723 :
724 : #ifdef HAVE_GPU
725 : call gpu_xgemm_strided_batched(cplx,transa,transb,m,n,k,alpha,&
726 : a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount,stream_id_)
727 :
728 : if (.not. async_) then
729 : call gpu_linalg_stream_synchronize()
730 : end if
731 :
732 : #else
733 : ! Unused if GPU code disabled
734 : ABI_UNUSED((/cplx,lda,ldb,ldc,m,n,k/))
735 : ABI_UNUSED((/strideA,strideB,strideC,batchCount/))
736 : ABI_UNUSED((/alpha,beta/))
737 : ABI_UNUSED((/transa,transb/))
738 : ABI_UNUSED((/a,b,c/))
739 : #endif
740 :
741 0 : end subroutine abi_gpu_xgemm_strided_cptr
742 : !!***
743 :
744 0 : subroutine abi_gpu_xgemm_strided_d(cplx,transa,transb,m,n,k,alpha,a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount)
745 :
746 : !Arguments ------------------------------------
747 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
748 : integer,intent(in) :: strideA,strideB,strideC,batchCount
749 : complex(dp),intent(in) :: alpha,beta
750 : character(len=1),intent(in) :: transa,transb
751 : real(dp), intent(in),target :: a(*),b(*)
752 : real(dp), intent(inout),target :: c(*)
753 : ! *********************************************************************
754 :
755 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
756 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
757 : end if
758 :
759 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
760 : call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
761 : c_loc(a),lda,strideA,&
762 : c_loc(b),ldb,strideB,&
763 : beta,&
764 0 : c_loc(c),ldc,strideC,batchCount)
765 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
766 : #ifdef HAVE_OPENMP_OFFLOAD
767 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
768 : call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
769 : c_loc(a),lda,strideA,&
770 : c_loc(b),ldb,strideB,&
771 : beta,&
772 : c_loc(c),ldc,strideC,batchCount)
773 : !$OMP END TARGET DATA
774 : #endif
775 : else
776 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
777 : end if
778 :
779 0 : end subroutine abi_gpu_xgemm_strided_d
780 : !!***
781 :
782 0 : subroutine abi_gpu_xgemm_strided_z(cplx,transa,transb,m,n,k,alpha,a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount)
783 :
784 : !Arguments ------------------------------------
785 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
786 : integer,intent(in) :: strideA,strideB,strideC,batchCount
787 : complex(dp),intent(in) :: alpha,beta
788 : character(len=1),intent(in) :: transa,transb
789 : complex(dp),intent(in),target :: a(*),b(*)
790 : complex(dp),intent(inout),target :: c(*)
791 : ! *********************************************************************
792 :
793 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
794 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
795 : end if
796 :
797 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
798 : call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
799 : c_loc(a),lda,strideA,&
800 : c_loc(b),ldb,strideB,&
801 : beta,&
802 0 : c_loc(c),ldc,strideC,batchCount)
803 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
804 : #ifdef HAVE_OPENMP_OFFLOAD
805 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
806 : call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
807 : c_loc(a),lda,strideA,&
808 : c_loc(b),ldb,strideB,&
809 : beta,&
810 : c_loc(c),ldc,strideC,batchCount)
811 : !$OMP END TARGET DATA
812 : #endif
813 : else
814 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
815 : end if
816 :
817 0 : end subroutine abi_gpu_xgemm_strided_z
818 : !!***
819 :
820 0 : subroutine abi_gpu_xgemm_strided_2d(cplx,transa,transb,m,n,k,alpha,a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount)
821 :
822 : !Arguments ------------------------------------
823 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
824 : integer,intent(in) :: strideA,strideB,strideC,batchCount
825 : complex(dp),intent(in) :: alpha,beta
826 : character(len=1),intent(in) :: transa,transb
827 : real(dp), intent(in),target :: a(lda,*),b(ldb,*)
828 : real(dp), intent(inout),target :: c(ldc,*)
829 : ! *********************************************************************
830 :
831 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
832 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
833 : end if
834 :
835 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
836 : call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
837 : c_loc(a),lda,strideA,&
838 : c_loc(b),ldb,strideB,&
839 : beta,&
840 0 : c_loc(c),ldc,strideC,batchCount)
841 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
842 : #ifdef HAVE_OPENMP_OFFLOAD
843 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
844 : call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
845 : c_loc(a),lda,strideA,&
846 : c_loc(b),ldb,strideB,&
847 : beta,&
848 : c_loc(c),ldc,strideC,batchCount)
849 : !$OMP END TARGET DATA
850 : #endif
851 : else
852 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
853 : end if
854 :
855 0 : end subroutine abi_gpu_xgemm_strided_2d
856 : !!***
857 :
858 0 : subroutine abi_gpu_xgemm_strided_2z(cplx,transa,transb,m,n,k,alpha,a,lda,strideA,b,ldb,strideB,beta,c,ldc,strideC,batchCount)
859 :
860 : !Arguments ------------------------------------
861 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n,k
862 : integer,intent(in) :: strideA,strideB,strideC,batchCount
863 : complex(dp),intent(in) :: alpha,beta
864 : character(len=1),intent(in) :: transa,transb
865 : complex(dp),intent(in),target :: a(lda,*),b(ldb,*)
866 : complex(dp),intent(inout),target :: c(ldc,*)
867 : ! *********************************************************************
868 :
869 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
870 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
871 : end if
872 :
873 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
874 : call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
875 : c_loc(a),lda,strideA,&
876 : c_loc(b),ldb,strideB,&
877 : beta,&
878 0 : c_loc(c),ldc,strideC,batchCount)
879 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
880 : #ifdef HAVE_OPENMP_OFFLOAD
881 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
882 : call abi_gpu_xgemm_strided_cptr(cplx,transa,transb,m,n,k,alpha,&
883 : c_loc(a),lda,strideA,&
884 : c_loc(b),ldb,strideB,&
885 : beta,&
886 : c_loc(c),ldc,strideC,batchCount)
887 : !$OMP END TARGET DATA
888 : #endif
889 : else
890 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
891 : end if
892 :
893 0 : end subroutine abi_gpu_xgemm_strided_2z
894 : !!***
895 :
896 : !------------------------------------------------------------------------------
897 : !!****f* m_abi_gpu_linalg/abi_gpu_xsymm
898 : !! NAME
899 : !! abi_gpu_xsymm
900 : !!
901 : !! FUNCTION
902 : !! Compute a symmetric scalar-matrix-matrix product and return a scalar-matrix product on GPU
903 : !! c = alpha * op(a) * op(b) + beta * c , if side == L
904 : !! c = alpha * op(b) * op(a) + beta * c , if side == R
905 : !!
906 : !! INPUTS
907 : !! cplx = 1 if real 2 if complex
908 : !! side = Specifies whether op(a) appears on the left or right of x for
909 : !! the operation to be performed as follows:
910 : !! L or l op(a)*x = alpha*b
911 : !! R or r x*op(a) = alpha*b
912 : !! uplo = Specifies whether the matrix a is an upper or lower triangular
913 : !! matrix as follows:
914 : !! U or u Matrix a is an upper triangular matrix.
915 : !! L or l Matrix a is a lower triangular matrix
916 : !! m = number of rows of the matrix op(a) and of the matrix c
917 : !! n = number of rows of the matrix op(b) and the number of columns of the matrix c
918 : !! alpha = alpha scalar coefficient for matrix op(a)
919 : !! a = pointer to gpu memory location of matrix a
920 : !! lda = first dimension of a
921 : !! b = pointer to gpu memory location of matrix b
922 : !! ldb = first dimension of b
923 : !! beta = beta scalar coefficient for matrix c
924 : !! c = pointer to gpu memory location of matrix c
925 : !! ldc = first dimension of c
926 : !!
927 : !! OUTPUT
928 : !! c = c matrix
929 : !!
930 : !! SOURCE
931 :
932 0 : subroutine abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
933 :
934 : !Arguments ------------------------------------
935 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n
936 : complex(dp),intent(in) :: alpha,beta
937 : character(len=1),intent(in) :: side,uplo
938 : type(c_ptr),intent(in) :: a,b
939 : type(c_ptr),intent(in) :: c
940 : ! *********************************************************************
941 :
942 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
943 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
944 : end if
945 :
946 : #ifdef HAVE_GPU
947 :
948 : call gpu_xsymm(cplx,side,uplo,m,n,alpha,&
949 : a,lda,b,ldb,beta,c,ldc)
950 :
951 : if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
952 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
953 : ! Therefore, we issue a stream sync here to avoid
954 : !potential mistakes in calling context.
955 : call gpu_linalg_stream_synchronize()
956 : end if
957 :
958 : #else
959 : ! Unused if GPU code disabled
960 : ABI_UNUSED((/cplx,lda,ldb,ldc,m,n/))
961 : ABI_UNUSED((/alpha,beta/))
962 : ABI_UNUSED((/side,uplo/))
963 : ABI_UNUSED((/a,b,c/))
964 : #endif
965 :
966 0 : end subroutine abi_gpu_xsymm_cptr
967 : !!***
968 :
969 0 : subroutine abi_gpu_xsymm_d(cplx,side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
970 :
971 : !Arguments ------------------------------------
972 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n
973 : complex(dp),intent(in) :: alpha,beta
974 : character(len=1),intent(in) :: side,uplo
975 : real(dp), intent(in),target :: a(*),b(*)
976 : real(dp), intent(inout),target :: c(*)
977 : ! *********************************************************************
978 :
979 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
980 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
981 : end if
982 :
983 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
984 : call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
985 : c_loc(a),lda,&
986 : c_loc(b),ldb,&
987 : beta,&
988 0 : c_loc(c),ldc)
989 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
990 : #ifdef HAVE_OPENMP_OFFLOAD
991 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
992 : call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
993 : c_loc(a),lda,&
994 : c_loc(b),ldb,&
995 : beta,&
996 : c_loc(c),ldc)
997 : !$OMP END TARGET DATA
998 : #endif
999 : else
1000 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1001 : end if
1002 :
1003 0 : end subroutine abi_gpu_xsymm_d
1004 : !!***
1005 :
1006 0 : subroutine abi_gpu_xsymm_z(cplx,side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
1007 :
1008 : !Arguments ------------------------------------
1009 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n
1010 : complex(dp),intent(in) :: alpha,beta
1011 : character(len=1),intent(in) :: side,uplo
1012 : complex(dp),intent(in),target :: a(*),b(*)
1013 : complex(dp),intent(inout),target :: c(*)
1014 : ! *********************************************************************
1015 :
1016 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1017 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1018 : end if
1019 :
1020 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1021 : call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
1022 : c_loc(a),lda,&
1023 : c_loc(b),ldb,&
1024 : beta,&
1025 0 : c_loc(c),ldc)
1026 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1027 : #ifdef HAVE_OPENMP_OFFLOAD
1028 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
1029 : call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
1030 : c_loc(a),lda,&
1031 : c_loc(b),ldb,&
1032 : beta,&
1033 : c_loc(c),ldc)
1034 : !$OMP END TARGET DATA
1035 : #endif
1036 : else
1037 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1038 : end if
1039 :
1040 0 : end subroutine abi_gpu_xsymm_z
1041 : !!***
1042 :
1043 0 : subroutine abi_gpu_xsymm_2d(cplx,side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
1044 :
1045 : !Arguments ------------------------------------
1046 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n
1047 : complex(dp),intent(in) :: alpha,beta
1048 : character(len=1),intent(in) :: side,uplo
1049 : real(dp), intent(in),target :: a(lda,*),b(ldb,*)
1050 : real(dp), intent(inout),target :: c(ldc,*)
1051 : ! *********************************************************************
1052 :
1053 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1054 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1055 : end if
1056 :
1057 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1058 : call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
1059 : c_loc(a),lda,&
1060 : c_loc(b),ldb,&
1061 : beta,&
1062 0 : c_loc(c),ldc)
1063 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1064 : #ifdef HAVE_OPENMP_OFFLOAD
1065 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
1066 : call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
1067 : c_loc(a),lda,&
1068 : c_loc(b),ldb,&
1069 : beta,&
1070 : c_loc(c),ldc)
1071 : !$OMP END TARGET DATA
1072 : #endif
1073 : else
1074 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1075 : end if
1076 :
1077 0 : end subroutine abi_gpu_xsymm_2d
1078 : !!***
1079 :
1080 0 : subroutine abi_gpu_xsymm_2z(cplx,side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
1081 :
1082 : !Arguments ------------------------------------
1083 : integer,intent(in) :: cplx,lda,ldb,ldc,m,n
1084 : complex(dp),intent(in) :: alpha,beta
1085 : character(len=1),intent(in) :: side,uplo
1086 : complex(dp),intent(in),target :: a(lda,*),b(ldb,*)
1087 : complex(dp),intent(inout),target :: c(ldc,*)
1088 : ! *********************************************************************
1089 :
1090 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1091 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1092 : end if
1093 :
1094 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1095 : call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
1096 : c_loc(a),lda,&
1097 : c_loc(b),ldb,&
1098 : beta,&
1099 0 : c_loc(c),ldc)
1100 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1101 : #ifdef HAVE_OPENMP_OFFLOAD
1102 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
1103 : call abi_gpu_xsymm_cptr(cplx,side,uplo,m,n,alpha,&
1104 : c_loc(a),lda,&
1105 : c_loc(b),ldb,&
1106 : beta,&
1107 : c_loc(c),ldc)
1108 : !$OMP END TARGET DATA
1109 : #endif
1110 : else
1111 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1112 : end if
1113 :
1114 0 : end subroutine abi_gpu_xsymm_2z
1115 : !!***
1116 :
1117 : !------------------------------------------------------------------------------
1118 : !!****f* m_abi_gpu_linalg/abi_gpu_zhemm
1119 : !! NAME
1120 : !! abi_gpu_xhemm
1121 : !!
1122 : !! FUNCTION
1123 : !! Compute a Hermitian scalar-matrix-matrix product and return a scalar-matrix product on GPU
1124 : !! c = alpha * op(a) * op(b) + beta * c , if side == L
1125 : !! c = alpha * op(b) * op(a) + beta * c , if side == R
1126 : !!
1127 : !! INPUTS
1128 : !! side = Specifies whether op(a) appears on the left or right of x for
1129 : !! the operation to be performed as follows:
1130 : !! L or l op(a)*x = alpha*b
1131 : !! R or r x*op(a) = alpha*b
1132 : !! uplo = Specifies whether the matrix a is an upper or lower triangular
1133 : !! matrix as follows:
1134 : !! U or u Matrix a is an upper triangular matrix.
1135 : !! L or l Matrix a is a lower triangular matrix
1136 : !! m = number of rows of the matrix op(a) and of the matrix c
1137 : !! n = number of rows of the matrix op(b) and the number of columns of the matrix c
1138 : !! alpha = alpha scalar coefficient for matrix op(a)
1139 : !! a_gpu = pointer to gpu memory location of matrix a
1140 : !! lda = first dimension of a
1141 : !! b_gpu = pointer to gpu memory location of matrix b
1142 : !! ldb = first dimension of b
1143 : !! beta = beta scalar coefficient for matrix c
1144 : !! c_gpu = pointer to gpu memory location of matrix c
1145 : !! ldc = first dimension of c
1146 : !!
1147 : !! OUTPUT
1148 : !! c = c matrix
1149 : !!
1150 : !! SOURCE
1151 :
1152 0 : subroutine abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
1153 :
1154 : !Arguments ------------------------------------
1155 : integer,intent(in) :: lda,ldb,ldc,m,n
1156 : complex(dp),intent(in) :: alpha,beta
1157 : character(len=1),intent(in) :: side,uplo
1158 : type(c_ptr),intent(in) :: a,b
1159 : type(c_ptr),intent(in) :: c
1160 : ! *********************************************************************
1161 :
1162 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1163 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1164 : end if
1165 :
1166 : #ifdef HAVE_GPU
1167 :
1168 : call gpu_zhemm(side,uplo,m,n,alpha,&
1169 : a,lda,b,ldb,beta,c,ldc)
1170 :
1171 : if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1172 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
1173 : ! Therefore, we issue a stream sync here to avoid
1174 : !potential mistakes in calling context.
1175 : call gpu_linalg_stream_synchronize()
1176 : end if
1177 :
1178 : #else
1179 : ! Unused if GPU code disabled
1180 : ABI_UNUSED((/lda,ldb,ldc,m,n/))
1181 : ABI_UNUSED((/alpha,beta/))
1182 : ABI_UNUSED((/side,uplo/))
1183 : ABI_UNUSED((/a,b,c/))
1184 : #endif
1185 :
1186 0 : end subroutine abi_gpu_zhemm_cptr
1187 : !!***
1188 :
1189 0 : subroutine abi_gpu_zhemm_d(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
1190 :
1191 : !Arguments ------------------------------------
1192 : integer,intent(in) :: lda,ldb,ldc,m,n
1193 : complex(dp),intent(in) :: alpha,beta
1194 : character(len=1),intent(in) :: side,uplo
1195 : real(dp),intent(in),target :: a(*),b(*)
1196 : real(dp),intent(inout),target :: c(*)
1197 : ! *********************************************************************
1198 :
1199 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1200 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1201 : end if
1202 :
1203 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1204 : call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
1205 : c_loc(a),lda,&
1206 : c_loc(b),ldb,&
1207 : beta,&
1208 0 : c_loc(c),ldc)
1209 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1210 : #ifdef HAVE_OPENMP_OFFLOAD
1211 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
1212 : call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
1213 : c_loc(a),lda,&
1214 : c_loc(b),ldb,&
1215 : beta,&
1216 : c_loc(c),ldc)
1217 : !$OMP END TARGET DATA
1218 : #endif
1219 : else
1220 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1221 : end if
1222 :
1223 0 : end subroutine abi_gpu_zhemm_d
1224 : !!***
1225 :
1226 0 : subroutine abi_gpu_zhemm_z(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
1227 :
1228 : !Arguments ------------------------------------
1229 : integer,intent(in) :: lda,ldb,ldc,m,n
1230 : complex(dp),intent(in) :: alpha,beta
1231 : character(len=1),intent(in) :: side,uplo
1232 : complex(dp),intent(in),target :: a(*),b(*)
1233 : complex(dp),intent(inout),target :: c(*)
1234 : ! *********************************************************************
1235 :
1236 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1237 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1238 : end if
1239 :
1240 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1241 : call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
1242 : c_loc(a),lda,&
1243 : c_loc(b),ldb,&
1244 : beta,&
1245 0 : c_loc(c),ldc)
1246 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1247 : #ifdef HAVE_OPENMP_OFFLOAD
1248 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
1249 : call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
1250 : c_loc(a),lda,&
1251 : c_loc(b),ldb,&
1252 : beta,&
1253 : c_loc(c),ldc)
1254 : !$OMP END TARGET DATA
1255 : #endif
1256 : else
1257 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1258 : end if
1259 :
1260 0 : end subroutine abi_gpu_zhemm_z
1261 : !!***
1262 :
1263 0 : subroutine abi_gpu_zhemm_2d(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
1264 :
1265 : !Arguments ------------------------------------
1266 : integer,intent(in) :: lda,ldb,ldc,m,n
1267 : complex(dp),intent(in) :: alpha,beta
1268 : character(len=1),intent(in) :: side,uplo
1269 : real(dp),intent(in),target :: a(lda,*),b(ldb,*)
1270 : real(dp),intent(inout),target :: c(ldc,*)
1271 : ! *********************************************************************
1272 :
1273 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1274 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1275 : end if
1276 :
1277 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1278 : call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
1279 : c_loc(a),lda,&
1280 : c_loc(b),ldb,&
1281 : beta,&
1282 0 : c_loc(c),ldc)
1283 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1284 : #ifdef HAVE_OPENMP_OFFLOAD
1285 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
1286 : call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
1287 : c_loc(a),lda,&
1288 : c_loc(b),ldb,&
1289 : beta,&
1290 : c_loc(c),ldc)
1291 : !$OMP END TARGET DATA
1292 : #endif
1293 : else
1294 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1295 : end if
1296 :
1297 0 : end subroutine abi_gpu_zhemm_2d
1298 : !!***
1299 :
1300 0 : subroutine abi_gpu_zhemm_2z(side,uplo,m,n,alpha,a,lda,b,ldb,beta,c,ldc)
1301 :
1302 : !Arguments ------------------------------------
1303 : integer,intent(in) :: lda,ldb,ldc,m,n
1304 : complex(dp),intent(in) :: alpha,beta
1305 : character(len=1),intent(in) :: side,uplo
1306 : complex(dp),intent(in),target :: a(lda,*),b(ldb,*)
1307 : complex(dp),intent(inout),target :: c(ldc,*)
1308 : ! *********************************************************************
1309 :
1310 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1311 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1312 : end if
1313 :
1314 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1315 : call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
1316 : c_loc(a),lda,&
1317 : c_loc(b),ldb,&
1318 : beta,&
1319 0 : c_loc(c),ldc)
1320 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1321 : #ifdef HAVE_OPENMP_OFFLOAD
1322 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b,c)
1323 : call abi_gpu_zhemm_cptr(side,uplo,m,n,alpha,&
1324 : c_loc(a),lda,&
1325 : c_loc(b),ldb,&
1326 : beta,&
1327 : c_loc(c),ldc)
1328 : !$OMP END TARGET DATA
1329 : #endif
1330 : else
1331 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1332 : end if
1333 :
1334 0 : end subroutine abi_gpu_zhemm_2z
1335 : !!***
1336 :
1337 : !------------------------------------------------------------------------------
1338 : !!****f* m_abi_gpu_linalg/abi_gpu_xscal
1339 : !! NAME
1340 : !! abi_gpu_xscal
1341 : !!
1342 : !! FUNCTION
1343 : !! Compute a BLAS-1 SCAL operation on GPU
1344 : !! x = alpha * x
1345 : !!
1346 : !! INPUTS
1347 : !! cplx = 1 if real 2 if complex
1348 : !! size = vector size
1349 : !! alpha = scalar complex value
1350 : !! x_gpu = pointer to gpu memory location of array x
1351 : !! incrx = stride between consecutive elements of x
1352 : !!
1353 : !! SOURCE
1354 0 : subroutine abi_gpu_xscal_cptr(cplx, size, alpha, x, incrx)
1355 :
1356 : ! !Arguments ------------------------------------
1357 : integer, intent(in) :: cplx
1358 : integer, intent(in) :: size
1359 : complex(dp), intent(in) :: alpha
1360 : type(c_ptr), intent(in) :: x
1361 : integer, intent(in) :: incrx
1362 : ! *************************************************************************
1363 :
1364 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1365 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1366 : end if
1367 :
1368 : #ifdef HAVE_GPU
1369 :
1370 : call gpu_xscal(cplx, size, alpha, x, incrx)
1371 :
1372 : if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1373 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
1374 : ! Therefore, we issue a stream sync here to avoid
1375 : !potential mistakes in calling context.
1376 : call gpu_linalg_stream_synchronize()
1377 : end if
1378 :
1379 : #else
1380 : ! Unused if GPU code disabled
1381 : ABI_UNUSED((/cplx,incrx,size/))
1382 : ABI_UNUSED((/alpha/))
1383 : ABI_UNUSED((/x/))
1384 : #endif
1385 :
1386 0 : end subroutine abi_gpu_xscal_cptr
1387 : !!***
1388 :
1389 0 : subroutine abi_gpu_xscal_d(cplx, size, alpha, x, incrx)
1390 :
1391 : ! !Arguments ------------------------------------
1392 : integer, intent(in) :: cplx
1393 : integer, intent(in) :: size
1394 : complex(dp), intent(in) :: alpha
1395 : real(dp), intent(inout), target :: x(*)
1396 : integer, intent(in) :: incrx
1397 : ! *************************************************************************
1398 :
1399 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1400 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1401 : end if
1402 :
1403 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1404 0 : call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
1405 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1406 : #ifdef HAVE_OPENMP_OFFLOAD
1407 : !$OMP TARGET DATA USE_DEVICE_ADDR(x)
1408 : call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
1409 : !$OMP END TARGET DATA
1410 : #endif
1411 : else
1412 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1413 : end if
1414 :
1415 0 : end subroutine abi_gpu_xscal_d
1416 : !!***
1417 :
1418 0 : subroutine abi_gpu_xscal_z(cplx, size, alpha, x, incrx)
1419 :
1420 : ! !Arguments ------------------------------------
1421 : integer, intent(in) :: cplx
1422 : integer, intent(in) :: size
1423 : complex(dp), intent(in) :: alpha
1424 : complex(dp), intent(inout), target :: x(*)
1425 : integer, intent(in) :: incrx
1426 : ! *************************************************************************
1427 :
1428 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1429 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1430 : end if
1431 :
1432 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1433 0 : call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
1434 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1435 : #ifdef HAVE_OPENMP_OFFLOAD
1436 : !$OMP TARGET DATA USE_DEVICE_ADDR(x)
1437 : call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
1438 : !$OMP END TARGET DATA
1439 : #endif
1440 : else
1441 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1442 : end if
1443 :
1444 0 : end subroutine abi_gpu_xscal_z
1445 : !!***
1446 :
1447 0 : subroutine abi_gpu_xscal_2d(cplx, size, alpha, x, incrx)
1448 :
1449 : ! !Arguments ------------------------------------
1450 : integer, intent(in) :: cplx
1451 : integer, intent(in) :: size
1452 : complex(dp), intent(in) :: alpha
1453 : real(dp), intent(inout), target :: x(size,*)
1454 : integer, intent(in) :: incrx
1455 : ! *************************************************************************
1456 :
1457 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1458 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1459 : end if
1460 :
1461 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1462 0 : call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
1463 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1464 : #ifdef HAVE_OPENMP_OFFLOAD
1465 : !$OMP TARGET DATA USE_DEVICE_ADDR(x)
1466 : call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
1467 : !$OMP END TARGET DATA
1468 : #endif
1469 : else
1470 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1471 : end if
1472 :
1473 0 : end subroutine abi_gpu_xscal_2d
1474 : !!***
1475 :
1476 0 : subroutine abi_gpu_xscal_2z(cplx, size, alpha, x, incrx)
1477 :
1478 : ! !Arguments ------------------------------------
1479 : integer, intent(in) :: cplx
1480 : integer, intent(in) :: size
1481 : complex(dp), intent(in) :: alpha
1482 : complex(dp), intent(inout), target :: x(size,*)
1483 : integer, intent(in) :: incrx
1484 : ! *************************************************************************
1485 :
1486 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1487 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1488 : end if
1489 :
1490 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1491 0 : call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
1492 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1493 : #ifdef HAVE_OPENMP_OFFLOAD
1494 : !$OMP TARGET DATA USE_DEVICE_ADDR(x)
1495 : call abi_gpu_xscal_cptr(cplx, size, alpha, c_loc(x), incrx)
1496 : !$OMP END TARGET DATA
1497 : #endif
1498 : else
1499 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1500 : end if
1501 :
1502 0 : end subroutine abi_gpu_xscal_2z
1503 : !!***
1504 :
1505 : !!****f* m_abi_gpu_linalg/abi_gpu_xdot
1506 : !! NAME
1507 : !! abi_gpu_xdot
1508 : !!
1509 : !! FUNCTION
1510 : !! Compute blas-3 DOT on GPU
1511 : !! trace(X^H*Y)
1512 : !!
1513 : !! INPUTS
1514 : !! cplx = 1 if real 2 if complex
1515 : !! size = vector size
1516 : !! alpha = scalar complex value
1517 : !! x_gpu = pointer to gpu memory location of array x
1518 : !! incrx = stride between consecutive elements of x
1519 : !! y_gpu = pointer to gpu memory location of array y
1520 : !! incry = stride between consecutive elements of y
1521 : !!
1522 : !! SOURCE
1523 0 : subroutine abi_gpu_xdot_cptr(cplx, size, alpha, x, incrx, y, incry)
1524 :
1525 : ! !Arguments ------------------------------------
1526 : integer, intent(in) :: cplx
1527 : integer, intent(in) :: size
1528 : complex(dp), intent(in) :: alpha
1529 : type(c_ptr), intent(in) :: x
1530 : integer, intent(in) :: incrx
1531 : type(c_ptr), intent(in) :: y
1532 : integer, intent(in) :: incry
1533 : ! *************************************************************************
1534 :
1535 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1536 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1537 : end if
1538 :
1539 : #ifdef HAVE_GPU
1540 :
1541 : call gpu_xdot(cplx, size, alpha, x, incrx, y, incry)
1542 :
1543 : if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1544 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
1545 : ! Therefore, we issue a stream sync here to avoid
1546 : !potential mistakes in calling context.
1547 : call gpu_linalg_stream_synchronize()
1548 : end if
1549 :
1550 : #else
1551 : ! Unused if GPU code disabled
1552 : ABI_UNUSED((/cplx,incrx,incry,size/))
1553 : ABI_UNUSED((/alpha/))
1554 : ABI_UNUSED((/x,y/))
1555 : #endif
1556 :
1557 0 : end subroutine abi_gpu_xdot_cptr
1558 : !!***
1559 :
1560 0 : subroutine abi_gpu_xdot_d(cplx, size, alpha, x, incrx, y, incry)
1561 :
1562 : !Arguments ------------------------------------
1563 : integer, intent(in) :: cplx
1564 : integer, intent(in) :: size
1565 : complex(dp), intent(in) :: alpha
1566 : real(dp), intent(in), target :: x(*)
1567 : integer, intent(in) :: incrx
1568 : real(dp), intent(inout), target :: y(*)
1569 : integer, intent(in) :: incry
1570 : ! *************************************************************************
1571 :
1572 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1573 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1574 : end if
1575 :
1576 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1577 0 : call abi_gpu_xdot_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1578 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1579 : #ifdef HAVE_OPENMP_OFFLOAD
1580 : !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
1581 : call abi_gpu_xdot_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1582 : !$OMP END TARGET DATA
1583 : #endif
1584 : else
1585 0 : ABI_BUG("Unhandled GPU mode !")
1586 : end if
1587 :
1588 0 : end subroutine abi_gpu_xdot_d
1589 : !!***
1590 :
1591 0 : subroutine abi_gpu_xdot_z(cplx, size, alpha, x, incrx, y, incry)
1592 :
1593 : !Arguments ------------------------------------
1594 : integer, intent(in) :: cplx
1595 : integer, intent(in) :: size
1596 : complex(dp), intent(in) :: alpha
1597 : complex(dp), intent(in), target :: x(*)
1598 : integer, intent(in) :: incrx
1599 : complex(dp), intent(inout), target :: y(*)
1600 : integer, intent(in) :: incry
1601 : ! *************************************************************************
1602 :
1603 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1604 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1605 : end if
1606 :
1607 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1608 0 : call abi_gpu_xdot_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1609 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1610 : #ifdef HAVE_OPENMP_OFFLOAD
1611 : !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
1612 : call abi_gpu_xdot_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1613 : !$OMP END TARGET DATA
1614 : #endif
1615 : else
1616 0 : ABI_BUG("Unhandled GPU mode !")
1617 : end if
1618 :
1619 0 : end subroutine abi_gpu_xdot_z
1620 : !!***
1621 :
1622 : !!****f* m_abi_gpu_linalg/abi_gpu_xaxpy
1623 : !! NAME
1624 : !! abi_gpu_xaxpy
1625 : !!
1626 : !! FUNCTION
1627 : !! Compute a BLAS-1 AXPY operation on GPU
1628 : !! y = alpha * x + y
1629 : !!
1630 : !! INPUTS
1631 : !! cplx = 1 if real 2 if complex
1632 : !! size = vector size
1633 : !! alpha = scalar complex value
1634 : !! x_gpu = pointer to gpu memory location of array x
1635 : !! incrx = stride between consecutive elements of x
1636 : !! y_gpu = pointer to gpu memory location of array y
1637 : !! incry = stride between consecutive elements of y
1638 : !!
1639 : !! SOURCE
1640 0 : subroutine abi_gpu_xaxpy_cptr(cplx, size, alpha, x, incrx, y, incry)
1641 :
1642 : ! !Arguments ------------------------------------
1643 : integer, intent(in) :: cplx
1644 : integer, intent(in) :: size
1645 : complex(dp), intent(in) :: alpha
1646 : type(c_ptr), intent(in) :: x
1647 : integer, intent(in) :: incrx
1648 : type(c_ptr), intent(in) :: y
1649 : integer, intent(in) :: incry
1650 : ! *************************************************************************
1651 :
1652 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1653 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1654 : end if
1655 :
1656 : #ifdef HAVE_GPU
1657 :
1658 : call gpu_xaxpy(cplx, size, alpha, x, incrx, y, incry)
1659 :
1660 : if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1661 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
1662 : ! Therefore, we issue a stream sync here to avoid
1663 : !potential mistakes in calling context.
1664 : call gpu_linalg_stream_synchronize()
1665 : end if
1666 :
1667 : #else
1668 : ! Unused if GPU code disabled
1669 : ABI_UNUSED((/cplx,incrx,incry,size/))
1670 : ABI_UNUSED((/alpha/))
1671 : ABI_UNUSED((/x,y/))
1672 : #endif
1673 :
1674 0 : end subroutine abi_gpu_xaxpy_cptr
1675 : !!***
1676 :
1677 0 : subroutine abi_gpu_xaxpy_d(cplx, size, alpha, x, incrx, y, incry)
1678 :
1679 : !Arguments ------------------------------------
1680 : integer, intent(in) :: cplx
1681 : integer, intent(in) :: size
1682 : complex(dp), intent(in) :: alpha
1683 : real(dp), intent(in), target :: x(*)
1684 : integer, intent(in) :: incrx
1685 : real(dp), intent(inout), target :: y(*)
1686 : integer, intent(in) :: incry
1687 : ! *************************************************************************
1688 :
1689 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1690 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1691 : end if
1692 :
1693 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1694 0 : call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1695 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1696 : #ifdef HAVE_OPENMP_OFFLOAD
1697 : !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
1698 : call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1699 : !$OMP END TARGET DATA
1700 : #endif
1701 : else
1702 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1703 : end if
1704 :
1705 0 : end subroutine abi_gpu_xaxpy_d
1706 : !!***
1707 :
1708 0 : subroutine abi_gpu_xaxpy_z(cplx, size, alpha, x, incrx, y, incry)
1709 :
1710 : !Arguments ------------------------------------
1711 : integer, intent(in) :: cplx
1712 : integer, intent(in) :: size
1713 : complex(dp), intent(in) :: alpha
1714 : complex(dp), intent(in), target :: x(*)
1715 : integer, intent(in) :: incrx
1716 : complex(dp), intent(inout), target :: y(*)
1717 : integer, intent(in) :: incry
1718 : ! *************************************************************************
1719 :
1720 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1721 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1722 : end if
1723 :
1724 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1725 0 : call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1726 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1727 : #ifdef HAVE_OPENMP_OFFLOAD
1728 : !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
1729 : call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1730 : !$OMP END TARGET DATA
1731 : #endif
1732 : else
1733 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1734 : end if
1735 :
1736 0 : end subroutine abi_gpu_xaxpy_z
1737 : !!***
1738 :
1739 0 : subroutine abi_gpu_xaxpy_2d(cplx, size, alpha, x, incrx, y, incry)
1740 :
1741 : !Arguments ------------------------------------
1742 : integer, intent(in) :: cplx
1743 : integer, intent(in) :: size
1744 : complex(dp), intent(in) :: alpha
1745 : real(dp), intent(in), target :: x(size,*)
1746 : integer, intent(in) :: incrx
1747 : real(dp), intent(inout), target :: y(size,*)
1748 : integer, intent(in) :: incry
1749 : ! *************************************************************************
1750 :
1751 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1752 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1753 : end if
1754 :
1755 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1756 0 : call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1757 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1758 : #ifdef HAVE_OPENMP_OFFLOAD
1759 : !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
1760 : call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1761 : !$OMP END TARGET DATA
1762 : #endif
1763 : else
1764 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1765 : end if
1766 :
1767 0 : end subroutine abi_gpu_xaxpy_2d
1768 : !!***
1769 :
1770 0 : subroutine abi_gpu_xaxpy_2z(cplx, size, alpha, x, incrx, y, incry)
1771 :
1772 : !Arguments ------------------------------------
1773 : integer, intent(in) :: cplx
1774 : integer, intent(in) :: size
1775 : complex(dp), intent(in) :: alpha
1776 : complex(dp), intent(in), target :: x(size,*)
1777 : integer, intent(in) :: incrx
1778 : complex(dp), intent(inout), target :: y(size,*)
1779 : integer, intent(in) :: incry
1780 : ! *************************************************************************
1781 :
1782 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1783 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1784 : end if
1785 :
1786 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1787 0 : call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1788 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1789 : #ifdef HAVE_OPENMP_OFFLOAD
1790 : !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
1791 : call abi_gpu_xaxpy_cptr(cplx, size, alpha, c_loc(x), incrx, c_loc(y), incry)
1792 : !$OMP END TARGET DATA
1793 : #endif
1794 : else
1795 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1796 : end if
1797 :
1798 0 : end subroutine abi_gpu_xaxpy_2z
1799 : !!***
1800 :
1801 : !!****f* m_abi_gpu_linalg/abi_gpu_xcopy
1802 : !! NAME
1803 : !! abi_gpu_xcopy
1804 : !!
1805 : !! FUNCTION
1806 : !! Compute a BLAS-1 COPY operation on GPU
1807 : !! y = x (copy x into y)
1808 : !!
1809 : !! INPUTS
1810 : !! cplx = 1 if real 2 if complex
1811 : !! size = input vector size
1812 : !! x = pointer to gpu memory location of array x
1813 : !! incrx = stride between consecutive elements of x
1814 : !! y = pointer to gpu memory location of array y
1815 : !! incry = stride between consecutive elements of y
1816 : !!
1817 : !! SOURCE
1818 :
1819 0 : subroutine abi_gpu_xcopy_cptr(cplx, size, x, incrx, y, incry)
1820 :
1821 : ! !Arguments ------------------------------------
1822 : integer, intent(in) :: cplx
1823 : integer, intent(in) :: size
1824 : type(c_ptr), intent(in) :: x
1825 : integer, intent(in) :: incrx
1826 : type(c_ptr), intent(in) :: y
1827 : integer, intent(in) :: incry
1828 :
1829 : ! *************************************************************************
1830 :
1831 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1832 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1833 : end if
1834 :
1835 : #ifdef HAVE_GPU
1836 :
1837 : call gpu_xcopy(cplx, size, x, incrx, y, incry)
1838 :
1839 : if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1840 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
1841 : ! Therefore, we issue a stream sync here to avoid
1842 : !potential mistakes in calling context.
1843 : call gpu_linalg_stream_synchronize()
1844 : end if
1845 :
1846 : #else
1847 : ! Unused if GPU code disabled
1848 : ABI_UNUSED((/cplx,incrx,incry,size/))
1849 : ABI_UNUSED((/x,y/))
1850 : #endif
1851 :
1852 0 : end subroutine abi_gpu_xcopy_cptr
1853 : !!***
1854 :
1855 0 : subroutine abi_gpu_xcopy_d(cplx, size, x, incrx, y, incry)
1856 :
1857 : ! !Arguments ------------------------------------
1858 : integer, intent(in) :: cplx
1859 : integer, intent(in) :: size
1860 : real(dp), intent(in),target :: x(*)
1861 : integer, intent(in) :: incrx
1862 : real(dp), intent(inout),target :: y(*)
1863 : integer, intent(in) :: incry
1864 :
1865 : ! *************************************************************************
1866 :
1867 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1868 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1869 : end if
1870 :
1871 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1872 0 : call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
1873 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1874 : #ifdef HAVE_OPENMP_OFFLOAD
1875 : !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
1876 : call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
1877 : !$OMP END TARGET DATA
1878 : #endif
1879 : else
1880 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1881 : end if
1882 :
1883 0 : end subroutine abi_gpu_xcopy_d
1884 : !!***
1885 :
1886 0 : subroutine abi_gpu_xcopy_z(cplx, size, x, incrx, y, incry)
1887 :
1888 : ! !Arguments ------------------------------------
1889 : integer, intent(in) :: cplx
1890 : integer, intent(in) :: size
1891 : complex(dp), intent(in),target :: x(*)
1892 : integer, intent(in) :: incrx
1893 : complex(dp), intent(inout),target :: y(*)
1894 : integer, intent(in) :: incry
1895 : ! *************************************************************************
1896 :
1897 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1898 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1899 : end if
1900 :
1901 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1902 0 : call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
1903 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1904 : #ifdef HAVE_OPENMP_OFFLOAD
1905 : !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
1906 : call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
1907 : !$OMP END TARGET DATA
1908 : #endif
1909 : else
1910 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1911 : end if
1912 :
1913 0 : end subroutine abi_gpu_xcopy_z
1914 : !!***
1915 :
1916 0 : subroutine abi_gpu_xcopy_2d(cplx, size, x, incrx, y, incry)
1917 :
1918 : ! !Arguments ------------------------------------
1919 : integer, intent(in) :: cplx
1920 : integer, intent(in) :: size
1921 : real(dp), intent(in),target :: x(size,*)
1922 : integer, intent(in) :: incrx
1923 : real(dp), intent(inout),target :: y(size,*)
1924 : integer, intent(in) :: incry
1925 :
1926 : ! *************************************************************************
1927 :
1928 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1929 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1930 : end if
1931 :
1932 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1933 0 : call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
1934 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1935 : #ifdef HAVE_OPENMP_OFFLOAD
1936 : !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
1937 : call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
1938 : !$OMP END TARGET DATA
1939 : #endif
1940 : else
1941 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1942 : end if
1943 :
1944 0 : end subroutine abi_gpu_xcopy_2d
1945 : !!***
1946 :
1947 0 : subroutine abi_gpu_xcopy_2z(cplx, size, x, incrx, y, incry)
1948 :
1949 : !Arguments ------------------------------------
1950 : integer, intent(in) :: cplx
1951 : integer, intent(in) :: size
1952 : complex(dp), intent(in),target :: x(size,*)
1953 : integer, intent(in) :: incrx
1954 : complex(dp), intent(inout),target :: y(size,*)
1955 : integer, intent(in) :: incry
1956 : ! *************************************************************************
1957 :
1958 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
1959 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
1960 : end if
1961 :
1962 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
1963 0 : call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
1964 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
1965 : #ifdef HAVE_OPENMP_OFFLOAD
1966 : !$OMP TARGET DATA USE_DEVICE_ADDR(x,y)
1967 : call abi_gpu_xcopy_cptr(cplx, size, c_loc(x), incrx, c_loc(y), incry)
1968 : !$OMP END TARGET DATA
1969 : #endif
1970 : else
1971 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
1972 : end if
1973 :
1974 0 : end subroutine abi_gpu_xcopy_2z
1975 : !!***
1976 :
1977 : !!****f* m_abi_gpu_linalg/abi_gpu_xtrsm
1978 : !! NAME
1979 : !! abi_gpu_xtrsm
1980 : !!
1981 : !! FUNCTION
1982 : !! Solves a matrix equation (one matrix operand is triangular) on GPU.
1983 : !! The xtrsm routines solve one of the following matrix equations
1984 : !! op(a)*x = alpha*b
1985 : !! or
1986 : !! x*op(a) = alpha*b,
1987 : !!
1988 : !! INPUTS
1989 : !! cplx= 1 if real 2 if complex
1990 : !! side= Specifies whether op(a) appears on the left or right of x for
1991 : !! the operation to be performed as follows:
1992 : !! L or l op(a)*x = alpha*b
1993 : !! R or r x*op(a) = alpha*b
1994 : !! uplo= Specifies whether the matrix a is an upper or lower triangular
1995 : !! matrix as follows:
1996 : !! U or u Matrix a is an upper triangular matrix.
1997 : !! L or l Matrix a is a lower triangular matrix
1998 : !! transa= Specifies the form of op(a) to be used in the matrix
1999 : !! multiplication as follows:
2000 : !! N or n op(a) = a
2001 : !! T or t op(a) = a'
2002 : !! C or c op(a) = conjg(a')
2003 : !! diag= Specifies whether or not a is unit triangular as follows:
2004 : !! U or u Matrix a is assumed to be unit triangular.
2005 : !! N or n Matrix a is not assumed to be unit triangular.
2006 : !! m= Specifies the number of rows of b. The value of m must be at least zero
2007 : !! n= Specifies the number of columns of b. The value of n must be at least zero
2008 : !! alpha= Specifies the scalar alpha. When alpha is zero, then a is not referenced and b
2009 : !! need not be set before entry.
2010 : !! a = pointer to gpu memory location of array a, DIMENSION (lda, k), where k is m when side = 'L' or 'l' and is n
2011 : !! when side = 'R' or 'r'.
2012 : !! lda= Specifies the first dimension of a as declared in the calling
2013 : !! (sub)program. When side = 'L' or 'l', then lda must be at least max(1,
2014 : !! m), when side = 'R' or 'r', then lda must be at least max(1, n).
2015 : !! b = pointer to gpu memory location of b Array, DIMENSION (ldb,n). Before entry, the leading m-by-n part of the array
2016 : !! b must contain the right-hand side matrix b.
2017 : !! ldb= Specifies the first dimension of b as declared in the calling
2018 : !! (sub)program. The value of ldb must be at least max(1, m).
2019 : !!
2020 : !! OUTPUT
2021 : !! b
2022 : !!
2023 : !! SIDE EFFECTS
2024 : !! WARNING! : this routine is a dummy one when HAVE_GPU_CUDA is not enabled
2025 : !! the correct one is in 17_toolbox/gpu_linalg.cu
2026 : !!
2027 : !! SOURCE
2028 :
2029 0 : subroutine abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
2030 :
2031 : ! !Arguments ------------------------------------
2032 : integer, intent(in) :: cplx,lda,ldb,m,n
2033 : complex(dp), intent(in) :: alpha
2034 : character(len=1), intent(in) :: side,uplo,transa,diag
2035 : type(c_ptr),intent(in) :: a
2036 : type(c_ptr),intent(in) :: b
2037 : ! *********************************************************************
2038 :
2039 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
2040 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
2041 : end if
2042 :
2043 : #ifdef HAVE_GPU
2044 :
2045 : call gpu_xtrsm(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
2046 :
2047 : if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2048 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
2049 : ! Therefore, we issue a stream sync here to avoid
2050 : !potential mistakes in calling context.
2051 : call gpu_linalg_stream_synchronize()
2052 : end if
2053 :
2054 : #else
2055 : ! Unused if GPU code disabled
2056 : ABI_UNUSED((/cplx,lda,ldb,m,n/))
2057 : ABI_UNUSED((/alpha/))
2058 : ABI_UNUSED((/side,uplo,transa,diag/))
2059 : ABI_UNUSED((/a,b/))
2060 : #endif
2061 :
2062 0 : end subroutine abi_gpu_xtrsm_cptr
2063 : !!***
2064 :
2065 0 : subroutine abi_gpu_xtrsm_d(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
2066 :
2067 : ! !Arguments ------------------------------------
2068 : integer, intent(in) :: cplx,lda,ldb,m,n
2069 : complex(dp), intent(in) :: alpha
2070 : character(len=1), intent(in) :: side,uplo,transa,diag
2071 : real(dp), intent(in),target :: a(*)
2072 : real(dp), intent(inout),target :: b(*)
2073 : ! *********************************************************************
2074 :
2075 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
2076 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
2077 : end if
2078 :
2079 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2080 : call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
2081 0 : diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
2082 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2083 : #ifdef HAVE_OPENMP_OFFLOAD
2084 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b)
2085 : call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
2086 : diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
2087 : !$OMP END TARGET DATA
2088 : #endif
2089 : else
2090 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2091 : end if
2092 :
2093 0 : end subroutine abi_gpu_xtrsm_d
2094 : !!***
2095 :
2096 0 : subroutine abi_gpu_xtrsm_z(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
2097 :
2098 : ! !Arguments ------------------------------------
2099 : integer, intent(in) :: cplx,lda,ldb,m,n
2100 : complex(dp), intent(in) :: alpha
2101 : character(len=1), intent(in) :: side,uplo,transa,diag
2102 : complex(dp),intent(in),target :: a(*)
2103 : complex(dp),intent(inout),target :: b(*)
2104 : ! *********************************************************************
2105 :
2106 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
2107 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
2108 : end if
2109 :
2110 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2111 : call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
2112 0 : diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
2113 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2114 : #ifdef HAVE_OPENMP_OFFLOAD
2115 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b)
2116 : call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
2117 : diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
2118 : !$OMP END TARGET DATA
2119 : #endif
2120 : else
2121 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2122 : end if
2123 :
2124 0 : end subroutine abi_gpu_xtrsm_z
2125 : !!***
2126 :
2127 0 : subroutine abi_gpu_xtrsm_2d(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
2128 :
2129 : !Arguments ------------------------------------
2130 : integer, intent(in) :: cplx,lda,ldb,m,n
2131 : complex(dp), intent(in) :: alpha
2132 : character(len=1), intent(in) :: side,uplo,transa,diag
2133 : real(dp), intent(in),target :: a(lda,*)
2134 : real(dp), intent(inout),target :: b(ldb,*)
2135 : ! *********************************************************************
2136 :
2137 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
2138 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
2139 : end if
2140 :
2141 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2142 : call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
2143 0 : diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
2144 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2145 : #ifdef HAVE_OPENMP_OFFLOAD
2146 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b)
2147 : call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
2148 : diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
2149 : !$OMP END TARGET DATA
2150 : #endif
2151 : else
2152 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2153 : end if
2154 :
2155 0 : end subroutine abi_gpu_xtrsm_2d
2156 : !!***
2157 :
2158 0 : subroutine abi_gpu_xtrsm_2z(cplx,side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
2159 :
2160 : !Arguments ------------------------------------
2161 : integer, intent(in) :: cplx,lda,ldb,m,n
2162 : complex(dp), intent(in) :: alpha
2163 : character(len=1), intent(in) :: side,uplo,transa,diag
2164 : complex(dp),intent(in),target :: a(lda,*)
2165 : complex(dp),intent(inout),target :: b(ldb,*)
2166 : ! *********************************************************************
2167 :
2168 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
2169 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
2170 : end if
2171 :
2172 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2173 : call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
2174 0 : diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
2175 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2176 : #ifdef HAVE_OPENMP_OFFLOAD
2177 : !$OMP TARGET DATA USE_DEVICE_ADDR(a,b)
2178 : call abi_gpu_xtrsm_cptr(cplx,side,uplo,transa,&
2179 : diag,m,n,alpha,c_loc(a),lda,c_loc(b),ldb)
2180 : !$OMP END TARGET DATA
2181 : #endif
2182 : else
2183 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2184 : end if
2185 :
2186 0 : end subroutine abi_gpu_xtrsm_2z
2187 : !!***
2188 :
2189 :
2190 : !!****f* m_abi_gpu_linalg/abi_gpu_work_resizeI
2191 : !!
2192 : !! NAME
2193 : !! abi_gpu_work_resizeI
2194 :
2195 : subroutine abi_gpu_work_resizeI(array,array_managed,current_dim,asked_dim)
2196 :
2197 : integer, allocatable, intent(inout) :: array(:)
2198 : integer(kind=c_int32_t), contiguous, pointer, intent(inout) :: array_managed(:)
2199 : integer, intent(inout) :: current_dim
2200 : integer, intent(in ) :: asked_dim
2201 : ! *************************************************************************
2202 :
2203 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2204 :
2205 : #ifdef HAVE_YAKL
2206 : if ( current_dim < asked_dim ) then
2207 : current_dim = asked_dim
2208 : if ( associated(array_managed) ) then
2209 : ABI_FREE_MANAGED(array_managed)
2210 : end if
2211 : ABI_MALLOC_MANAGED(array_managed,(/asked_dim/))
2212 : end if
2213 : #endif
2214 :
2215 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2216 :
2217 : #ifdef HAVE_OPENMP_OFFLOAD
2218 : if ( current_dim < asked_dim ) then
2219 : current_dim = asked_dim
2220 : if ( allocated(array) ) then
2221 : !$OMP TARGET EXIT DATA MAP(release:array)
2222 : ABI_FREE(array)
2223 : end if
2224 : ABI_MALLOC(array,(asked_dim))
2225 : !$OMP TARGET ENTER DATA MAP(alloc:array)
2226 : end if
2227 : #endif
2228 :
2229 : else
2230 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2231 : end if
2232 :
2233 : #ifndef HAVE_GPU
2234 : ! Unused if GPU code disabled
2235 : ABI_UNUSED(array)
2236 : ABI_UNUSED(array_managed)
2237 : ABI_UNUSED((/current_dim,asked_dim/))
2238 : #endif
2239 :
2240 : end subroutine abi_gpu_work_resizeI
2241 : !!***
2242 :
2243 : !!****f* m_abi_gpu_linalg/abi_gpu_work_resizeR
2244 : !!
2245 : !! NAME
2246 : !! abi_gpu_work_resizeR
2247 :
2248 : subroutine abi_gpu_work_resizeR(array,array_managed,current_dim,asked_dim)
2249 :
2250 : double precision, allocatable, intent(inout) :: array(:)
2251 : real(kind=c_double), contiguous, pointer, intent(inout) :: array_managed(:)
2252 : integer, intent(inout) :: current_dim
2253 : integer, intent(in ) :: asked_dim
2254 :
2255 : ! *************************************************************************
2256 :
2257 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2258 :
2259 : #ifdef HAVE_YAKL
2260 : if ( current_dim < asked_dim ) then
2261 : current_dim = asked_dim
2262 : if ( associated(array_managed) ) then
2263 : ABI_FREE_MANAGED(array_managed)
2264 : end if
2265 : ABI_MALLOC_MANAGED(array_managed,(/asked_dim/))
2266 : end if
2267 : #endif
2268 :
2269 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2270 :
2271 : #ifdef HAVE_OPENMP_OFFLOAD
2272 : if ( current_dim < asked_dim ) then
2273 : current_dim = asked_dim
2274 : if ( allocated(array) ) then
2275 : !$OMP TARGET EXIT DATA MAP(release:array)
2276 : ABI_FREE(array)
2277 : end if
2278 : ABI_MALLOC(array,(asked_dim))
2279 : !$OMP TARGET ENTER DATA MAP(alloc:array)
2280 : end if
2281 : #endif
2282 :
2283 : else
2284 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2285 : end if
2286 :
2287 : #ifndef HAVE_GPU
2288 : ! Unused if GPU code disabled
2289 : ABI_UNUSED(array)
2290 : ABI_UNUSED(array_managed)
2291 : ABI_UNUSED((/current_dim,asked_dim/))
2292 : #endif
2293 :
2294 : end subroutine abi_gpu_work_resizeR
2295 : !!***
2296 :
2297 :
2298 : !!****f* m_abi_gpu_linalg/abi_gpu_work_resizeC
2299 : !!
2300 : !! NAME
2301 : !! abi_gpu_work_resizeC
2302 :
2303 : subroutine abi_gpu_work_resizeC(array,array_managed,current_dim,asked_dim)
2304 :
2305 : complex(kind=8), allocatable, intent(inout) :: array(:)
2306 : complex(kind=c_double_complex), contiguous, pointer, intent(inout) :: array_managed(:)
2307 : integer, intent(inout) :: current_dim
2308 : integer, intent(in ) :: asked_dim
2309 : ! *************************************************************************
2310 :
2311 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2312 :
2313 : #ifdef HAVE_YAKL
2314 : if ( current_dim < asked_dim ) then
2315 : current_dim = asked_dim
2316 : if ( associated(array_managed) ) then
2317 : ABI_FREE_MANAGED(array_managed)
2318 : end if
2319 : ABI_MALLOC_MANAGED(array_managed,(/asked_dim/))
2320 : end if
2321 : #endif
2322 :
2323 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2324 :
2325 : #ifdef HAVE_OPENMP_OFFLOAD
2326 : if ( current_dim < asked_dim ) then
2327 : current_dim = asked_dim
2328 : if ( allocated(array) ) then
2329 : !$OMP TARGET EXIT DATA MAP(release:array)
2330 : ABI_FREE(array)
2331 : end if
2332 : ABI_MALLOC(array,(asked_dim))
2333 : !$OMP TARGET ENTER DATA MAP(alloc:array)
2334 : end if
2335 : #endif
2336 :
2337 : else
2338 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2339 : end if
2340 :
2341 : #ifndef HAVE_GPU
2342 : ! Unused if GPU code disabled
2343 : ABI_UNUSED(array)
2344 : ABI_UNUSED(array_managed)
2345 : ABI_UNUSED((/current_dim,asked_dim/))
2346 : #endif
2347 :
2348 : end subroutine abi_gpu_work_resizeC
2349 : !!***
2350 :
2351 : !!****f* m_abi_gpu_linalg/abi_gpu_work_resizeCptr
2352 : !!
2353 : !! NAME
2354 : !! abi_gpu_work_resizeCptr
2355 :
2356 : subroutine abi_gpu_work_resizeCptr(array,current_dim,asked_dim)
2357 : use, intrinsic :: iso_c_binding
2358 :
2359 : type(c_ptr), intent(inout) :: array
2360 : integer(c_size_t), intent(inout) :: current_dim
2361 : integer(c_size_t), intent(in ) :: asked_dim
2362 : ! *************************************************************************
2363 :
2364 : if ( current_dim < asked_dim ) then
2365 : if(current_dim /= 0) then
2366 : call dealloc_on_gpu(array)
2367 : end if
2368 : current_dim = asked_dim
2369 : call alloc_on_gpu(array, asked_dim)
2370 : end if
2371 :
2372 : #ifndef HAVE_GPU
2373 : ! Unused if GPU code disabled
2374 : ABI_UNUSED(array)
2375 : ABI_UNUSED((/current_dim,asked_dim/))
2376 : #endif
2377 :
2378 : end subroutine abi_gpu_work_resizeCptr
2379 : !!***
2380 :
2381 : subroutine abi_gpu_work_finalize()
2382 : use, intrinsic :: iso_c_binding
2383 :
2384 : #ifdef HAVE_GPU
2385 : !FIXME Assuming managed here ?
2386 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2387 :
2388 : #ifdef HAVE_YAKL
2389 : if ( associated(i_work_managed) ) then
2390 : ABI_FREE_MANAGED(i_work_managed)
2391 : end if
2392 : if ( associated(r_work_managed) ) then
2393 : ABI_FREE_MANAGED(r_work_managed)
2394 : end if
2395 : if ( associated(c_work_managed) ) then
2396 : ABI_FREE_MANAGED(c_work_managed)
2397 : end if
2398 : #endif
2399 :
2400 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2401 :
2402 : #ifdef HAVE_OPENMP_OFFLOAD
2403 : if ( allocated(i_work) ) then
2404 : !$OMP TARGET EXIT DATA MAP(release:i_work)
2405 : ABI_FREE(i_work)
2406 : end if
2407 : if ( allocated(r_work) ) then
2408 : !$OMP TARGET EXIT DATA MAP(release:r_work)
2409 : ABI_FREE(r_work)
2410 : end if
2411 : if ( allocated(c_work) ) then
2412 : !$OMP TARGET EXIT DATA MAP(release:c_work)
2413 : ABI_FREE(c_work)
2414 : end if
2415 : #endif
2416 :
2417 : if(gpu_work_len > 0) then
2418 : call dealloc_on_gpu(gpu_work)
2419 : end if
2420 :
2421 : end if
2422 :
2423 : i_work_len = 0
2424 : r_work_len = 0
2425 : c_work_len = 0
2426 : gpu_work_len = 0
2427 :
2428 : #endif
2429 :
2430 : end subroutine abi_gpu_work_finalize
2431 : !!***
2432 :
2433 : !!****f* m_abi_gpu_linalg/abi_gpu_xhegvd
2434 : !! NAME
2435 : !! abi_gpu_xhegvd
2436 : !!
2437 : !! FUNCTION
2438 : !! Compute a LAPACK SYGVD operation on GPU
2439 : !! compute eigen values/vectors of a real generalized
2440 : !! symmetric-definite eigenproblem
2441 : !!
2442 : !! See cusolver documentation
2443 : !! https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-hegvd
2444 : !!
2445 : !! See also LAPACK doc in reference implementation:
2446 : !! https://github.com/Reference-LAPACK/lapack/blob/master/SRC/dhegvd.f
2447 : !!
2448 : !! INPUTS
2449 : !! cplx = 1 if real 2 if complex
2450 : !! itype = integer, type of problem
2451 : !! jobz = character, 'n'(eigenvalues only) or 'v' (eigenvalues + eigenvectors)
2452 : !! uplo = character, 'u' or 'l'
2453 : !! A_nrows = matrix size
2454 : !! A = pointer to gpu memory location of matrix A
2455 : !! lda = leading dimension of matrix A
2456 : !! B = pointer to gpu memory location of matrix B
2457 : !! ldb = leading dimension of matrix B
2458 : !! W = pointer to gpu memory location of matrix W (output eigen values)
2459 : !! devInfo =
2460 : !!
2461 : !! SOURCE
2462 :
2463 0 : subroutine abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, A_nrows, &
2464 : A, lda, &
2465 : B, ldb, &
2466 : W, &
2467 : devInfo)
2468 :
2469 : ! Arguments ------------------------------------
2470 : integer, intent(in ) :: cplx
2471 : integer, intent(in ) :: itype
2472 : character(len=1),intent(in ) :: jobz
2473 : character(len=1),intent(in ) :: uplo
2474 : integer, intent(in ) :: A_nrows
2475 : type(c_ptr), intent(in ) :: A
2476 : integer, intent(in ) :: lda
2477 : type(c_ptr), intent(in ) :: B
2478 : integer, intent(in ) :: ldb
2479 : type(c_ptr), intent(in ) :: W
2480 : integer, intent(inout) :: devInfo
2481 :
2482 : ! Local variables ------------------------------
2483 : integer :: bufferSize
2484 : type(c_ptr) :: gpu_ptr
2485 : ! *************************************************************************
2486 :
2487 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
2488 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
2489 : end if
2490 :
2491 : #ifdef HAVE_GPU
2492 :
2493 : ! probe needed bufferSize
2494 : call gpu_xsygvd_buffersize(cplx, itype, jobz, uplo, &
2495 : A_nrows, &
2496 : A, lda, &
2497 : B, ldb, &
2498 : W, &
2499 : bufferSize)
2500 :
2501 : select case(cplx)
2502 :
2503 : case (1)
2504 : ! resize work array if needed and retrieve work pointer to use
2505 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
2506 : .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2507 : call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
2508 : gpu_ptr = c_loc(r_work_managed)
2509 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2510 : !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(1,c_size_t)*bufferSize*dp)
2511 : !gpu_ptr = gpu_work
2512 : call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
2513 : gpu_ptr = xomp_get_mapped_ptr(c_loc(r_work))
2514 : end if
2515 :
2516 : case (2)
2517 : ! resize work array if needed and retrieve work pointer to use
2518 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
2519 : .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2520 : call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
2521 : gpu_ptr = c_loc(c_work_managed)
2522 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2523 : !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(2,c_size_t)*bufferSize*dp)
2524 : !gpu_ptr = gpu_work
2525 : call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
2526 : gpu_ptr = xomp_get_mapped_ptr(c_loc(c_work))
2527 : end if
2528 :
2529 : end select
2530 :
2531 : ! and compute (finally)
2532 : call gpu_xsygvd(cplx, itype, jobz, uplo, &
2533 : A_nrows, &
2534 : A, lda, &
2535 : B, ldb, &
2536 : W, &
2537 : gpu_ptr, bufferSize, devInfo)
2538 :
2539 : if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2540 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
2541 : ! Therefore, we issue a stream sync here to avoid
2542 : !potential mistakes in calling context.
2543 : call gpu_linalg_stream_synchronize()
2544 : !FIXME Free memory to help GPU memory constraint (temporary?)
2545 : call abi_gpu_work_finalize()
2546 : end if
2547 :
2548 : #else
2549 : ! Unused if GPU code disabled
2550 : ABI_UNUSED((/cplx,itype,A_nrows,lda,ldb,devInfo,bufferSize/))
2551 : ABI_UNUSED((/jobz,uplo/))
2552 : ABI_UNUSED((/A,B,W,gpu_ptr/))
2553 : #endif
2554 :
2555 0 : end subroutine abi_gpu_xhegvd_cptr
2556 : !!***
2557 :
2558 0 : subroutine abi_gpu_xhegvd_d(cplx, itype, jobz, uplo, A_nrows, &
2559 : A, lda, &
2560 : B, ldb, &
2561 : W, &
2562 : devInfo)
2563 :
2564 : ! Arguments ------------------------------------
2565 : integer, intent(in ) :: cplx
2566 : integer, intent(in ) :: itype
2567 : character(len=1),intent(in ) :: jobz
2568 : character(len=1),intent(in ) :: uplo
2569 : integer, intent(in ) :: A_nrows
2570 : real(dp), intent(in ),target :: A(*)
2571 : integer, intent(in ) :: lda
2572 : real(dp), intent(in ),target :: B(*)
2573 : integer, intent(in ) :: ldb
2574 : real(dp), intent(inout),target :: W(*)
2575 : integer, intent(inout) :: devInfo
2576 : ! *************************************************************************
2577 :
2578 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2579 : call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
2580 : A_nrows, &
2581 : c_loc(A), lda, &
2582 : c_loc(B), ldb, &
2583 : c_loc(W), &
2584 0 : devInfo)
2585 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2586 : #ifdef HAVE_OPENMP_OFFLOAD
2587 : !$OMP TARGET DATA USE_DEVICE_ADDR(A,B,W)
2588 : call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
2589 : A_nrows, &
2590 : c_loc(A), lda, &
2591 : c_loc(B), ldb, &
2592 : c_loc(W), &
2593 : devInfo)
2594 : !$OMP END TARGET DATA
2595 : #endif
2596 : else
2597 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2598 : end if
2599 :
2600 0 : end subroutine abi_gpu_xhegvd_d
2601 : !!***
2602 :
2603 0 : subroutine abi_gpu_xhegvd_z(cplx, itype, jobz, uplo, A_nrows, &
2604 : A, lda, &
2605 : B, ldb, &
2606 : W, &
2607 : devInfo)
2608 :
2609 : ! Arguments ------------------------------------
2610 : integer, intent(in ) :: cplx
2611 : integer, intent(in ) :: itype
2612 : character(len=1),intent(in ) :: jobz
2613 : character(len=1),intent(in ) :: uplo
2614 : integer, intent(in ) :: A_nrows
2615 : complex(dp), intent(in ),target :: A(*)
2616 : integer, intent(in ) :: lda
2617 : complex(dp), intent(in ),target :: B(*)
2618 : integer, intent(in ) :: ldb
2619 : real(dp), intent(inout),target :: W(*)
2620 : integer, intent(inout) :: devInfo
2621 : ! *************************************************************************
2622 :
2623 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2624 : call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
2625 : A_nrows, &
2626 : c_loc(A), lda, &
2627 : c_loc(B), ldb, &
2628 : c_loc(W), &
2629 0 : devInfo)
2630 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2631 : #ifdef HAVE_OPENMP_OFFLOAD
2632 : !$OMP TARGET DATA USE_DEVICE_ADDR(A,B,W)
2633 : call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
2634 : A_nrows, &
2635 : c_loc(A), lda, &
2636 : c_loc(B), ldb, &
2637 : c_loc(W), &
2638 : devInfo)
2639 : !$OMP END TARGET DATA
2640 : #endif
2641 : else
2642 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2643 : end if
2644 :
2645 0 : end subroutine abi_gpu_xhegvd_z
2646 : !!***
2647 :
2648 0 : subroutine abi_gpu_xhegvd_2d(cplx, itype, jobz, uplo, A_nrows, &
2649 0 : A, lda, &
2650 0 : B, ldb, &
2651 0 : W, &
2652 : devInfo)
2653 :
2654 : ! Arguments ------------------------------------
2655 : integer, intent(in ) :: cplx
2656 : integer, intent(in ) :: itype
2657 : character(len=1),intent(in ) :: jobz
2658 : character(len=1),intent(in ) :: uplo
2659 : integer, intent(in ) :: A_nrows,lda,ldb
2660 : real(dp), intent(in ),target :: A(lda,*)
2661 : real(dp), intent(in ),target :: B(ldb,*)
2662 : real(dp), intent(inout),target :: W(A_nrows,*)
2663 : integer, intent(inout) :: devInfo
2664 : ! *************************************************************************
2665 :
2666 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2667 : call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
2668 : A_nrows, &
2669 : c_loc(A), lda, &
2670 : c_loc(B), ldb, &
2671 : c_loc(W), &
2672 0 : devInfo)
2673 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2674 : #ifdef HAVE_OPENMP_OFFLOAD
2675 : !$OMP TARGET DATA USE_DEVICE_ADDR(A,B,W)
2676 : call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
2677 : A_nrows, &
2678 : c_loc(A), lda, &
2679 : c_loc(B), ldb, &
2680 : c_loc(W), &
2681 : devInfo)
2682 : !$OMP END TARGET DATA
2683 : #endif
2684 : else
2685 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2686 : end if
2687 :
2688 0 : end subroutine abi_gpu_xhegvd_2d
2689 : !!***
2690 :
2691 0 : subroutine abi_gpu_xhegvd_2z(cplx, itype, jobz, uplo, A_nrows, &
2692 0 : A, lda, &
2693 0 : B, ldb, &
2694 0 : W, &
2695 : devInfo)
2696 :
2697 : ! Arguments ------------------------------------
2698 : integer, intent(in ) :: cplx
2699 : integer, intent(in ) :: itype
2700 : character(len=1),intent(in ) :: jobz
2701 : character(len=1),intent(in ) :: uplo
2702 : integer, intent(in ) :: A_nrows,lda,ldb
2703 : complex(dp), intent(in ),target :: A(lda,*)
2704 : complex(dp), intent(in ),target :: B(ldb,*)
2705 : real(dp), intent(inout),target :: W(A_nrows,*)
2706 : integer, intent(inout) :: devInfo
2707 : ! *************************************************************************
2708 :
2709 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2710 : call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
2711 : A_nrows, &
2712 : c_loc(A), lda, &
2713 : c_loc(B), ldb, &
2714 : c_loc(W), &
2715 0 : devInfo)
2716 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2717 : #ifdef HAVE_OPENMP_OFFLOAD
2718 : !$OMP TARGET DATA USE_DEVICE_ADDR(A,B,W)
2719 : call abi_gpu_xhegvd_cptr(cplx, itype, jobz, uplo, &
2720 : A_nrows, &
2721 : c_loc(A), lda, &
2722 : c_loc(B), ldb, &
2723 : c_loc(W), &
2724 : devInfo)
2725 : !$OMP END TARGET DATA
2726 : #endif
2727 : else
2728 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2729 : end if
2730 :
2731 0 : end subroutine abi_gpu_xhegvd_2z
2732 : !!***
2733 :
2734 : !!****f* m_abi_gpu_linalg/abi_gpu_xheevd
2735 : !! NAME
2736 : !! abi_gpu_xheevd
2737 : !!
2738 : !! FUNCTION
2739 : !! Compute a LAPACK SYEVD operation on GPU
2740 : !! compute eigen values/vectors of a real
2741 : !! symmetric-definite eigenproblem
2742 : !!
2743 : !! See cusolver documentation
2744 : !! https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-heevd
2745 : !!
2746 : !! See also LAPACK doc in reference implementation:
2747 : !! https://github.com/Reference-LAPACK/lapack/blob/master/SRC/dheevd.f
2748 : !!
2749 : !! INPUTS
2750 : !! cplx = 1 if real 2 if complex
2751 : !! jobz = character, 'n'(eigenvalues only) or 'v' (eigenvalues + eigenvectors)
2752 : !! uplo = character, 'u' or 'l'
2753 : !! A_nrows = matrix size
2754 : !! A = pointer to gpu memory location of matrix A
2755 : !! lda = leading dimension of matrix A
2756 : !! W = pointer to gpu memory location of matrix W (output eigen values)
2757 : !! devInfo =
2758 : !!
2759 : !! SOURCE
2760 :
2761 0 : subroutine abi_gpu_xheevd_cptr(cplx, jobz, uplo, A_nrows, &
2762 : A, lda, &
2763 : W, &
2764 : devInfo)
2765 :
2766 : ! Arguments ------------------------------------
2767 : integer, intent(in ) :: cplx
2768 : character(len=1),intent(in ) :: jobz
2769 : character(len=1),intent(in ) :: uplo
2770 : integer, intent(in ) :: A_nrows
2771 : type(c_ptr), intent(in ) :: A
2772 : integer, intent(in ) :: lda
2773 : type(c_ptr), intent(in) :: W
2774 : integer, intent(inout) :: devInfo
2775 :
2776 : ! Local variables ------------------------------
2777 : integer :: bufferSize
2778 : type(c_ptr) :: gpu_ptr
2779 : ! *************************************************************************
2780 :
2781 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
2782 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
2783 : end if
2784 :
2785 : #ifdef HAVE_GPU
2786 :
2787 : ! probe needed bufferSize
2788 : call gpu_xsyevd_buffersize(cplx, jobz, uplo, &
2789 : A_nrows, &
2790 : A, lda, &
2791 : W, &
2792 : bufferSize)
2793 :
2794 : select case(cplx)
2795 :
2796 : case (1)
2797 : ! resize work array if needed and retrieve work pointer to use
2798 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
2799 : .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2800 : call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
2801 : gpu_ptr = c_loc(r_work_managed)
2802 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2803 : !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(1,c_size_t)*bufferSize*dp)
2804 : !gpu_ptr = gpu_work
2805 : call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
2806 : gpu_ptr = xomp_get_mapped_ptr(c_loc(r_work))
2807 : end if
2808 :
2809 : case (2)
2810 : ! resize work array if needed and retrieve work pointer to use
2811 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
2812 : .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2813 : call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
2814 : gpu_ptr = c_loc(c_work_managed)
2815 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2816 : !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(2,c_size_t)*bufferSize*dp)
2817 : !gpu_ptr = gpu_work
2818 : call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
2819 : gpu_ptr = xomp_get_mapped_ptr(c_loc(c_work))
2820 : end if
2821 :
2822 : end select
2823 :
2824 : ! and compute (finally)
2825 : call gpu_xsyevd(cplx, jobz, uplo, &
2826 : A_nrows, &
2827 : A, lda, &
2828 : W, &
2829 : gpu_ptr, bufferSize, devInfo)
2830 :
2831 : if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2832 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
2833 : ! Therefore, we issue a stream sync here to avoid
2834 : !potential mistakes in calling context.
2835 : call gpu_linalg_stream_synchronize()
2836 : end if
2837 :
2838 : #else
2839 : ! Unused if GPU code disabled
2840 : ABI_UNUSED((/cplx,A_nrows,lda,devInfo,bufferSize/))
2841 : ABI_UNUSED((/jobz,uplo/))
2842 : ABI_UNUSED((/A,W,gpu_ptr/))
2843 : #endif
2844 :
2845 0 : end subroutine abi_gpu_xheevd_cptr
2846 : !!***
2847 :
2848 0 : subroutine abi_gpu_xheevd_d(cplx, jobz, uplo, A_nrows, &
2849 : A, lda, &
2850 : W, &
2851 : devInfo)
2852 :
2853 : ! Arguments ------------------------------------
2854 : integer, intent(in ) :: cplx
2855 : character(len=1),intent(in ) :: jobz
2856 : character(len=1),intent(in ) :: uplo
2857 : integer, intent(in ) :: A_nrows
2858 : real(dp), intent(in ),target :: A(*)
2859 : integer, intent(in ) :: lda
2860 : real(dp), intent(inout),target :: W(*)
2861 : integer, intent(inout) :: devInfo
2862 : ! *************************************************************************
2863 :
2864 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2865 : call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
2866 : A_nrows, &
2867 : c_loc(A), lda, &
2868 : c_loc(W), &
2869 0 : devInfo)
2870 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2871 : #ifdef HAVE_OPENMP_OFFLOAD
2872 : !$OMP TARGET DATA USE_DEVICE_ADDR(A,W)
2873 : call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
2874 : A_nrows, &
2875 : c_loc(A), lda, &
2876 : c_loc(W), &
2877 : devInfo)
2878 : !$OMP END TARGET DATA
2879 : #endif
2880 : else
2881 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2882 : end if
2883 :
2884 0 : end subroutine abi_gpu_xheevd_d
2885 : !!***
2886 :
2887 0 : subroutine abi_gpu_xheevd_z(cplx, jobz, uplo, A_nrows, &
2888 : A, lda, &
2889 : W, &
2890 : devInfo)
2891 :
2892 : ! Arguments ------------------------------------
2893 : integer, intent(in ) :: cplx
2894 : character(len=1),intent(in ) :: jobz
2895 : character(len=1),intent(in ) :: uplo
2896 : integer, intent(in ) :: A_nrows
2897 : complex(dp), intent(in ),target :: A(*)
2898 : integer, intent(in ) :: lda
2899 : real(dp), intent(inout),target :: W(*)
2900 : integer, intent(inout) :: devInfo
2901 : ! *************************************************************************
2902 :
2903 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2904 : call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
2905 : A_nrows, &
2906 : c_loc(A), lda, &
2907 : c_loc(W), &
2908 0 : devInfo)
2909 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2910 : #ifdef HAVE_OPENMP_OFFLOAD
2911 : !$OMP TARGET DATA USE_DEVICE_ADDR(A,W)
2912 : call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
2913 : A_nrows, &
2914 : c_loc(A), lda, &
2915 : c_loc(W), &
2916 : devInfo)
2917 : !$OMP END TARGET DATA
2918 : #endif
2919 : else
2920 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2921 : end if
2922 :
2923 0 : end subroutine abi_gpu_xheevd_z
2924 : !!***
2925 :
2926 0 : subroutine abi_gpu_xheevd_2d(cplx, jobz, uplo, A_nrows, &
2927 0 : A, lda, &
2928 0 : W, &
2929 : devInfo)
2930 :
2931 : ! Arguments ------------------------------------
2932 : integer, intent(in ) :: cplx
2933 : character(len=1),intent(in ) :: jobz
2934 : character(len=1),intent(in ) :: uplo
2935 : integer, intent(in ) :: A_nrows,lda
2936 : real(dp), intent(in ),target :: A(lda,*)
2937 : real(dp), intent(inout),target :: W(A_nrows,*)
2938 : integer, intent(inout) :: devInfo
2939 : ! *************************************************************************
2940 :
2941 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2942 : call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
2943 : A_nrows, &
2944 : c_loc(A), lda, &
2945 : c_loc(W), &
2946 0 : devInfo)
2947 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2948 : #ifdef HAVE_OPENMP_OFFLOAD
2949 : !$OMP TARGET DATA USE_DEVICE_ADDR(A,W)
2950 : call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
2951 : A_nrows, &
2952 : c_loc(A), lda, &
2953 : c_loc(W), &
2954 : devInfo)
2955 : !$OMP END TARGET DATA
2956 : #endif
2957 : else
2958 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2959 : end if
2960 :
2961 0 : end subroutine abi_gpu_xheevd_2d
2962 : !!***
2963 :
2964 0 : subroutine abi_gpu_xheevd_2z(cplx, jobz, uplo, A_nrows, &
2965 0 : A, lda, &
2966 0 : W, &
2967 : devInfo)
2968 :
2969 : ! Arguments ------------------------------------
2970 : integer, intent(in ) :: cplx
2971 : character(len=1),intent(in ) :: jobz
2972 : character(len=1),intent(in ) :: uplo
2973 : integer, intent(in ) :: A_nrows,lda
2974 : complex(dp), intent(in ),target :: A(lda,*)
2975 : real(dp), intent(inout),target :: W(A_nrows,*)
2976 : integer, intent(inout) :: devInfo
2977 : ! *************************************************************************
2978 :
2979 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
2980 : call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
2981 : A_nrows, &
2982 : c_loc(A), lda, &
2983 : c_loc(W), &
2984 0 : devInfo)
2985 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
2986 : #ifdef HAVE_OPENMP_OFFLOAD
2987 : !$OMP TARGET DATA USE_DEVICE_ADDR(A,W)
2988 : call abi_gpu_xheevd_cptr(cplx, jobz, uplo, &
2989 : A_nrows, &
2990 : c_loc(A), lda, &
2991 : c_loc(W), &
2992 : devInfo)
2993 : !$OMP END TARGET DATA
2994 : #endif
2995 : else
2996 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
2997 : end if
2998 :
2999 0 : end subroutine abi_gpu_xheevd_2z
3000 : !!***
3001 :
3002 : !!****f* m_abi_gpu_linalg/abi_gpu_xpotrf
3003 : !! NAME
3004 : !! abi_gpu_xpotrf
3005 : !!
3006 : !! FUNCTION
3007 : !! Compute a LAPACK SYGVD operation on GPU
3008 : !! compute eigen values/vectors of a real
3009 : !! symmetric-definite eigenproblem
3010 : !!
3011 : !! See cusolver documentation
3012 : !! https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-potrf
3013 : !!
3014 : !! See also LAPACK doc in reference implementation:
3015 : !! https://github.com/Reference-LAPACK/lapack/blob/master/SRC/dpotrf.f
3016 : !!
3017 : !! INPUTS
3018 : !! cplx = 1 if real 2 if complex
3019 : !! uplo = character, 'u' or 'l'
3020 : !! A_nrows = matrix size
3021 : !! A = pointer to gpu memory location of matrix A
3022 : !! lda = leading dimension of matrix A
3023 : !! devInfo =
3024 : !!
3025 : !! SOURCE
3026 0 : subroutine abi_gpu_xpotrf_cptr(cplx, uplo, A_nrows, &
3027 : A, lda, &
3028 : devInfo)
3029 :
3030 : ! Arguments ------------------------------------
3031 : integer, intent(in ) :: cplx
3032 : character(len=1),intent(in ) :: uplo
3033 : integer, intent(in ) :: A_nrows
3034 : type(c_ptr), intent(in ) :: A
3035 : integer, intent(in ) :: lda
3036 : integer, intent(inout) :: devInfo
3037 :
3038 : ! Local variables ------------------------------
3039 : integer :: bufferSize
3040 : type(c_ptr) :: gpu_ptr
3041 : ! *************************************************************************
3042 :
3043 0 : if (abi_linalg_gpu_mode == ABI_GPU_DISABLED) then
3044 0 : ABI_BUG("You requested to run on CPU to a GPU wrapper :/")
3045 : end if
3046 :
3047 : #ifdef HAVE_GPU
3048 :
3049 : ! probe needed bufferSize
3050 : call gpu_xpotrf_buffersize(cplx, uplo, &
3051 : A_nrows, &
3052 : A, lda, &
3053 : bufferSize)
3054 :
3055 : select case(cplx)
3056 :
3057 : case (1)
3058 : ! resize work array if needed and retrieve work pointer to use
3059 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
3060 : .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
3061 : call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
3062 : gpu_ptr = c_loc(r_work_managed)
3063 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
3064 : !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(1,c_size_t)*bufferSize*dp)
3065 : !gpu_ptr = gpu_work
3066 : call abi_gpu_work_resize(r_work,r_work_managed,r_work_len,bufferSize)
3067 : gpu_ptr = xomp_get_mapped_ptr(c_loc(r_work))
3068 : end if
3069 :
3070 : case (2)
3071 : ! resize work array if needed and retrieve work pointer to use
3072 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY &
3073 : .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
3074 : call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
3075 : gpu_ptr = c_loc(c_work_managed)
3076 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
3077 : !call abi_gpu_work_resizeCptr(gpu_work,gpu_work_len,INT(1,c_size_t)*bufferSize*dp)
3078 : !gpu_ptr = gpu_work
3079 : call abi_gpu_work_resize(c_work,c_work_managed,c_work_len,bufferSize)
3080 : gpu_ptr = xomp_get_mapped_ptr(c_loc(c_work))
3081 : end if
3082 :
3083 : end select
3084 :
3085 : ! and compute (finally)
3086 : call gpu_xpotrf(cplx, uplo, &
3087 : A_nrows, &
3088 : A, lda, &
3089 : gpu_ptr, bufferSize, devInfo)
3090 :
3091 : if (abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
3092 : ! CUDA/HIP linalg calls are run asynchronously and OpenMP is unaware of them.
3093 : ! Therefore, we issue a stream sync here to avoid
3094 : !potential mistakes in calling context.
3095 : call gpu_linalg_stream_synchronize()
3096 : end if
3097 :
3098 : #else
3099 : ! Unused if GPU code disabled
3100 : ABI_UNUSED((/cplx,A_nrows,lda,devInfo,bufferSize/))
3101 : ABI_UNUSED((/uplo/))
3102 : ABI_UNUSED((/A,gpu_ptr/))
3103 : #endif
3104 :
3105 0 : end subroutine abi_gpu_xpotrf_cptr
3106 : !!***
3107 :
3108 0 : subroutine abi_gpu_xpotrf_d(cplx, uplo, A_nrows, &
3109 : A, lda, &
3110 : devInfo)
3111 :
3112 : ! Arguments ------------------------------------
3113 : integer, intent(in ) :: cplx
3114 : character(len=1),intent(in ) :: uplo
3115 : integer, intent(in ) :: A_nrows
3116 : real(dp), intent(in ),target :: A(*)
3117 : integer, intent(in ) :: lda
3118 : integer, intent(inout) :: devInfo
3119 : ! *************************************************************************
3120 :
3121 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
3122 : call abi_gpu_xpotrf_cptr(cplx, uplo, &
3123 : A_nrows, &
3124 : c_loc(A), lda, &
3125 0 : devInfo)
3126 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
3127 : #ifdef HAVE_OPENMP_OFFLOAD
3128 : !$OMP TARGET DATA USE_DEVICE_ADDR(A)
3129 : call abi_gpu_xpotrf_cptr(cplx, uplo, &
3130 : A_nrows, &
3131 : c_loc(A), lda, &
3132 : devInfo)
3133 : !$OMP END TARGET DATA
3134 : #endif
3135 : else
3136 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
3137 : end if
3138 :
3139 0 : end subroutine abi_gpu_xpotrf_d
3140 : !!***
3141 :
3142 0 : subroutine abi_gpu_xpotrf_z(cplx, uplo, A_nrows, &
3143 : A, lda, &
3144 : devInfo)
3145 :
3146 : ! Arguments ------------------------------------
3147 : integer, intent(in ) :: cplx
3148 : character(len=1),intent(in ) :: uplo
3149 : integer, intent(in ) :: A_nrows
3150 : complex(dp), intent(in ),target :: A(*)
3151 : integer, intent(in ) :: lda
3152 : integer, intent(inout) :: devInfo
3153 : ! *************************************************************************
3154 :
3155 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
3156 : call abi_gpu_xpotrf_cptr(cplx, uplo, &
3157 : A_nrows, &
3158 : c_loc(A), lda, &
3159 0 : devInfo)
3160 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
3161 : #ifdef HAVE_OPENMP_OFFLOAD
3162 : !$OMP TARGET DATA USE_DEVICE_ADDR(A)
3163 : call abi_gpu_xpotrf_cptr(cplx, uplo, &
3164 : A_nrows, &
3165 : c_loc(A), lda, &
3166 : devInfo)
3167 : !$OMP END TARGET DATA
3168 : #endif
3169 : else
3170 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
3171 : end if
3172 :
3173 0 : end subroutine abi_gpu_xpotrf_z
3174 : !!***
3175 :
3176 0 : subroutine abi_gpu_xpotrf_2d(cplx, uplo, A_nrows, &
3177 0 : A, lda, &
3178 : devInfo)
3179 :
3180 : ! Arguments ------------------------------------
3181 : integer, intent(in ) :: cplx
3182 : character(len=1),intent(in ) :: uplo
3183 : integer, intent(in ) :: A_nrows,lda
3184 : real(dp), intent(in ),target :: A(lda,*)
3185 : integer, intent(inout) :: devInfo
3186 : ! *************************************************************************
3187 :
3188 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
3189 : call abi_gpu_xpotrf_cptr(cplx, uplo, &
3190 : A_nrows, &
3191 : c_loc(A), lda, &
3192 0 : devInfo)
3193 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
3194 : #ifdef HAVE_OPENMP_OFFLOAD
3195 : !$OMP TARGET DATA USE_DEVICE_ADDR(A)
3196 : call abi_gpu_xpotrf_cptr(cplx, uplo, &
3197 : A_nrows, &
3198 : c_loc(A), lda, &
3199 : devInfo)
3200 : !$OMP END TARGET DATA
3201 : #endif
3202 : else
3203 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
3204 : end if
3205 :
3206 0 : end subroutine abi_gpu_xpotrf_2d
3207 : !!***
3208 :
3209 0 : subroutine abi_gpu_xpotrf_2z(cplx, uplo, A_nrows, &
3210 0 : A, lda, &
3211 : devInfo)
3212 :
3213 : ! Arguments ------------------------------------
3214 : integer, intent(in ) :: cplx
3215 : character(len=1),intent(in ) :: uplo
3216 : integer, intent(in ) :: A_nrows,lda
3217 : complex(dp), intent(in ),target :: A(lda,*)
3218 : integer, intent(inout) :: devInfo
3219 : ! *************************************************************************
3220 :
3221 0 : if(abi_linalg_gpu_mode == ABI_GPU_LEGACY .or. abi_linalg_gpu_mode == ABI_GPU_KOKKOS) then
3222 : call abi_gpu_xpotrf_cptr(cplx, uplo, &
3223 : A_nrows, &
3224 : c_loc(A), lda, &
3225 0 : devInfo)
3226 0 : else if(abi_linalg_gpu_mode == ABI_GPU_OPENMP) then
3227 : #ifdef HAVE_OPENMP_OFFLOAD
3228 : !$OMP TARGET DATA USE_DEVICE_ADDR(A)
3229 : call abi_gpu_xpotrf_cptr(cplx, uplo, &
3230 : A_nrows, &
3231 : c_loc(A), lda, &
3232 : devInfo)
3233 : !$OMP END TARGET DATA
3234 : #endif
3235 : else
3236 0 : ABI_BUG(sjoin("Unhandled GPU mode:", itoa(abi_linalg_gpu_mode)))
3237 : end if
3238 :
3239 0 : end subroutine abi_gpu_xpotrf_2z
3240 : !!***
3241 :
3242 : !!****f* m_abi_linalg/gpu_xorthonormalize
3243 : !! NAME
3244 : !! gpu_xorthonormalize
3245 : !!
3246 : !! FUNCTION
3247 : !! This routine computes the overlap of two complex wavefunctions (for a given number of bands)
3248 : !! and orthonormalizes it using gpu:
3249 : !! - Computes the products of two rectangular matrices
3250 : !! containing the wavefunctions psi and S.psi (where S is the
3251 : !! overlap (with the PAW terms if necessary)).
3252 : !! - Does a Cholesky decomposition of this overlap
3253 : !! - rotates the initial matrix blockvectorx by the triangular matrix to
3254 : !! have an orthonormal set of wavefunctions
3255 : !!
3256 : !! INPUTS
3257 : !! blockvectorbx = matrix of dimension (blocksize,vectsize) as a GPU ptr
3258 : !! (e.g. block of overlap*wavefunction)
3259 : !! blocksize = dimension of matrices (e.g number of bands)
3260 : !! spaceComm = communicator used for MPI parallelization
3261 : !! vectsize = dimension of matrices (e.g number of G vector)
3262 : !!
3263 : !! OUTPUT
3264 : !! sqgram = Choleski decomposition of transpose(blockvector)*blockvectorx as a GPU ptr
3265 : !!
3266 : !! SIDE EFFECTS
3267 : !! blockvectorx = on input, matrix of dimension (vectsize,blocksize) as a GPU ptr
3268 : !! (e.g block of wavefunction)
3269 : !! blockvectorx = on output, orthonormalized wavefunction. as a GPU ptr
3270 : !!
3271 : !! SOURCE
3272 :
3273 0 : subroutine gpu_xorthonormalize(blockvectorx_gpu,blockvectorbx_gpu,blocksize,spaceComm,&
3274 : & sqgram_gpu,vectsize,&
3275 : & x_cplx,timopt,tim_xortho) ! optional arguments
3276 :
3277 : !Arguments ------------------------------------
3278 : !scalars
3279 : integer,intent(in) :: blocksize,spaceComm,vectsize,x_cplx
3280 : integer, intent(in), optional :: timopt,tim_xortho
3281 : !arrays
3282 : type(c_ptr),intent(inout) :: blockvectorbx_gpu, blockvectorx_gpu, sqgram_gpu
3283 : !Local variables-------------------------------
3284 : #if defined HAVE_GPU
3285 : integer :: ierr,info
3286 : real(dp), dimension(:,:),allocatable, target :: d_sqgram
3287 : complex(dp),dimension(:,:),allocatable, target :: z_sqgram
3288 : character :: tr
3289 : real(dp) :: tsec(2)
3290 : integer(c_size_t) :: size
3291 : #else
3292 : type(c_ptr) :: cptr_a
3293 : #endif
3294 : character(len=500) :: message
3295 : ! *********************************************************************
3296 :
3297 : #if defined HAVE_GPU
3298 : if (present(tim_xortho).and.present(timopt)) then
3299 : if(abs(timopt)==3) then
3300 : call timab(tim_xortho,1,tsec)
3301 : end if
3302 : end if
3303 :
3304 : if ( x_cplx == 1 ) then
3305 : tr='t'
3306 : ABI_MALLOC(d_sqgram,(blocksize,blocksize))
3307 : else
3308 : tr='c'
3309 : ABI_MALLOC(z_sqgram,(blocksize,blocksize))
3310 : end if
3311 :
3312 : call gpu_xgemm(x_cplx,tr,'n',blocksize,blocksize,vectsize, &
3313 : & cone,blockvectorx_gpu,vectsize,blockvectorbx_gpu,vectsize,czero,sqgram_gpu,blocksize)
3314 : call gpu_device_synchronize()
3315 : size=x_cplx*dp*blocksize*blocksize
3316 :
3317 : if ( x_cplx == 1 ) then
3318 : call copy_from_gpu(d_sqgram, sqgram_gpu, INT(x_cplx, c_size_t)*dp*blocksize*blocksize)
3319 : call xmpi_sum(d_sqgram,spaceComm,ierr)
3320 : call abi_xpotrf('u',blocksize,d_sqgram,blocksize,info)
3321 : call copy_on_gpu(d_sqgram, sqgram_gpu, INT(x_cplx, c_size_t)*dp*blocksize*blocksize)
3322 : else
3323 : call copy_from_gpu(z_sqgram, sqgram_gpu, size)
3324 : call xmpi_sum(z_sqgram,spaceComm,ierr)
3325 : call abi_xpotrf('u',blocksize,z_sqgram,blocksize,info)
3326 : call copy_on_gpu(z_sqgram, sqgram_gpu, size)
3327 : end if
3328 :
3329 : if (info /= 0 ) then
3330 : write(message,'(a,i3)') ' xpotrf, info=',info
3331 : ABI_WARNING(message)
3332 : end if
3333 :
3334 : call gpu_xtrsm(x_cplx,'r','u','n','n',vectsize,blocksize,cone,sqgram_gpu,blocksize,&
3335 : & blockvectorx_gpu,vectsize)
3336 :
3337 : if(x_cplx==1) then
3338 : ABI_FREE(d_sqgram)
3339 : else
3340 : ABI_FREE(z_sqgram)
3341 : end if
3342 : if (present(tim_xortho).and.present(timopt)) then
3343 : if(abs(timopt)==3) then
3344 : call timab(tim_xortho,2,tsec)
3345 : end if
3346 : end if
3347 : return
3348 :
3349 : #else
3350 0 : message=' This routine is not allowed when running on GPU is disabled !'
3351 0 : ABI_BUG(message)
3352 : if (.false.) then
3353 : write(std_out,*) blocksize,vectsize,spaceComm,x_cplx
3354 : if (present(timopt)) write(std_out,*) timopt
3355 : if (present(tim_xortho)) write(std_out,*) tim_xortho
3356 : cptr_a=blockvectorbx_gpu;cptr_a=blockvectorx_gpu;cptr_a=sqgram_gpu
3357 : end if
3358 : #endif
3359 :
3360 0 : end subroutine gpu_xorthonormalize
3361 : !!***
|