Reputation: 13
I'm really sorry if this was already solved somewhere, but I cannot find any solutions anywhere. I'm trying to compile a Fortran-based code using cuda. I stumbled on weird errors that I was able to reproduce using the simple example from this page.
It's a simple operation, we have the cuda code:
cudatest.cu
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cuda.h>
#include <cuda_runtime.h>
// function called from main fortran program
extern "C" void kernel_wrapper_(float *a, int *Np)
{
float *a_d; // declare GPU vector copy
int N = *Np; // N threads on GPU
// Allocate memory on GPU
cudaMalloc( (void **)&a_d, sizeof(float) * N );
// free GPU memory
cudaFree(a_d);
return;
}
The fortran code:
fortest.f95
PROGRAM fortest
IMPLICIT NONE
integer*4 :: i
integer*4, parameter :: N=8
real*4, Dimension(N) :: a
DO i=1,N
a(i)=i*1.0
END DO
print *, 'a = ', (a(i), i=1,N)
CALL kernel_wrapper(a, N)
print *, 'a = ', (a(i), i=1,N)
END PROGRAM fortest
And the makefile:
Test: fortest.f95 cudatest.o
gfortran -L/usr/local/cuda-5.5/lib64 -I/usr/local/cuda-5.5/include -lcudart -lcuda fortest.f95 cudatest.o
cudatest.o: cudatest.cu
nvcc -c -O3 cudatest.cu
clean:
rm a.out cudatest.o cudatest.linkinfo
While trying to compile through make
, I'm getting the following errors:
nvcc -c cudatest.cu
gfortran -L /usr/local/cuda-5.5/lib64 -lcudart fortest.f95 cudatest.o
cudatest.o: In function `kernel_wrapper_':
tmpxft_00004a32_00000000-3_cudatest.cudafe1.cpp:(.text+0x31): undefined reference to `cudaMalloc'
tmpxft_00004a32_00000000-3_cudatest.cudafe1.cpp:(.text+0x3d): undefined reference to `cudaFree'
cudatest.o: In function `__cudaUnregisterBinaryUtil()':
tmpxft_00004a32_00000000-3_cudatest.cudafe1.cpp:(.text+0x71): undefined reference to `__cudaUnregisterFatBinary'
cudatest.o: In function `__sti____cudaRegisterAll_43_tmpxft_00004a32_00000000_6_cudatest_cpp1_ii_3bf9bcb9()':
tmpxft_00004a32_00000000-3_cudatest.cudafe1.cpp:(.text+0x9a): undefined reference to `__cudaRegisterFatBinary'
collect2: error: ld returned 1 exit status
make: *** [Test] Erreur 1
So basically, gfortran doesn't realize it now knows cuda. I found some people with the same problems, but it seems adding the cuda runtime library (-lcudart) was the solution for all of them. I noticed that if I change the name of the cuda include directory to anything, the compiler doesn't really notice and spout out the same errors (e.g. "cuda-5.5/include" to "cuda-banana/include")
I'm using gfortran 4.8.1 and Cuda 5.5 which I just installed. The cuda code compiles well on its own.
Again, if the solution is already somewhere, I apologize. I may have already found it but not understood it. Thank you in advance !
EDIT: I simplified the overall program so the issue can be clearer.
Upvotes: 1
Views: 1378
Reputation: 60113
This Makefile works for me with gcc 4.6 and CUDA 4.2. The main point is linking with nvcc
.
Test: fortest.o cudatest.o
nvcc -lgfortran -lgfortranbegin -L/usr/local/cuda-5.5/lib64 -I/usr/local/cuda-5.5/include -lcudart -lcuda fortest.o cudatest.o
fortest.o: fortest.f95
gfortran -c -O5 fortest.f95 -o fortest.o
cudatest.o: cudatest.cu
nvcc -c -O3 cudatest.cu
clean:
rm a.out cudatest.o fortest.o cudatest.linkinfo
This works too, the cure is to have the order right. First the files that contain the references to the library functions and then the libraries with the functions (adjust the path to the libraries):
Test: fortest.f95 cudatest.o
gfortran fortest.f95 cudatest.o -L/usr/local/cuda/lib64 -lcuda -lcudart
cudatest.o: cudatest.cu
nvcc -c -O3 cudatest.cu
clean:
rm a.out cudatest.o cudatest.linkinfo
Output of your program:
./a.out
a = 1.0000000 2.0000000 3.0000000 4.0000000 5.0000000 6.0000000 7.0000000 8.0000000
a = 1.0000000 2.0000000 3.0000000 4.0000000 5.0000000 6.0000000 7.0000000 8.0000000
Upvotes: 1