【问题标题】:fortran openacc derived types with allocatable具有可分配的 fortran openacc 派生类型
【发布时间】:2017-08-08 19:28:03
【问题描述】:

我阅读了 Fortran 派生类型的手动深度复制是可能的,但是以下简单的测试程序在运行时失败;使用 PGI v16.10 干净编译的程序。出了什么问题?

program Test

    implicit none

    type dt
        integer :: n
        real, dimension(:), allocatable :: xm
    end type dt

    type(dt) :: grid
    integer :: i

    grid%n = 10
    allocate(grid%xm(grid%n))

!$acc enter data copyin(grid)
!$acc enter data pcreate(grid%xm)

!$acc kernels
   do i = 1, grid%n
      grid%xm(i) = i * i
   enddo
!$acc end kernels

   print*,grid%xm

end program Test

我得到的错误是:

call to cuStreamSynchronize returned error 700: Illegal address during kernel execution
call to cuMemFreeHost returned error 700: Illegal address during kernel execution

【问题讨论】:

  • 根据文档(PGI openacc 指南,v2015 和 v2017):派生类型的数组,其中派生类型包含可分配的成员,未经测试,不应被视为此版本支持。 stackoverflow.com/questions/45233207/…
  • 原来注释掉pcreate(grid%xm)的创建可以让程序正常运行。这是否意味着现在支持深度复制?
  • “尚未经过测试,不应被视为支持”...用于数组的位。您只有一个变量,所以我不知道,请尝试在手册中搜索。

标签: fortran gpu openacc pgi


【解决方案1】:

您只需要在 kernels 指令上添加一个“present(grid)”子句。

这是您的程序示例,其中包含修复程序以及其他一些内容,例如更新数据以便可以在主机上打印。

% cat test.f90
program Test

    implicit none

    type dt
        integer :: n
        real, dimension(:), allocatable :: xm
    end type dt

    type(dt) :: grid
    integer :: i

    grid%n = 10
    allocate(grid%xm(grid%n))

!$acc enter data copyin(grid)
!$acc enter data create(grid%xm)
!$acc kernels present(grid)
   do i = 1, grid%n
      grid%xm(i) = i * i
   enddo
!$acc end kernels
!$acc update host(grid%xm)
   print*,grid%xm

!$acc exit data delete(grid%xm, grid)
   deallocate(grid%xm)

end program Test

% pgf90 -acc test.f90 -Minfo=accel -ta=tesla -V16.10; a.out
test:
     16, Generating enter data copyin(grid)
     17, Generating enter data create(grid%xm(:))
     18, Generating present(grid)
     19, Loop is parallelizable
         Accelerator kernel generated
         Generating Tesla code
         19, !$acc loop gang, vector(128) ! blockidx%x threadidx%x
     23, Generating update self(grid%xm(:))
    1.000000        4.000000        9.000000        16.00000
    25.00000        36.00000        49.00000        64.00000
    81.00000        100.0000

请注意,PGI 17.7 将在 Fortran 中包含对真正深拷贝的 beta 支持。与您上面的手动深层复制相反。下面是一个使用真正深拷贝的例子:

% cat test_deep.f90
program Test

    implicit none

    type dt
        integer :: n
        real, dimension(:), allocatable :: xm
    end type dt

    type(dt) :: grid
    integer :: i

    grid%n = 10
    allocate(grid%xm(grid%n))

!$acc enter data copyin(grid)
!$acc kernels present(grid)
   do i = 1, grid%n
      grid%xm(i) = i * i
   enddo
!$acc end kernels
!$acc update host(grid)
   print*,grid%xm

!$acc exit data delete(grid)
   deallocate(grid%xm)

end program Test

% pgf90 -acc test_deep.f90 -Minfo=accel -ta=tesla:deepcopy -V17.7 ; a.out
test:
     16, Generating enter data copyin(grid)
     17, Generating present(grid)
     18, Loop is parallelizable
         Accelerator kernel generated
         Generating Tesla code
         18, !$acc loop gang, vector(128) ! blockidx%x threadidx%x
     22, Generating update self(grid)
    1.000000        4.000000        9.000000        16.00000
    25.00000        36.00000        49.00000        64.00000
    81.00000        100.0000

【讨论】:

  • Mat,非常感谢,我将使用深拷贝。即使在 v17.7 中,为什么现在的条款也是必要的?不应该隐式复制/存在网格,我希望在使用没有数据子句的内核区域时发生这种情况,同样可以正常工作吗?再次感谢!
  • 我认为这是一个错误,因为你是正确的,深拷贝隐式拷贝应该可以工作。授予的深拷贝是新的和 beta 功能,因此这些类型的问题并不意外。
猜你喜欢
  • 2020-03-17
  • 2014-10-18
  • 1970-01-01
  • 2012-10-23
  • 2019-03-02
  • 2023-03-13
  • 1970-01-01
  • 2018-11-15
  • 2017-08-12
相关资源
最近更新 更多