2016-02-25 34 views
0

我正在使用OpenACC处理相当大的代码。现在,我有一个程序foo的调用其他几个例程酒吧,远远的,嘘delaing,就像这样:如何在OpenACC数据区域中创建子例程

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进行测试。

我目前专注于“酒吧”的电话。我想让酒吧成为一个向量例程。我还没有准备好做同样的事情。所以我想在一个平行区域内打电话给酒吧,但我还没有准备好做同样的事情。 (我说这是一项正在进行的工作,对吧?)现在,我可以 - 我想! - 在它自己的并行区域三明治吧和数据复制到和它在每次循环迭代

!$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

让外部数据区跨越“i”循环。正如你所知道的那样,你在开始之后直接“结束数据”,所以x,y和z在“i”循环之前被删除并且不存在。我还建议在循环中使用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”中可能会更好,因此您可以同时使用“gang”和“vector”。当然,如果你的意图是稍后将内部“平行”区域移动到“我”循环周围的“并行循环帮派”,那么将它保持原样是有意义的。

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