2017-12-25 14 views
1

私はサブルーチンcompoundretの計算時間を高速化することに興味があります。これは基本的に、ある保持期間、例えば1ヶ月、3ヶ月、6ヶ月などの月間リターン系列を複合します。 私はこのサブルーチンをRからdll 。私は、Fortranで動作するすべてのものを取得するために、付属のコードスニペットに主要な関数を書いています。私のターゲットプラットフォームは、コンピューティングデバイス6.0(GTX 1060)である これ以上スピードアップできますか?

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) 

エンドプログラム。

+1

これはCUDAではなくOpenACC – Chiel

+0

@Chiel OpenACCコードですが、ループ内のすべてをCuda Fortranカーネル経由でGPUにロードすることは大したことではありません。 –

+0

一時配列の割り当てにかかる時間と、GPUへのメモリ転送に要する時間を確認します。 –

答えて

1

2つの外側ループを折りたたみ、 "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 Community Editionを使用している場合は、4月に18.4コンパイラを待つ必要があります。

共有ライブラリまたは動的ライブラリにOpenACCを置くには、 "-ta = tesla:nordc"オプションを使用する必要があります。

関連する問題