Trouble using cublas in fortran: Could not resolve generic procedure cublasdgemv_v2

Hello! I apologize in advance for the novice question but I’m trying to learn how to get cublas_v2 function calls working in a Fortran code. The codes are a 1d heat equation solver using implicit methods as part of a school research project and when I compile I cannot seem to get cublas to link correctly. The section of code that the compiler complains about is

function impmid_driver(nt, ts, xs, dx, init_dt, ti, tf, beta) result(u)
!https://docs.nvidia.com/hpc-sdk/compilers/fortran-cuda-interfaces/index.html#iface-introduction
use cudafor 
use cublas_v2
use cusolverDn 
implicit none 
integer, value, intent(in) :: nt 
real(8), intent(in) :: ts(:), xs(NX), dx, init_dt, ti, tf, beta
real(8) :: t_f, dt, t, gamma
real(8) :: a(NX, NX), b(NX, NX), u(NX) 
integer :: i, stat
real(8), device :: a_d(NX, NX), u_d(NX)
real(8), device :: b_d(NX, NX), y1_d(NX), workspace_d(NX)
integer, device :: pivots_d(NX), info_d
type (cublasHandle) ::cb_h
type (cusolverDnHandle) :: cs_h
stat = cublasCreate(cb_h)
stat = cusolverDnCreate(cs_h)

!initializations
dt = init_dt
gamma = beta * dt / (dx * dx)
call init_u(u, xs)
u_d = u 
	
!initialize the matricies for LU. Only perform one LU decompose on b 
!then use the getrs solvers on decomposed b each iteration.
call init_a(a, gamma)
a_d = a 
call init_b(a, b)
b_d = b

!https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-getrf
stat = cusolverDnDgetrf(cs_h, NX, NX, b_d, NX, workspace_d, pivots_d, info_d)

t_f = ti 
!run time stepping loop
do i=1,size(ts)
	!implicit step
	!https://docs.nvidia.com/cuda/cusolver/index.html#cuSolverDN-lt-t-gt-getrs
	y1_d = u_d
	!Note I have no idea what nrhs is supposed to be so I just set it to 1
	stat = cusolverDnDgetrs(cs_h, CUBLAS_OP_N, NX, 1, b_d, NX, pivots_d, y1_d, NX, info_d)
	!update step
	!https://docs.nvidia.com/cuda/cublas/index.html#cublas-lt-t-gt-gemv
	!note I have no idea what the inc[x,y] are supposed to be so I just used 1
	stat = cublasDgemv_v2(cb_h, CUBLAS_OP_N, NX, NX, 1.0, a_d, NX, y1_d, 1, 1.0, u_d, 1.0)
	stat = cudaDeviceSynchronize()
	!update total time
	t_f = t_f + dt 
end do 
u = u_d

end function impmid_driver

I am compiling the full program (omitted here to cut back on clutter, I can provide it if it helps) using nvfortran -o impmid.x impmid.cuf -cpp -DNX=20 and am greeted with the error

NVFORTRAN-S-0155-Could not resolve generic procedure cublasdgemv_v2 (impmid.cuf: 173)
  0 inform,   0 warnings,   1 severes, 0 fatal for impmid_driver

I’ve tried adding the -cudalib=cublas and -lblas flags but nothing changed. This is confusing to me because I don’t seem to be getting any errors regarding the use of cusolver calls, only cublas calls. My user environment is making use of the nvhpc/21.9 modulefile.

Thanks in advance for any tips/help you can provide!

The last entry should be an integer (1), you are passing a real number (1.0).
Interfaces usually check for type mismatch and will throw an error if they find one.

Hmmmm that didn’t seem to do the trick. When I try with

stat = cublasDgemv_v2(cb_h, CUBLAS_OP_N, NX, NX, 1.0, a_d, NX, y1_d, 1, 1.0, u_d, 1)

I still get the same

NVFORTRAN-S-0155-Could not resolve generic procedure cublasdgemv_v2 (impmid.cuf: 173)
  0 inform,   0 warnings,   1 severes, 0 fatal for impmid_driver

I also tried to sanity check myself on this by changing an argument in the cusolver interface and it correctly flagged a type mismatch. So if I wrongly insert a real for the cusolver call like

stat = cusolverDnDgetrs(cs_h, CUBLAS_OP_N, NX, 1.0, b_d, NX, pivots_d, y1_d, NX, info_d)
stat = cublasDgemv_v2(cb_h, CUBLAS_OP_N, NX, NX, 1.0, a_d, NX, y1_d, 1, 1.0, u_d, 1)

I get

NVFORTRAN-S-0188-Argument number 4 to cusolverdndgetrs: type mismatch (impmid.cuf: 169)
NVFORTRAN-S-0155-Could not resolve generic procedure cublasdgemv_v2 (impmid.cuf: 173)
  0 inform,   0 warnings,   2 severes, 0 fatal for impmid_driver

So type mismatching is working but it still seems to be a linking issue

It is not a linking issue, you are getting the error during compilation.
This is a working example of a dgemv call.

program main
use cublas
implicit none
integer, parameter :: dp = kind(0.d0)
integer:: N=4,stat
real(dp), device,allocatable :: a(:,:),x(:),y(:)
real(dp), allocatable :: y_h(:)
type (cublasHandle) ::cb_h

stat = cublasCreate(cb_h)
allocate(a(N,N),x(N),y(N),y_h(N))

a=1.0_dp
x=2.0_dp
y=0.0_dp

! y := alpha*A*x + beta*y
stat = cublasDgemv_v2(cb_h, CUBLAS_OP_N, N, N, 1.0_dp, a, N, x, 1, 1.0_dp, y, 1)

y_h=y
! With N=4 and x=2, y will be all 8
print *,y_h

end program main

pgf90 dgemv.cuf -cudalibs=cublas

$ ./a.out
8.000000000000000 8.000000000000000 8.000000000000000
8.000000000000000

Awesome! Thank you for your help! Adding in the line

integer, parameter :: dp = kind(0.d0)

and changing the dgemv call to include the _dp

stat = cublasDgemv_v2(cb_h, CUBLAS_OP_N, NX, NX, 1.0_dp, a_d, NX, y1_d, 1, 1.0_dp, u_d, 1)

fixed the issue. I guess the call was interpreting 1.0 as a single precision and not a double precision?

Correct. The default kind is 4 (single precision) for literal real values. You can add the flag “-r8” to change the default kind to 8 (double precision), but explicitly setting the kind, as you have, is the better way to go.

-Mat

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.