如何使子例程在OpenACC数据区域中工作

时间:2016-02-25 18:59:08

标签: fortran90 openacc

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

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做同样的事情。 (我说这是一项正在进行中的工作,对吗?)现在,我可以 - 我想! - 将三明治条放在其自己的并行区域中,并在每次循环迭代中将数据复制到其中或从中复制数据

!$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 create以及data copyin。)

那么有没有办法做我想做的事情?感谢。

1 个答案:

答案 0 :(得分:1)

让外部数据区域跨越“i”循环。如你所知,你在开始之后直接有“结束数据”,因此在“i”循环之前删除x,y和z并且不存在。我还建议在循环中使用update子句来管理数据传输。类似的东西:

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

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