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

Allocate CUDA pinned memory in a Fortran program with C wrapper (WITHOUT PGI CUDA Fortran)

我正在尝试让 Fortran 程序(主)write/read 由 CUDA C/C++ 分配的固定内存,但测试显示来自 C 包装器的 cudaHostAlloc 也会 return 错误。

Fortran 访问 CUDA C/C++ malloc 内存可以按照 "Passing allocatable array from fortran to C and malloc it" 完成,但是,只需将 malloc 替换为 cudaMallocHostcudaHostAlloc会returncudaErrorMemoryAllocation(可以编译成功)。

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 MB\n", fm / 1024 / 1024,
            gm / 1024 / 1024);
    cudaHostAlloc((void **) &(a), sizeof(int) * size, cudaHostAllocDefault);
    printf("%s\n", cudaGetErrorString(cudaGetLastError()));
    //       a=(int*) malloc(sizeof(int) * 4);  // 'malloc' works
    return a;
}
void destroy_test(int *ptr) {
    cudaFreeHost(ptr);
    printf("%s\n", 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

在 Fortran 主程序中 cudaMallocHost 可行吗?我已经尝试过 PGI CUDA Fortran,它可以很容易地完成这项工作,而无需涉及 Fortran/C 混合编程。我也尝试过纯 CUDA cudaMallocHost,它也适用于我的系统 (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