和Fortran调用C代码一样,问题很简单,就是混合编译的问题,基本思路是:C/CUDA 代码写一个文件。Fortran代码写一个文件。各自独立编译compile, 生成-obj文件,然后链接。
只不过写的时候有讲究了。比如在fortran 的test 中调用一段cuda:
其中C代码为:#include
#include
#include
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);
};
其中Fortran代码为program test
implicit none
print *,"Hello World from Fortran"
call helloworldcuda()
end program test然后编译cuda 代码nvcc -c trycuda.cu 然后链接和编译到Fortran代码ifort -o test -L /usr/local/cuda/lib -lcudart trycuda.o tryf.f90然后运行./test注: 该例子来自:http://forums.nvidia.com/index.php?showtopic=151886
fortran一般开的是数组。而C用的是指针?这该怎么办?Fortran的索引从1开始而且是collmn major,C从0开始,而且是row major怎么办?幸好,Nvidia给了个小的解决方案,就是在cublas中。引入了几个API,CUBLAS_SET_VECTOR, CUBLAS_GET_VECTOR,CUBLAS_SET_MATRIX, and CUBLAS_GET_MATRIX).定义在/usr/local/cuda/src 的fortran.c中这几个API的作用是分配device变量的指针和相互拷贝Host和device中内存。编程人员可以直接在f90文件中调用这些函数。
具体,必须将fortran.c拷入你当前的工作目录。然后编译nvcc -c fortran.c 生成了fortran.o然后和你的fortran程序(比如test.f90)进行链接:ifort -o test -L /usr/local/cuda/lib -lcudart -lcublas fortran.o test.f90注意-lcublas不能少。然后./test
具体的那几个api的使用必须查看nvidia的cublas.pdf
Fortran方面声明为数组:如: real, allocatable :: f(:,:,:),df(:,:,:) integer :: nx integer :: ny integer :: ny nx=100 ny=100 nz=100 allocate (df(nx,ny,nz)) allocate ( f(nx,ny,nz))
call cuda_diff(df, f, nx, ny, nz)
而C 代码中这样写:extern "C"void cuda_diff_(float *f, float *df, int *nx, int *ny, int *nz){int x=*nx;....}所以必须注意,nx,ny,nz前面必须有*。而C函数前必须有下划线。
Fortran不区分大小写,并且把在code中所有的大写字母全部识别为小写。而CUDA和C区分大小写。这样在命名函数的时候,CUDA和C的函数如果含有大写字母,那么fortan call cuda 的时候就会报错,找不到XX这个函数。
查看原文 :http://blog.sina.com.cn/dtx08