我相信有很多可能的方法来解决这个问题。但是按照你给出的例子,它应该是相当简单的。
任务可分为两个部分:
- 如何调用C函数从Fortran语言
- 如何从C
调用CUDA功能
我认为你的问题很可能围绕围绕第一部分,因此它并不是CUDA特有的。对于第二部分课程,这里有许多cuda标签的示例,以及cuda sample codes和programming guide。
可能有助于精简第一部分的一种方法是使用许多当前Fortran发行版中内置的ISO_C_BINDING
builtin module。这个模块定义了许多在C和Fortran之间传递数据的类型。
然后,您可以创建一个INTERFACE
块来定义您希望从fortran调用的C函数的参数。下面是一个样例:
$ cat cuda_test.f90
!=======================================================================================================================
!Interface to cuda C functions
!=======================================================================================================================
module cuda_test
use iso_c_binding
interface
!
integer(c_int) function cudatestfunc(idata, isize) bind(C, name="cudatestfunc")
use iso_c_binding
implicit none
type(c_ptr),value :: idata
integer(c_int),value :: isize
end function cudatestfunc
!
end interface
end module cuda_test
!=======================================================================================================================
program main
!=======================================================================================================================
use iso_c_binding
use cuda_test
type(c_ptr) :: mydata
integer*4, target :: mysize,myresult
integer*4,dimension(:),allocatable,target :: darray
mysize = 100
allocate(darray(mysize))
darray = (/ (1, I = 1, mysize) /)
mydata = c_loc(darray)
myresult = cudatestfunc(mydata, mysize)
write (*, '(A, I10)') " result: ", myresult
write (*,*)
end program main
$ cat cuda_test.cu
#include <stdio.h>
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
__global__ void testkernel(int *data, int size){
for (int i = 1; i < size; i++) data[0] += data[i];
}
extern "C" {
int cudatestfunc(int *data, int size){
int *d_data;
cudaMalloc(&d_data, size*sizeof(int));
cudaMemcpy(d_data, data, size*sizeof(int), cudaMemcpyHostToDevice);
testkernel<<<1,1>>>(d_data, size);
int result;
cudaMemcpy(&result, d_data, sizeof(int), cudaMemcpyDeviceToHost);
cudaCheckErrors("cuda error");
return result;
}
}
$ gfortran -c cuda_test.f90 -o cuda_testf.o
$ nvcc -c cuda_test.cu -o cuda_testc.o
$ gfortran cuda_testc.o cuda_testf.o -o cuda_test -L/usr/local/cuda/lib64 -lcudart -lstdc++
$ ./cuda_test
result: 100
$
注意事项/(在RHEL 6.2,GNU 4.4.7,CUDA 7.0测试)其他选项:
如果你只需要调用CUDA运行时API函数,您可以直接从Fortran中调用这些函数,而无需任何C/C++文件(如果您创建自己的绑定)。示例here。
如果您只需调用CUSPARSE或CUBLAS库函数,则会为您创建一些绑定,这些绑定将包含在CUDA分发中。 Linux上缺省的那些绑定安装在/usr/local/cuda/src
。 the cublas documentation包含cublas绑定的工作示例。
如果您需要直接从fortran中调用其他CUDA库函数,创建自己的绑定并不难。对于CUSOLVER中的一组简单操作,一个可行的示例是here。
你也可以直接写CUDA Fortran的代码。 (Here就是一个例子。)这需要CUDA Fortran compiler from PGI。
您也可以编写OpenACC Fortran代码。这需要一个可用的OpenACC编译器,例如来自PGI的编译器。一个PGI免费为学术使用或试用版可供here
你只想调用C函数(调用一些CUDA,但你不CUDA从Fortran的直接互动?)还有的吨关于这个问题。只需在右上角的搜索行中搜索C和Fortran即可。 http://stackoverflow.com/questions/tagged/fortran+c你有没有尝试过自己? –
或者如果你需要更多的参与,你应该提供更多的信息到底应该是什么。 –