在带有 C 包装器的 Fortran 程序中分配 CUDA 固定内存(没有 PGI CUDA FORTRAN)



我正在尝试让Fortran程序(主)写入/读取由CUDA C/C++分配的固定内存,但测试表明即使来自C包装器的cudaHostAlloc也会返回错误。

Fortran 访问 CUDA C/C++malloc内存可以在"将可分配数组从 fortran 传递到 C 并 malloc 它"之后完成,但是,简单地用cudaMallocHostcudaHostAlloc替换malloc将返回cudaErrorMemoryAllocation(可以成功编译)。

ifort用于Fortran。下面是不起作用的代码:*编辑以包含整个脚本

//CUDA C/C++ host function in "cudaMallocHost.cu"
#include <cuda.h>
#include <cuda_runtime_api.h>
#include <cstdio>
extern "C" {
int *alloc_test(size_t size) {
int *a;
size_t fm, gm;
cudaMemGetInfo(&fm, &gm);
printf("GPU memory usage: %lu/%lu MBn", fm / 1024 / 1024,
gm / 1024 / 1024);
cudaHostAlloc((void **) &(a), sizeof(int) * size, cudaHostAllocDefault);
printf("%sn", cudaGetErrorString(cudaGetLastError()));
//       a=(int*) malloc(sizeof(int) * 4);  // 'malloc' works
return a;
}
void destroy_test(int *ptr) {
cudaFreeHost(ptr);
printf("%sn", cudaGetErrorString(cudaGetLastError()));
//       free(ptr);
}
}

! FORTRAN program in "main.f"
PROGRAM fortran_side
USE ISO_C_BINDING
IMPLICIT NONE
INTERFACE
FUNCTION alloc_test(s) BIND(C, NAME='alloc_test')
USE ISO_C_BINDING
IMPLICIT NONE
TYPE(C_PTR)   :: alloc_test
INTEGER(C_SIZE_T) :: s
END FUNCTION alloc_test
SUBROUTINE destroy_test(p) BIND(C, NAME='destroy_test')
USE, INTRINSIC :: ISO_C_BINDING, ONLY: C_PTR
IMPLICIT NONE
TYPE(C_PTR), INTENT(IN), VALUE :: p
END SUBROUTINE destroy_test
END INTERFACE
TYPE(C_PTR) :: p
INTEGER(C_INT), POINTER :: array(:)
INTEGER(C_SIZE_T)       :: sz
INTEGER(4)              :: i
sz=4
p = alloc_test(sz)
CALL C_F_POINTER(p, array, [sz])
DO i=1,sz
array(i)=i*3
END DO
PRINT*,array
CALL destroy_test(p)
END PROGRAM fortran_side

#Makefile
all: cudaMallocHost.o main.f
ifort -L/Developer/NVIDIA/CUDA-8.0/lib -lcudart -lcufft -O0 -132 
cudaMallocHost.o main.f -o ./test
clean:
rm  -f *.o *.mod ./test
%.o: %.cu
nvcc -arch sm_30 -O0 -c $*.cu -o $*.o

输出:

GPU memory usage: 836/2047 MB
out of memory
forrtl: severe (174): SIGSEGV, segmentation fault occurred

cudaMallocHost在Fortran主程序中可行吗?我已经尝试过PGI CUDA Fortran,它可以很容易地完成,而不涉及Fortran/C混合编程。我也尝试过纯 CUDAcudaMallocHost,它也适用于我的系统 (Mac)。

C 函数

int *alloc_test(size_t size) 

期望按值参数,但您的 Fortran 接口通过引用传递它

FUNCTION alloc_test(s) BIND(C, NAME='alloc_test')
...
INTEGER(C_SIZE_T) :: s

按值使用传递它

INTEGER(C_SIZE_T), VALUE :: s

最新更新