OpenACC GFortran Interoperability with CUDA libraries
Fortran interface files for the FORTRAN CUDA Library based on their corresponding header files provided by the CUDA Toolkit are publicly available on GitHub: https://github.com/MentorEmbedded/fortran-cuda-interfaces. They contain modules cublas_v2, cublas (legacy CUBLAS interface), cublasxt (multi-GPU host interface), openacc_cublas (interface for OpenACC device code regions), and cufft, which can be utilized by adding the following lines at the beginning of a Fortran program, function or subroutine:
use cublas_v2 use cublas use cublasxt use openacc_cublas use cufft
The following program demonstrates how to use cublasSaxpy with gfortran.
program test use cublas implicit none integer, parameter :: N = 10 integer :: i real*4 :: x_ref(N), y_ref(N), x(N), y(N), a a = 2.0 do i = 1, N x(i) = 4.0 * i y(i) = 3.0 x_ref(i) = x(i) y_ref(i) = y(i) end do call saxpy (N, a, x_ref, y_ref) !$acc data copyin (x) copy (y) !$acc host_data use_device (x, y) call cublassaxpy(N, a, x, 1, y, 1) !$acc end host_data !$acc end data do i = 1, N if (y(i) .ne. y_ref(i)) call abort end do end program test subroutine saxpy (nn, aa, xx, yy) integer :: nn real*4 :: aa, xx(nn), yy(nn) integer i real*4 :: t !$acc routine do i = 1, nn yy(i) = yy(i) + aa * xx(i) end do end subroutine saxpy
To build and run this example, issue the following commands:
$gfortran -fopenacc cublas-test.f90 -lcublas
$ ./a.out
You may need to add -L/path/to/cuda/lib if CUDA is not installed in a standard location. At present, the CUDA interface files for Fortran include support for calling CUBLAS and CUFFT functions from the host. As the example demonstrates, the on-device data for those CUDA functions can be managed by OpenACC. However, the CUDA functions cannot be called from within OpenACC parallel or kernels regions.
The CUDA interface files support the functions defined in CUDA 9. If new functions are added to CUDA in a later release, they can be called directly in GFortran manually by writing new function interfaces for them. For example, to call cublassaxpy from Fortran, use the following interface block.
interface subroutine cublassaxpy(N, alpha, x, incx, y, incy) bind(c, name="cublasSaxpy") use iso_c_binding integer(kind=c_int), value :: N real*4, value :: alpha type(*), dimension(*) :: x integer(kind=c_int), value :: incx type(*), dimension(*) :: y integer(kind=c_int), value :: incy end subroutine cublassaxpy end interface
The arguments passed to cublassaxpy must be declared as host_data. A more complete example can be found here: