Cuda C in Fortran program

Hi

As a student in numerical methods, I am trying to add a GPU accelerated Poisson Solver (Conjugate Gradient) in my DNS code.

However, I failed to call the C routine in my Fortran program. :confused:

Here is the simple test program :

The tryf.f90 file :

program test

implicit none

print *,"Hello World from Fortran"

call helloworld()

call helloworldCUDA()

end program test

The tryc.c file :

#include <stdlib.h>

#include <stdio.h>

void helloworld_ ()

{

printf("Hello world !!\n");

};

And the trycuda.cu file :

#include <stdio.h>

#include <assert.h>

#include <cuda.h>

void helloworldCUDA_ ()

{

printf("Hello world CUDA Routine !!\n");

int deviceCount;

int dev;

cudaGetDeviceCount(&deviceCount);

dev=0;

cudaDeviceProp deviceProp;

cudaGetDeviceProperties(&deviceProp, dev);

printf("\nDevice %d: on %d \"%s\"\n", dev, deviceCount, deviceProp.name);

};

And the makefile is the following :

FC = gfortran

FFLAGS = -fdefault-real-8 -g 

OBJ= \

tryc.o \

trycuda.o \

tryf.o

test:  $(OBJ) makefile

	$(FC) $(FFLAGS)  -o test $(OBJ)

tryc.o: tryc.c makefile

	gcc -g -o tryc.o -c tryc.c

trycuda.o: trycuda.cu makefile

	nvcc -g trycuda.o -c trycuda.cu

tryf.o: tryf.f90 makefile

	$(FC) $(FFLAGS)  -o tryf.o  -c tryf.f90 

clean:

	\rm *.mod *.o

If I try compilling without the CUDA part, the hello world in C works pretty well. But when adding the cuda compilation, I got the following message :

moomba@Freedom:~/Bureau/essaicuda/Test_Modules$ make -f makefile

gcc -g -o tryc.o -c tryc.c

nvcc -g trycuda.o -c trycuda.cu

gfortran -fdefault-real-8 -g   -o tryf.o  -c tryf.f90 

gfortran -fdefault-real-8 -g   -o test tryc.o trycuda.o tryf.o

trycuda.o: In function `__sti____cudaRegisterAll_40_tmpxft_00002e24_00000000_4_e

ssai_cpp1_ii_cec5f5d9':

/tmp/tmpxft_00002e24_00000000-1_essai.cudafe1.stub.c:7: undefined reference to `__cudaRegisterFatBinary'

trycuda.o: In function `__ftexfetch':

/usr/local/cuda/bin/../include/texture_fetch_functions.h:1961: undefined reference to `__cudaTextureFetch'

trycuda.o: In function `__utexfetch':

/usr/local/cuda/bin/../include/texture_fetch_functions.h:1952: undefined reference to `__cudaTextureFetch'

trycuda.o: In function `__itexfetch':

/usr/local/cuda/bin/../include/texture_fetch_functions.h:1943: undefined reference to `__cudaTextureFetch'

trycuda.o: In function `__ftexfetchi':

/usr/local/cuda/bin/../include/texture_fetch_functions.h:1934: undefined reference to `__cudaTextureFetch'

trycuda.o: In function `__utexfetchi':

/usr/local/cuda/bin/../include/texture_fetch_functions.h:1925: undefined reference to `__cudaTextureFetch'

trycuda.o:/usr/local/cuda/bin/../include/texture_fetch_functions.h:1916: more undefined references to `__cudaTextureFetch' follow

trycuda.o: In function `__cudaUnregisterBinaryUtil':

/usr/local/cuda/bin/../include/crt/host_runtime.h:176: undefined reference to `__cudaUnregisterFatBinary'

trycuda.o: In function `helloworldCUDA_()':

/home/moomba/Bureau/essaicuda/Test_Modules/trycuda.cu:10: undefined reference to `cudaGetDeviceCount'

/home/moomba/Bureau/essaicuda/Test_Modules/trycuda.cu:14: undefined reference to `cudaGetDeviceProperties'

trycuda.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'

collect2: ld a retourné 1 code d'état d'exécution

make: *** [pospro_pade6] Erreur 1

moomba@Freedom:~/Bureau/essaicuda/Test_Modules$

Is there a way to import CUDA C code in Fortran program without using the portland fortran beta cuda compiler ? :)

Could someone tell me how to proceed ? :sweat:

You need to link the cudart and stdc++.

Add this to your linking stage:
-L/usr/local/cuda/lib64 -lcudart -lstdc++

I think linking with libstdc++ is not necessary, but on the other side you’d need, when compiling with GCC, to change your .cu file: rename your helloworldCUDA_() method to helloworldcuda_(), and then put all of it into an extern “C” block - both of this to match corresponding calling conventions. Linking Fortran and C code is tricky, and compiler-dependent for the most of the time; hopefully wider adoption of Fortran 2003 will remedy this…

Thank you for your help :)

I will try it today and see if it works like this. (I don’t have my PC with me here ^_^ )

Hi

It works perfect when combining your two answers :

extern "C" helloworldcuda_ ()

{

}

And the compiling with :

nvcc -c trycuda.cu

and then (no lib64, so I used lib)

f95 -L /usr/local/cuda/lib -lcudart -lstdc++ trycuda.o tryf.f90

With :

program test

implicit none

print *,"Hello World from Fortran"

call helloworldcuda()

end program test
#include <stdio.h>

#include <assert.h>

#include <cuda.h>

extern "C" void helloworldcuda_ ()

{

printf("Hello world CUDA Routine !!\n");

int deviceCount;

int dev;

cudaGetDeviceCount(&deviceCount);

dev=0;

cudaDeviceProp deviceProp;

cudaGetDeviceProperties(&deviceProp, dev);

printf("\nDevice %d: on %d \"%s\"\n", dev, deviceCount, deviceProp.name);

};

Thanks a lot, to both of you ! :w00t:

I will be able use my GTX to performe huge CFD and Chemistry simulations. :)