我有兴趣加快子程序复合计算的计算时间,它基本上会在一些持有期间(比如一个月,三个月,六个月等)构成一个月回报系列。 我将把这个子程序从R称为dll。我在附加的代码片段中编写了一个main函数,以便在fortran中使用所有内容。
subroutine compoundret(R_c, R, RF, horizons, Tn, N, M)
implicit none
! Arguments declarations
integer, intent(in) :: horizons(M), Tn, N, M
real*8, intent(in) :: RF(Tn), R(Tn, N, M)
real*8, intent(out) :: R_c(Tn, N, M)
! Intermediary Variables
integer :: t, j, k
real*8 :: RF_Temp(Tn, N, M)
R_c = 0.0
do t = 1, Tn
RF_Temp(t,:,:) = RF(t)
end do
!$acc data copyin(r(Tn,N,M), RF_Temp(Tn,N,M), horizons(M)), create(R_c(Tn,
N, M))
!$acc parallel loop
do k = 1, M
do j = 1, N
do t = 1, Tn - horizons(k) + 1
R_c( t, j, k) = PRODUCT( 1 + R( t:t + horizons(k) - 1, j, k) + &
RF_Temp( t:t + horizons(k) - 1, j, k)) - &
PRODUCT(1+ RF_Temp( t:t + horizons(k) - 1, j, k))
end do
end do
end do
!$acc end parallel
!$acc update host(R_c)
!$acc end data
end subroutine compoundret
Program main
implicit none
real*8 :: df(1000,5000, 6)
real*8 :: retdata(size(df,1),size(df,2),size(df,3)),RF(size(df,1))
integer :: horizons(6), Tn, N, M
Tn = size(df, 1)
N = size(df, 2)
M = size(df, 3)
df = 0.001
RF = 0.001
horizons(:) = (/1,3,6,12,24,48/)
call compoundret(retdata,df,RF,horizons, Tn, N, M)
print*, retdata(1, 1, 1:M)
结束程序 我的目标平台是一个计算6.0设备(GTX 1060)。
答案 0 :(得分:1)
我建议折叠两个外部循环,然后在“t”循环上添加“!$ acc loop vector”。
!$acc parallel loop collapse(2)
do k = 1, M
do j = 1, N
!$acc loop vector
do t = 1, Tn - horizons(k) + 1
R_c( t, j, k) = PRODUCT( 1 + R( t:t + horizons(k) - 1, j, k) + &
RF_Temp( t:t + horizons(k) - 1, j, k)) - &
PRODUCT(1+ RF_Temp( t:t + horizons(k) - 1, j, k))
end do
end do
end do
!$acc end parallel
现在,你只是在外部循环并行化,因为“M”非常小,所以你的GPU使用率不高。
请注意,PGI 2017编译器有一个错误,它会阻止您在DLL中使用OpenACC(Linux上的共享对象很好)。我们正在努力在18.1编译器中修复此问题。你现在的选择是等到明年初发布18.1或者回到16.10编译器。如果您正在使用PGI社区版,那么您需要等待4月份的18.4编译器。
此外,将OpenACC放在共享库或动态库中需要使用“-ta = tesla:nordc”选项。