2017-12-25 42 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

두 개의 외부 루프를 축소 한 다음 "!"acc 루프 벡터를 "t"루프에 추가하는 것이 좋습니다.

!$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"옵션을 사용해야합니다.