2017-04-11 10 views
4

내가 알고있는 증식하는 적절한 방법 또는 내가실수로 멀티플렉싱 할 때 언더 플로가 발생하지 않도록하려면 어떻게해야합니까? <code>underflow</code> 옵션이 아니라고

gfortran -ffpe-trap=invalid,zero,overflow,underflow ... 

처럼 내 포트란 코드를 컴파일 할 때 언더 플로우 에러를하지 않고 함께 광장 플로트 (또는 더블) 번호가 있는지 알고 싶습니다 항상 좋은 생각이지만이 옵션으로 곱셈을 할 수 있는지 궁금합니다. 사실, 다음 예제에서 나는 언더 플로우가 발생할 수 있지만 어쩌면 나는 코드에있는 다른 사례를 알지 못한다는 것을 안다. 이것이 가능한 경우이 옵션을 유지하려는 이유입니다.

다음은 행렬의 x, y 인덱스마다 벡터 u를 계산하는 예입니다. 이 벡터를 구성하는 2 개의 값은 0과 1 사이에 있습니다. 그리고 나는 그 표준의 제곱을 계산합니다.

매우 논리적이므로이 사각형 연산 때문에 값이 언더 플로우됩니다. 이후,이 아주 작은 값은 제로라고 생각할 수 있습니다. if 비교를 사용하는 것보다 underflow이 더 좋은 방법이 아닌가요?

implicit none 
double :: u(100,100,2), uSqr(100,100) 
integer :: x,y 

DO x= 1, 100 
    DO y = 1, 100 
       CALL Poisin(u(x,y,:), x, y) 
    ENDDO 
ENDDO 

uSqr = u(:,:,1)*u(:,:,1) + u(:,:,2) * u(:,:,2) ! where comes the underflow errors 
+1

언더 플로가 발생하지 않도록 하시겠습니까? 아니면 언더 플로우가 오류 상태가되는 것을 방지 하시겠습니까? – francescalus

+0

파일 단위로'-ffpe-trap' 옵션을 설정할 수 없습니까? 그렇다면 위의 인용 부분을 하나의 소스 파일로 분리하고'-ffpe-trap' 목록에서'underflow'를 생략하여 다른 소스 파일에 대한 원래 예외 트랩 목록을 유지하면서이 파일을 컴파일 할 수 있습니다. 나는 당신이'uSqr' 값의 언더 플로우에도 불구하고 그것들을 0으로 간주 함으로서 프로그램이 계속 진행되도록하고 싶다고 가정합니다. – norio

+0

두 번째 @ francescalus의 덧글이 있어야합니다. 계산을 유지하면서 오류없이 종료하겠습니까?왜 당신은'언더 플로'를 걸고 싶습니까? '언더 플로우'를 포착하지 않는 것이 진지한 생각이다. 내 의견으로는 그것은 꽤 쓸모 없거나 해롭다. –

답변

3

특정 상황에서는 이 부당한을 피하는 구체적인 방법을 찾는 답이 있습니다. 이 기능은 hypot 기능을 사용합니다. 이것은 부분적으로 답입니다. 언더 플로를 피하려면 알고리즘을 다시 작성하여이를 피할 수있는 방법이있을 수 있습니다.

예외 플래그를 정밀하게 제어하려는 경우 (예 :이 질문과 같이) 적합하지 않은 일반적인 경우 그러나 컴파일러는 종종 예외 처리 루틴에 대한 인터페이스를 제공합니다.

은 포트란 2003 년 IEEE 기능을 사용하고이 일을 한 휴대용 방법 [당신이 적어도 버전 5.0이 필요합니다,하지만 가능한 유사한 컴파일러 구체적인 방법이 있습니다 gfortran를 사용하는 경우.]

포트란은 IEEE를 정의 예외 및 플래그. 플래그는 신호음이나 신호음 일 수 있습니다. 언더 플로우가 그 계산 후에 언더 플로우 플래그 상태에 영향을 미치지 않는 유용한 진단이 아닌 부분에 대한 것이 있습니다.

이 플래그는 IEEE_UNDERFLOW으로 알려져 있습니다. 서브 루틴 IEEE_GET_FLAG(IEEE_UNDERFLOW, value)IEEE_SET_FLAG(IEEE_UNDERFLOW, value)을 사용하여 상태를 쿼리하고 설정 할 수 있습니다. 언더 플로우가 예상되지만 걱정하지 않으려는 경우 예외가 중단되지 않도록해야합니다. 서브 루틴 IEEE_SET_HALTING_MODE(IEEE_UNDERFLOW, value)이이 모드를 제어합니다.

주석이 달린 예입니다.

use, intrinsic :: ieee_arithmetic, only : IEEE_SELECTED_REAL_KIND 
    use, intrinsic :: ieee_exceptions 

    implicit none 

    ! We want an IEEE kind, but this doesn't ensure support for underflow control 
    integer, parameter :: rk=IEEE_SELECTED_REAL_KIND(6, 70) 

    ! State preservation/restoration 
    logical should_halt, was_flagged 

    real(rk) x 

    ! Get the original halting mode and signal state 
    call ieee_get_halting_mode(IEEE_UNDERFLOW, should_halt) 
    call ieee_get_flag(IEEE_UNDERFLOW, was_flagged) 

    ! Ensure we aren't going to halt on underflow 
    call ieee_set_halting_mode(IEEE_UNDERFLOW, .FALSE.) 

    ! The irrelevant computation 
    x=TINY(x) 
    x=x**2 

    ! And restore our old state 
    call ieee_set_halting_mode(IEEE_UNDERFLOW, should_halt) 
    call ieee_set_flag(IEEE_UNDERFLOW, was_flagged) 

end program 
+0

귀하의 대답은 매우 적합합니다. 나는 이번 주말에 집에서 시험 할 것이고 나는 당신의 답을 검증 할 것입니다. –

1

는 어쩌면 당신이 hypot을 사용하려는 또는 당신이 정말로 빗변의 제곱이 필요합니까 언더 플로우를 피하기 위해 그냥 경우?

구현시 hypotsqrt(x**2+y**2)의 오버플로/언더 플로 문제를 방지해야합니다.

+0

당신은 맞습니다. 저는 항상 오버 플로우 문제 만 고려했습니다.하지만 같은 방식으로 언더 플로가 발생하지 않도록해야합니다. –

+0

'hypot' 팁을 주셔서 감사합니다. 그러나 저는 정말로 빗변의 사각형이 필요합니다. –

+0

@Romain 그래서 hypot의 제곱을 계산하면 문제는 ... 언더 플로우가 발생하면 피할 수없는 것입니다. –