0

我正在使用 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 成为向量例程。我还没有准备好为 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。)

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

4

1 回答 1

2

让外部数据区域跨越“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”,然后添加更新指令以同步主机和设备副本。

于 2016-02-25T22:07:48.257 回答