how to use cuda c in fortran

I’m using linux pgi workstation 10.3. I have a free library from NVdia named “batched solver”. It’s a accelerated lib for the computation of batched small scale linear equation. However it is writen in CUDA C, while my program is wirten in CUDA fortran. So i wonder if there is some way to call the function which writen in cuda c, or maybe you can help me to get a cuda fortran version.
The source code of batched solver is too long to paste here.
You can check http://forums.nvidia.com/index.php?showtopic=210707 , or you can provide a E-mail, i will send a email to you.
Thanks!

Hi Siwuxie,

So i wonder if there is some way to call the function which writen in cuda c,

Sure. CUDA C and CUDA Fortran work well together and each can call the other.

To call a CUDA C global routine from CUDA Fortran, you need to write an ISO C Binding interface block for the routine. Once defined, you would then call the routine as any other CUDA routine. Standard Fortran calling C issues still apply. Things like column major versus row major, zero versus 1 based indexing, etc.

I wrote an article Tuning a Monte Carlo Algorithm on GPUs, where I include an example on calling a CUDA C “Mersenne Twister” routine from CUDA Fortran.

Here’s the interface block:

interface

    ! C function to load the Mersenne Twister input data set
    subroutine loadMTGPU(dat_path) bind(c,name='loadMTGPU')
       use iso_c_binding
       character(len=80) :: dat_path
    end subroutine loadMTGPU

    ! C function to initialize the random seed on the GPU
    subroutine seedMTGPU(seed) bind(c,name='seedMTGPU')
       use iso_c_binding
        integer(c_int), value :: seed   ! Pass by value
    end subroutine seedMTGPU

    ! CUDA C Mersenne Twister algorithm to generate an array of random
    ! numbers in parallel.  Note that nvcc has added '__entry' to the
    ! end of the function name.
    subroutine RandomGPU(d_Rand, n_per_rng) bind(c,name='randomgpu__entry')
        use iso_c_binding
        real(c_float), dimension(:), device :: d_Rand
        integer, value :: n_per_rng  ! pass by value
    end subroutine RandomGPU

end interface

Then call the routines as you normally would:

    ! initalize and then call the RNG for dX
    write(dpath,'(a)') 'mtdata/MersenneTwister.dat'//char(0)
    call loadMTGPU(dpath)
    call seedmtgpu(777)
    call randomgpu<<<32>>>(dX,N_PER_THD)

Hope this helps,
Mat

Hi mat
Thanks for your interface! It really worked well!

siwuxie