【问题标题】:How to allocate arrays of arrays in structure with CUDA Fortran?如何使用 CUDA Fortran 在结构中分配数组?
【发布时间】:2017-11-24 14:19:33
【问题描述】:

使用 CUDA,我试图在结构中分配数组,但我遇到了问题,我不知道为什么。所以这里有一个描述我的问题的短代码(存储在一个名为struct.cuf 的文件中)。我正在使用PGI 16.10 version 进行编译,并且正在使用以下选项:-O3 -Mcuda=cc60 -tp=x64 struct.cuf -o struct_out

module structure
contains

type mytype
 integer :: alpha,beta,gamma
 real,dimension(:),pointer :: a
end type mytype

type mytypeDevice
 integer :: alpha,beta,gamma
 real,dimension(:),pointer,device :: a
end type mytypeDevice

end module structure

program main
 use cudafor
 use structure

 type(mytype) :: T(3)
 type(mytypeDevice),device :: T_Device(3)

 ! For the host
 do i=1,3
  allocate(T(i)%a(10))
 end do
 T(1)%a=1; T(2)%a=2; T(3)%a=3

 ! For the device
 print *, 'Everything from now is ok'
 do i=1,3
  allocate(T_Device(i)%a(10))
 end do
 !do i=1,3
 ! T_Device(i)%a=T(i)%a
 !end do

end program main

输出错误:

 Everything from now is ok
Segmentation fault     

我在这里做错了什么?

我发现(并且有效)的唯一解决方案是将值存储在不同的数组中并将它们传输到 GPU,但它非常“重”。大多数情况下,如果我使用很多像 mytype 这样的结构。

编辑:代码已修改为使用 Vladimir F 的解决方案。如果我从T_Device(3) 声明中删除device 属性,那么分配似乎没问题并且也给出了值(分配下方的注释行)。但我需要T_Device(3)device 属性,因为我将在内核中使用它。

谢谢!

【问题讨论】:

  • 来自pgroup.com/doc/pgi17cudaforug.pdf(Vladimir F 的链接):“派生类型的成员可能没有设备属性,除非它们是可分配的。”此外,您将“设备”属性同时赋予“a”和“T_Device”,从而形成嵌套的“设备”属性。这肯定会使您的问题复杂化:为“设备”属性设置一个级别。
  • 是的,它只适用于一个“设备”属性。但是如果我从T_Device(3) 中删除这个属性,我就不能在内核中使用T_Device(3)...

标签: arrays cuda fortran pgi


【解决方案1】:

我认为你需要一个设备指针

type mytype_device
 ...
 real,dimension(:),pointer, device :: a
end type

在我的生活中从未使用过 CUDA Fortran,但它似乎足以下注。

【讨论】:

  • 我也试过这个解决方案!但它不起作用,我得到同样的错误......顺便说一下,属性“指针”与fortran PGI中的属性“设备”不匹配,你必须使用“可分配”。
  • 您无法将pointer 用于设备这一事实的资源是什么?我查看了一些 PGI 演示文稿,他们使用了它。比如pgroup.com/doc/pgi17cudaforug.pdf中的2.12.3
  • 应始终首选可分配,但这是 Fortran 中的一般规则,而不是 CUDA。
  • 否则,如果您仍然有段错误,很明显我们需要minimal reproducible example。几行是不够的。准备一个完整且可编译的短代码和段错误。
  • 我的错,是的,pointer 属性也有效。我也试过了,但总是会导致同样的错误。明天我会准备一个简短的代码来强调我的问题,无论如何感谢您的关注!
【解决方案2】:

这里的问题是你如何声明T_Device。要使用主机端分配,您首先填充设备结构的 主机 内存副本,然后将其复制到设备内存。这个:

type(mytypeDevice) :: T_Device(3)

do i=1,3
  allocate(T_Device(i)%a(10))
 end do

将正常工作。这是基于C++的CUDA代码中非常标准的设计模式,这里的原理是一样的。

【讨论】:

  • 所以不应该有任何设备指针存储在设备派生类型中?因为如果我尝试(刚刚安装 PIG 社区)我会得到PGF90-S-0519-More than one device-resident object in assignment
  • @VladimirF:派生类型中没有设备指针。但是,当这些设备指针在主机代码中分配时,派生类型本身驻留在主机内存中。然后,您可以将该主机实例复制到设备内存中的一个实例。
  • 是的,我明白了。您的代码运行良好。但是,如果我想获得一个包含设备指针的结构体?我必须在内核中做这些事情吗?
  • 声明mytypeDevice的设备内存实例并从填充的主机内存实例复制到它
  • 这正是我正在尝试的。如果我有时间,我可能会就此提出一个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-03
  • 2018-12-26
  • 1970-01-01
  • 2018-09-21
  • 1970-01-01
  • 1970-01-01
  • 2021-12-05
相关资源
最近更新 更多