2016-02-25 63 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指令以同步主機和設備副本。