【问题标题】:How to make a subroutine work in an OpenACC data region如何使子例程在 OpenACC 数据区域中工作
【发布时间】:2016-02-26 06:07:48
【问题描述】:

我正在使用 OpenACC 检测相当大的代码。现在,我正在处理一个调用其他一些例程 bar、far 和 boo 的例程 foo,如下所示:

subroutine foo

real x(100,25),y(100,25),z(100,25)
real barout(25), farout(25), booout(25)

do i=1,25
  call bar(barout, x(1,i),y(1,i),z(1,i))
  call far(farout, x(1,i),y(1,i),z(1,i))
  call boo(booout, x(1,i),y(1,i),z(1,i))
enddo

....

end subroutine foo

几个点:1) x、y 和 z 在循环中保持不变。 2) 你可能不喜欢这里的代码结构,但这超出了我的工作描述。我应该使用 OpenACC 进行检测,期间。

我目前正专注于对“bar”的调用。我想让 bar 成为向量例程。我还没有准备好为 far 和 boo 做同样的事情。所以我想在一个平行区域内调用 bar,但我还没有准备好对 far 和 boo 做同样的事情。 (我说这是一项正在进行的工作,对吗?)现在,我可以——我想! -- 在自己的并行区域中夹层条,并在每次循环迭代中向其中复制数据

!$acc data copy(barout) &
!$acc&     copyin(x(:,:),y(:,:),z(:,:))
!$acc parallel
call bar( .... )
!$acc en parallel
!$acc end data

但这是大量的数据传输。如果我可以只将 x、y 和 z 传输到设备一次,那就太好了。每个例程都有自己的数据区域,所以据我了解(如果我错了,请纠正我!)我不能将整个循环包含在单个数据区域中。这是我尝试过的替代方法

subroutine foo
!$acc routine(bar) vector

real x(100,25),y(100,25),z(100,25)
real barout(25), farout(25), booout(25)

!$acc data create(x(:,:),y(:,:),z(:,:))
!$acc end data
do i=1,25
!$acc data copy(barout(:)) &
!$acc&     present(x(:,:),y(:,:),z(:,:))
!$acc parallel
  call bar(barout, x(1,i),y(1,i),z(1,i))
!$acc end parallel
!$acc end data
  call far(farout, x(1,i),y(1,i),z(1,i))
  call boo(booout, x(1,i),y(1,i),z(1,i))
enddo

....

end subroutine foo

但这不起作用,因为copyin 中的数据不会保留在设备上。当data present 子句出现时,它就消失了。 (我试过data createdata copyin。)

那么有没有办法做我在这里想做的事情?谢谢。

【问题讨论】:

    标签: fortran90 openacc


    【解决方案1】:

    让外部数据区域跨越“i”循环。正如你所拥有的,你在开始之后直接有“结束数据”,所以 x、y 和 z 在“i”循环之前被删除并且不存在。我还建议在循环中使用更新子句来管理数据传输。比如:

    subroutine foo
    !$acc routine(bar) vector
    
    real x(100,25),y(100,25),z(100,25)
    real barout(25), farout(25), booout(25)
    
    !$acc data copyin(x, y, z), create(barout)
    do i=1,25
    !$acc update device(barout)
    !$acc parallel
      call bar(barout, x(1,i),y(1,i),z(1,i))
    !$acc end parallel
    !$acc update host(barout)
      call far(farout, x(1,i),y(1,i),z(1,i))
      call boo(booout, x(1,i),y(1,i),z(1,i))
    enddo
    !$end data
    ....
    
    end subroutine foo
    

    注意事项:

    由于“bar”是一个向量例程,从“并行”区域调用它意味着您将只使用一个 gang。这不是错误的代码,但你会失去性能。最好将其保留为主机例程,然后将“parallel”放在“bar”中,这样​​您就可以同时使用“gang”和“vector”。当然,如果您的意图是稍后将内部“并行”区域移动到“i”循环周围的“并行循环组”,那么保持原样是有意义的。

    我将您的代码更改为复制 x、y 和 z,因为我不确定这些变量的初始化位置。如果它们在“bar”中初始化,您可以将它们改回使用“create”,然后添加更新指令以同步主机和设备副本。

    【讨论】:

      猜你喜欢
      • 2020-08-08
      • 2015-01-08
      • 1970-01-01
      • 1970-01-01
      • 2020-12-18
      • 2022-01-20
      • 1970-01-01
      • 1970-01-01
      • 2016-05-01
      相关资源
      最近更新 更多