How to use (or call) cublas library

Hi,

I am testing to use cublas in cuda fortran sample code.

program test_cublasSgemm
#ifdef _CUDAFOR
use cudafor

interface
  subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc ) bind(c,name='cublasSgemm')
   use iso_c_binding
   integer(c_int), value :: m, n, k, lda, ldb, ldc
   real(c_float), device, dimension(m,n) :: a, b, c
   real(c_float), value :: alpha, beta
   character(kind=c_char), value :: transa, transb
  end subroutine sgemm
end interface

real, device, allocatable, dimension(:,:) :: dA, dB, dC
#endif

real, allocatable, dimension(:,:) :: a, b, c
real :: alpha = 1.0e0
real :: beta  = 0.0e0
real :: t1, t2, tt, gflops
integer :: i, j, k

print *, "Enter N: "
read(5,*) n

allocate(a(n,n), b(n,n), c(n,n))
#ifdef _CUDAFOR
allocate(dA(n,n), dB(n,n), dC(n,n))
#endif

a = 2.0e0
b = 1.5e0
c = -9.9e0

call cpu_time(t1)

#ifdef _CUDAFOR
dA = a
dB = b
if (beta .ne. 0.0) then
  dC = c
endif

call sgemm('n', 'n', n, n, n, alpha, dA, n, dB, n, beta, dC, n)
c = dC
#else
call sgemm('n', 'n', n, n, n, alpha, a, n, b, n, beta, c, n)
#endif

call cpu_time(t2)

print *, "Checking results...."

do j = 1, n
  do i = 1, n
    if (c(i,j) .ne. (3.0e0*real(n))) then
      print *, "error:  ",i,j,c(i,j)
    endif
  enddo
enddo

gflops = (real(n) * real(n) * real(n) * 2.0) / 1000000000.0
tt = t2 - t1
print *, "Total Time: ",tt
print *, "Total SGEMM gflops: ",gflops/tt
print *, "Done...."

end

I compiled the code with “pgfortran -Mcuda -D_CUDAFOR -o test_cublasSgemm_gpu test_cublasSgemm.F90 -lcublas”, and got an error message like “LINK : fatal error LNK1104: cannot open file libcublas.lib”. It seems like linking problem with calling C code from fortran. Please help. I’m using windows xp x86.

Thanks.

Hi odyssey,

I compiled the code with “pgfortran -Mcuda -D_CUDAFOR -o test_cublasSgemm_gpu test_cublasSgemm.F90 -lcublas”, and got an error message like "LINK : fatal error LNK1104: cannot open file libcublas.lib

Since CUBLAS doesn’t ship with the compilers or a system library, the location of this library is not included in the default search paths. Hence, you need to add the “-L<full/path/to/cublas/lib/dir>” flag.

Also, check the actual name of the library. On Windows, libraries can sometimes be called “cublas.lib” (i.e. no “lib”). If this is the case, then instead of using “-l” and “-L”, just add the full path and library name to the link line.

Hope this helps,
Mat

Thank you for reply, Mat.

Based on your recommendation, I tried to compile with “pgfortran -Mcuda -o test_cublasSgemm_gpu test_cublasSgemm.F90 c:\cuda\lib\cublas.lib”.
But I got an error like
“test_cublasSgemm.obj : error LNK2019: unresolved external symbol _cublasSgemm referenced in function MAIN
test_cublasSgemm_gpu.exe : fatal error LNK1120: 1 unresolved externals”

Please help.

Thanks,

odyssey

Hi odyssey,

Because of Win32 calling conventions, you need to add an “@” followed by the size in bytes of the argument list to symbol decoration. For sgemm this is “@52”.

interface
  subroutine sgemm(transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, ldc bind(c,name='cublasSgemm@52')
use iso_c_binding
...

Note to figure out what the “@” number should be for other cublas.lib routines, run the command “pgnm c:\cuda\lib\cublas.lib” and look for the particular routine name.

Also, Win64 uses a different calling convention and does not need the “@”. For full details on Win32 calling conventions, please refer to chapter 12 of the PGI User’s Guide.

Hope this helps,
Mat

Hi Mat,

It works. Thank you.

I appreciate it.

odyssey