Fortran call curand library - can not compile

Hello! I want to use curand library in Fortran. I write a module as follows:

module curand
	integer, parameter, public :: CURAND_RNG_PSEUDO_DEFAULT=100

	interface curandCreateGenerator
	    !curandCreateGenerator(curandGenerator_t* generator, curandRngType_t rng_type)
		subroutine curandCreateGenerator(generator,rng_type) &
		bind(C,name='curandCreateGenerator')
			use iso_c_binding
			integer(c_size_t)::generator
			integer(c_int),value::rng_type
		end subroutine
	end interface

	interface curandSetPseudoRandomGeneratorSeed
		!curandSetPseudoRandomGeneratorSeed(curandGenerator_t generator, unsigned long long seed)
		subroutine curandSetPseudoRandomGeneratorSeed(generator,seed) &
		bind(C,name='curandSetPseudoRandomGeneratorSeed')
			use iso_c_binding
			integer(c_size_t),value::generator
			integer(c_long_long),value::seed
		end subroutine
	end interface

	interface curandGenerateUniform
		!curandGenerateUniform(curandGenerator_t generator, float *outputPtr, size_t num)
		subroutine curandGenerateUniform(generator, odata, numele) &
		bind(C,name='curandGenerateUniform')
			use iso_c_binding
			integer(c_size_t),value::generator
			!pgi$ ignore_tr odata
			real(c_float),device::odata(*)
			integer(c_int),value::numele
		end subroutine
	end interface

	interface curandDestroyGenerator
		!curandDestroyGenerator(curandGenerator_t generator)
		subroutine curandDestroyGenerator(generator) &
		bind(C,name='curandDestroyGenerator')
			use iso_c_binding
			integer(c_size_t),value::generator
		end subroutine
	end interface
end module

and a Main.cuf file, as:

!
!  Main.cuf
!
!  CUDA Fortran Source File 
!  Generated by PGI Visual Fortran(R)
!  2014/6/14 20:02:15
!

program testCurand
	use cudafor
	use curand
	implicit none
	real,allocatable,pinned :: hostData(:)
	real,allocatable,device :: deviceData(:)
	integer(kind=8) :: gen,N,seed=1234

	N=10000000 ! Define how many numbers we want to generate
	! Allocate arrays on CPU and GPU
	allocate(hostData(N),deviceData(N))
	! Create pseudonumber generator
	call curandCreateGenerator(gen,CURAND_RNG_PSEUDO_DEFAULT)
	! Set seed
	call curandSetPseudoRandomGeneratorSeed(gen,seed)
	! Generate N floats on device
	call curandGenerateUniform(gen,deviceData,N)
	! Copy the data back to CPU
	hostData=deviceData
	print *,hostData(1:5),hostData(N-4:N)
	! Deallocate data on CPU and GPU
	deallocate(hostData,deviceData)
	! Destroy the generator
	call curandDestroyGenerator(gen)

	pause
	stop
end program

the compile settings are:
Additional Include Directories: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\include
Additional Library Directories: C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v5.5\include
Additional Dependencies: curand.lib
but it can not compile, the errors are:
Deleting intermediate and output files for project ‘CudaFortranCallCurand’, configuration ‘Debug’
Compiling Project …
curand_module.cuf
Main.cuf
D:\PGI Visual Fortran 13.9\CudaFortranCallCurand\CudaFortranCallCurand\Main.cuf(21) : error S0155 : Could not resolve generic procedure curandcreategenerator
D:\PGI Visual Fortran 13.9\CudaFortranCallCurand\CudaFortranCallCurand\Main.cuf(23) : error S0155 : Could not resolve generic procedure curandsetpseudorandomgeneratorseed
D:\PGI Visual Fortran 13.9\CudaFortranCallCurand\CudaFortranCallCurand\Main.cuf(25) : error S0155 : Could not resolve generic procedure curandgenerateuniform
D:\PGI Visual Fortran 13.9\CudaFortranCallCurand\CudaFortranCallCurand\Main.cuf(32) : error S0155 : Could not resolve generic procedure curanddestroygenerator
0 inform, 0 warnings, 4 severes, 0 fatal for testcurand
CudaFortranCallCurand build failed.
Can you give some advices about this problem? Thank you very much!

Nightwish

Hi Nightwish,

The problem is that you have a kind mismatch between the interface and main program. Also, I’m guessing that you’re using Win32, in which case you also need to add the “!dec$ attribute” in order to get the Win32 symbol names in the “stdcall” api format.

Hope this helps,
Mat

module curand
    integer, parameter, public :: CURAND_RNG_PSEUDO_DEFAULT=100

    interface curandCreateGenerator
        !curandCreateGenerator(curandGenerator_t* generator, curandRngType_t rng_type)
       subroutine curandCreateGenerator(generator,rng_type) &
       bind(C,name='curandCreateGenerator')
!dec$ attributes stdcall, decorate :: curandCreateGenerator
          use iso_c_binding
          integer(c_size_t)::generator
          integer(c_int),value::rng_type
       end subroutine
    end interface

    interface curandSetPseudoRandomGeneratorSeed
       !curandSetPseudoRandomGeneratorSeed(curandGenerator_t generator, unsigned long long seed)
       subroutine curandSetPseudoRandomGeneratorSeed(generator,seed) &
       bind(C,name='curandSetPseudoRandomGeneratorSeed')
!dec$ attributes stdcall, decorate :: curandSetPseudoRandomGeneratorSeed
          use iso_c_binding
          integer(c_size_t),value::generator
          integer(c_long_long),value::seed
       end subroutine
    end interface

    interface curandGenerateUniform
       !curandGenerateUniform(curandGenerator_t generator, float *outputPtr, size_t num)
       subroutine curandGenerateUniform(generator, odata, numele) &
       bind(C,name='curandGenerateUniform')
!dec$ attributes stdcall, decorate :: curandGenerateUniform
          use iso_c_binding
          integer(c_size_t),value::generator
          !pgi$ ignore_tr odata
          real(c_float),device::odata(*)
          integer(c_size_t),value::numele
       end subroutine
    end interface

    interface curandDestroyGenerator
       !curandDestroyGenerator(curandGenerator_t generator)
       subroutine curandDestroyGenerator(generator) &
       bind(C,name='curandDestroyGenerator')
!dec$ attributes stdcall, decorate :: curandDestroyGenerator
          use iso_c_binding
          integer(c_size_t),value::generator
       end subroutine
    end interface
 end module



!
 !  Main.cuf
 !
 !  CUDA Fortran Source File
 !  Generated by PGI Visual Fortran(R)
 !  2014/6/14 20:02:15
 !

 program testCurand
    use cudafor
    use curand
    use iso_c_binding
    implicit none
    real,allocatable,pinned :: hostData(:)
    real,allocatable,device :: deviceData(:)
    integer(kind=8) :: N,seed=1234
    integer(c_size_t) :: gen,istat

    N=10000 ! Define how many numbers we want to generate
    ! Allocate arrays on CPU and GPU
    allocate(hostData(N),deviceData(N))
    ! Create pseudonumber generator
    call curandCreateGenerator(gen,CURAND_RNG_PSEUDO_DEFAULT)
    ! Set seed
    call curandSetPseudoRandomGeneratorSeed(gen,seed)
    ! Generate N floats on device
    call curandGenerateUniform(gen,deviceData,N)
    ! Copy the data back to CPU
    hostData=deviceData
    print *,hostData(1:5),hostData(N-4:N)
    ! Deallocate data on CPU and GPU
    deallocate(hostData,deviceData)
    ! Destroy the generator
    call curandDestroyGenerator(gen)

    pause
    stop
 end program



PGI$ pgf90 -Mcuda curand_m.cuf  main.cuf curand.lib -o test.exe
curand_m.cuf:
main.cuf:
PGI$ ./test.exe
   0.1454676       0.8201809       0.5503992       0.2948303
   0.9147328       0.5784590       0.6629176       0.7371495
   0.7640094       0.4601919
FORTRAN PAUSE: enter <return> or <ctrl>d to continue>
Warning: ieee_inexact is signaling
FORTRAN STOP

Thank you very much for your kind reply.

I copy all the codes listed by you and compile the source files by VS2012 and command window. However, both of them failed. The error message is:

Deleting intermediate and output files for project ‘CudaFortranCallCurand’, configuration ‘Debug’
Compiling Project …
curand_module.cuf
Main.cuf
D:\PGI Visual Fortran 14.6\CudaFortranCallCurand\CudaFortranCallCurand\Main.cuf(27) : error S0155 : Could not resolve generic procedure curandgenerateuniform
0 inform, 0 warnings, 1 severes, 0 fatal for testcurand
CudaFortranCallCurand build failed.

If I comment “call curandGenerateUniform(gen,deviceData,N)”, it can be compiled successfully. What should I do with this problem?

Furthermore, I use the windows 7 32 bit operating system. I want to know that when I using 64 bit operating system, do i need to add the !dec$ directives? Or need more other codes?

Thank you!

Nightwish

If I comment “call curandGenerateUniform(gen,deviceData,N)”, it can be compiled successfully. What should I do with this problem?

Check that the variable data types match. My guess is that “N” might need to be “integer(c_size_t)” (which is 4 in 32-bits) instead of integer(8). Though, you might need to try a couple values. Though it could be “gen” as well.

Furthermore, I use the windows 7 32 bit operating system. I want to know that when I using 64 bit operating system, do i need to add the !dec$ directives? Or need more other codes?

Win64 is more sane and only has the one calling convention.

Win32 has multiple calling conventions and you need make sure the caller and callee match. When our default calling convention differs from that of the callee, you need to add the DEC directives so we know what calling convention to target.

  • Mat

Thank you very much Mat! Your reply is so valueable!

I follow your suggestions but it still fail to compile with the same error. I tried lots of ways to check how to solve this problem but no success. Therefore I uninstall the 14.6 and install the 13.9. I success in 13.9 after revise the kind mismatch of variable N (switch from “integer(kind=8)” to “integer(c_size_t)”).

I have faced lots of problems in using the 14.6 version such as call libraries curand and thrust. I find that 14.x is much different from 13.x and causes some trouble when coding. 13.9 is more stable but do not support the routine directive in OpenACC. What a pity!

Thank you very much!

Nightwish

Hi Nightwish,

I tested the example I posted on Linux, Win64, and Win32 using PGI 14.4 and 14.6. I’m note why it’s not working for you, Sorry!

  • Mat