如何在CUDA Fortran中分配共享内存数组?

时间:2010-12-09 19:28:19

标签: arrays compiler-errors cuda fortran

我在尝试在内核中声明共享内存数组时遇到了麻烦。这是包含我内核的代码:

module my_kernels

  use cudafor
  implicit none

contains

  attributes(global) subroutine mykernel(N)

    ! Declare variables
    integer :: index
    integer, intent(in), value :: N
    real,shared,dimension(N) :: shared_array  

    ! Map threadID to index
    index = blockDim%x * (blockIdx%x-1) + threadIdx%x

    ! Set array element equal to index
    shared_array(index) = index

  end subroutine mykernel

end module my_kernels

以下是我调用内核的方式:

program cuda

  use my_kernels
  implicit none  

  ! Set number of threads
  integer :: N = 9

  ! Invoke kernel with 3 blocks of 3 threads
  call mykernel<<<N/3,3>>>(N)

end program cuda

我所有这一切都在一个文件test.cuf中。当我尝试使用pgf90编译test.cuf时,我收到此错误:

PGF90-S-0000-Internal compiler error. unexpected runtime function call       0 (test.cuf: 34)
PGF90-S-0000-Internal compiler error. unsupported procedure     349 (test.cuf: 34)
  0 inform,   0 warnings,   2 severes, 0 fatal for mykernel
/tmp/pgcudaforw5MgcaFALD9p.gpu(19): error: a value of type "int" cannot be assigned to an entity of type "float *"

/tmp/pgcudaforw5MgcaFALD9p.gpu(22): error: expected an expression

2 errors detected in the compilation of "/tmp/pgnvdl7MgHLY1VOV5.nv0".
PGF90-F-0000-Internal compiler error. pgnvd job exited with nonzero status code       0 (test.cuf: 34)
PGF90/x86-64 Linux 10.8-0: compilation aborted

在这种情况下,第34行引用end subroutine mykernel。编译器错误不是很有用,我花了一段时间才发现问题与共享数组有关(我使用这段代码作为一个简单的例子)。

当我在共享数组的声明中将'N'替换为'9'以使real,shared,dimension(N) :: shared_array替换为real,shared,dimension(9) :: shared_array时,错误消失了。

我的问题是,为什么会出现此错误,如何使用变量设置共享数组的维度(如果可能的话)?

2 个答案:

答案 0 :(得分:1)

将“dimension(N)”更改为“dimension(*)”,然后传入共享数组的大小(以字节为单位)作为内核启动的第三个参数。

希望这有帮助,

% cat test.cuf 
module my_kernels

  use cudafor
  implicit none

  real, dimension(:), allocatable,device :: Ad
  real, dimension(:),allocatable :: Ah

contains

  attributes(global) subroutine mykernel(N)

    ! Declare variables
    integer :: index
    integer, intent(IN), value :: N
    real,shared,dimension(*) :: shared_array  

    ! Map threadID to index
    index = blockDim%x * (blockIdx%x-1) + threadIdx%x

    ! Set array element equal to index
    shared_array(index) = index

    Ad(index) = index

  end subroutine mykernel

end module my_kernels


program cuda

  use my_kernels
  implicit none  

  ! Set number of threads
  integer :: N = 9

   allocate(Ad(N), Ah(N))

  ! Invoke kernel with 3 blocks of 3 threads
  call mykernel<<<N/3,3,N*4>>>(N)

  Ah=Ad
  print *, Ah

end program cuda

% pgf90 test.cuf -V10.9 ; a.out
    1.000000        2.000000        3.000000        4.000000     
    5.000000        6.000000        7.000000        8.000000     
    9.000000 

答案 1 :(得分:1)

您可以拥有多个共享内存数组,但必须在编译时知道它们的大小。 通常,共享内存数组应该是固定大小的,在运行时可以传递大小以字节为单位的情况有点特殊。 我想这都是由于SM(流多处理器)中共享内存的限制。 根据我的经验,在CUDA C和CUDA中开发fortran最好让所有这些参数“固定”,然后让内核重复工作所需的次数以覆盖所有输入数据,这样我就更容易控制所有的paarmeters影响占用率(您使用GPU中所有物理资源的程度)。