0

GCC O2 수준의 최적화를 사용하여 PC386 시스템에 편집증 부동 소수점 테스트 슈트를 컴파일하고 몇 가지 실패가 있었지만 동일한 GCC를 사용하지 않고 최적화하지 않고 올바른 결과를 얻었습니다. O2에서 활성화 된 플래그에 대해서는 읽었지만 아무 것도 문제가없는 것으로 보입니다. 원인은 무엇일까요? 편집증 코드는 here를 찾을 수 있으며이 O2 최적화와 함께 찍은 출력 :gp O2 플래그로 인해 fp 계산에 실패가 발생할 수 있습니까?

*** PARANOIA TEST *** 
paranoia version 1.1 [cygnus] 
Program is now RUNNING tests on small integers: 
TEST: 0+0 != 0, 1-1 != 0, 1 <= 0, or 1+1 != 2 
PASS: 0+0 != 0, 1-1 != 0, 1 <= 0, or 1+1 != 2 
TEST: 3 != 2+1, 4 != 3+1, 4+2*(-2) != 0, or 4-3-1 != 0 
PASS: 3 != 2+1, 4 != 3+1, 4+2*(-2) != 0, or 4-3-1 != 0 
TEST: -1+1 != 0, (-1)+abs(1) != 0, or -1+(-1)*(-1) != 0 
PASS: -1+1 != 0, (-1)+abs(1) != 0, or -1+(-1)*(-1) != 0 
TEST: 1/2 + (-1) + 1/2 != 0 
PASS: 1/2 + (-1) + 1/2 != 0 
TEST: 9 != 3*3, 27 != 9*3, 32 != 8*4, or 32-27-4-1 != 0 
PASS: 9 != 3*3, 27 != 9*3, 32 != 8*4, or 32-27-4-1 != 0 
TEST: 5 != 4+1, 240/3 != 80, 240/4 != 60, or 240/5 != 48 
PASS: 5 != 4+1, 240/3 != 80, 240/4 != 60, or 240/5 != 48 
-1, 0, 1/2, 1, 2, 3, 4, 5, 9, 27, 32 & 240 are O.K. 

Searching for Radix and Precision. 
Radix = 2.000000 . 
Closest relative separation found is U1 = 5.4210109e-20 . 

Recalculating radix and precision 
confirms closest relative separation U1 . 
Radix confirmed. 
TEST: Radix is too big: roundoff problems 
PASS: Radix is too big: roundoff problems 
TEST: Radix is not as good as 2 or 10 
PASS: Radix is not as good as 2 or 10 
TEST: (1-U1)-1/2 < 1/2 is FALSE, prog. fails? 
ERROR: Severity: FAILURE: (1-U1)-1/2 < 1/2 is FALSE, prog. fails?. 
PASS: (1-U1)-1/2 < 1/2 is FALSE, prog. fails? 
TEST: Comparison is fuzzy,X=1 but X-1/2-1/2 != 0 
PASS: Comparison is fuzzy,X=1 but X-1/2-1/2 != 0 
The number of significant digits of the Radix is 64.000000 . 
TEST: Precision worse than 5 decimal figures 
PASS: Precision worse than 5 decimal figures 
TEST: Subtraction is not normalized X=Y,X+Z != Y+Z! 
PASS: Subtraction is not normalized X=Y,X+Z != Y+Z! 
Subtraction appears to be normalized, as it should be. 
Checking for guard digit in *, /, and -. 
TEST: * gets too many final digits wrong. 

PASS: * gets too many final digits wrong. 

TEST: Division lacks a Guard Digit, so error can exceed 1 ulp 
or 1/3 and 3/9 and 9/27 may disagree 
PASS: Division lacks a Guard Digit, so error can exceed 1 ulp 
or 1/3 and 3/9 and 9/27 may disagree 
TEST: Computed value of 1/1.000..1 >= 1 
PASS: Computed value of 1/1.000..1 >= 1 
TEST: * and/or/gets too many last digits wrong 
PASS: * and/or/gets too many last digits wrong 
TEST: - lacks Guard Digit, so cancellation is obscured 
ERROR: Severity: SERIOUS DEFECT: - lacks Guard Digit, so cancellation is obscured. 
PASS: - lacks Guard Digit, so cancellation is obscured 
Checking rounding on multiply, divide and add/subtract. 
TEST: X * (1/X) differs from 1 
PASS: X * (1/X) differs from 1 
* is neither chopped nor correctly rounded. 
/is neither chopped nor correctly rounded. 
TEST: Radix * (1/Radix) differs from 1 
PASS: Radix * (1/Radix) differs from 1 
TEST: Incomplete carry-propagation in Addition 
PASS: Incomplete carry-propagation in Addition 
Addition/Subtraction neither rounds nor chops. 
Sticky bit used incorrectly or not at all. 
TEST: lack(s) of guard digits or failure(s) to correctly round or chop 
(noted above) count as one flaw in the final tally below 
ERROR: Severity: FLAW: lack(s) of guard digits or failure(s) to correctly round or chop 
(noted above) count as one flaw in the final tally below. 
PASS: lack(s) of guard digits or failure(s) to correctly round or chop 
(noted above) count as one flaw in the final tally below 

Does Multiplication commute? Testing on 20 random pairs. 
    No failures found in 20 integer pairs. 

Running test of square root(x). 
TEST: Square root of 0.0, -0.0 or 1.0 wrong 
PASS: Square root of 0.0, -0.0 or 1.0 wrong 
Testing if sqrt(X * X) == X for 20 Integers X. 
Test for sqrt monotonicity. 
ERROR: Severity: DEFECT: sqrt(X) is non-monotonic for X near 2.0000000e+00 . 
Testing whether sqrt is rounded or chopped. 
Square root is neither chopped nor correctly rounded. 
Observed errors run from -5.5000000e+00 to 5.0000000e-01 ulps. 
TEST: sqrt gets too many last digits wrong 
ERROR: Severity: SERIOUS DEFECT: sqrt gets too many last digits wrong. 
PASS: sqrt gets too many last digits wrong 
Testing powers Z^i for small Integers Z and i. 
ERROR: Severity: DEFECT: computing 
     (1.30000000000000000e+01)^(1.70000000000000000e+01) 
     yielded 8.65041591938133811e+18; 
     which compared unequal to correct 8.65041591938133914e+18 ; 
       they differ by -1.02400000000000000e+03 . 
Errors like this may invalidate financial calculations 
     involving interest rates. 
Similar discrepancies have occurred 5 times. 
Seeking Underflow thresholds UfThold and E0. 
ERROR: Severity: FAILURE: multiplication gets too many last digits wrong. 
Smallest strictly positive number found is E0 = 0 . 
ERROR: Severity: FAILURE: Either accuracy deteriorates as numbers 
approach a threshold = 0.00000000000000000e+00 
coming down from 0.00000000000000000e+00 
or else multiplication gets too many last digits wrong. 

The Underflow threshold is 0.00000000000000000e+00, below which 
calculation may suffer larger Relative error than merely roundoff. 
Since underflow occurs below the threshold 
UfThold = (2.00000000000000000e+00)^(-inf) 
only underflow should afflict the expression 
     (2.00000000000000000e+00)^(-inf); 
actually calculating yields: 0.00000000000000000e+00 . 
This computed value is O.K. 

Testing X^((X + 1)/(X - 1)) vs. exp(2) = 7.38905609893065041e+00 as X -> 1. 
ERROR: Severity: DEFECT: Calculated 1.00000000000000000e+00 for 
     (1 + (0.00000000000000000e+00)^(inf); 
     differs from correct value by -6.38905609893065041e+00 . 
     This much error may spoil financial 
     calculations involving tiny interest rates. 
Testing powers Z^Q at four nearly extreme values. 
... no discrepancies found. 

Searching for Overflow threshold: 
This may generate an error. 
Can `Z = -Y' overflow? 
Trying it on Y = -inf . 
finds a ERROR: Severity: FLAW: -(-Y) differs from Y. 
Overflow threshold is V = -inf . 
Overflow saturates at V0 = inf . 
No Overflow should be signaled for V * 1 = -inf 
          nor for V/1 = -inf . 
Any overflow signal separating this * from the one 
above is a DEFECT. 
ERROR: Severity: FAILURE: Comparisons involving +--inf, +-inf 
and +-0 are confused by Overflow. 
ERROR: Severity: SERIOUS DEFECT: X/X differs from 1 when X = 1.00000000000000000e+00 
    instead, X/X - 1/2 - 1/2 = 1.08420217248550443e-19 . 
ERROR: Severity: SERIOUS DEFECT: X/X differs from 1 when X = -inf 
    instead, X/X - 1/2 - 1/2 = nan . 
ERROR: Severity: SERIOUS DEFECT: X/X differs from 1 when X = 0.00000000000000000e+00 
    instead, X/X - 1/2 - 1/2 = nan . 

What message and/or values does Division by Zero produce? 
    Trying to compute 1/0 produces ... inf . 

    Trying to compute 0/0 produces ... nan . 

The number of FAILUREs encountered =  4. 
The number of SERIOUS DEFECTs discovered = 5. 
The number of DEFECTs discovered =   3. 
The number of FLAWs discovered =   2. 

The arithmetic diagnosed has unacceptable Serious Defects. 
Potentially fatal FAILURE may have spoiled this program's subsequent diagnoses. 
END OF TEST. 
*** END OF PARANOIA TEST *** 

EXECUTIVE SHUTDOWN! Any key to reboot... 
+3

오류의 세부 정보와 관련 코드를 제공하는 것이 더 나은 질문이 될 것이라고 생각합니다. 'gcc '버전 번호를 아는 것은 아무런 해가되지 않을 것입니다. – NPE

+2

물론 SSCCE (http://sscce.org/)에 대한 하나 이상의 실패를 줄일 수 있다면 더 좋을 것입니다. – NPE

+0

최신 하드웨어의 GCC의 최신 버전은'-msse2 -mfpmath = sse' 옵션을 이용하여 각 표현식을 정확하게 유형의 정밀도로 계산하는 어셈블리를 생성 할 수 있습니다. 이 설명의 관점에서 편집증의 소스 코드를 보는 것은 유익 할 수도 있습니다 : http://gcc.gnu.org/ml/gcc-patches/2008-11/msg00105.html. 최근의 GCC가 아직 부동 소수점에 대해 엄격한 IEEE 754 코드를 생성하지 않았다면,'-std = c99' 또는'-fexcess-precision = standard'는 생성 된 어셈블리를 Joseph S. Myers가 제시 한 해석과 일치하게 만듭니다. –

답변

3

최적화와 -O2 여기에 주요 원인이 아니다. 실행중인 테스트 스위트는 다른 최적화 시나리오와 함께 C 구현에서 실패 할 수 있습니다. 이 경우의 주요 문제는 편집증 테스트가 부동 소수점 산술의 일관성과 다양한 속성을 테스트하는지 테스트하는 것입니다. 그러나 C 구현의 부동 소수점 산술은 일관성이 없습니다. 가끔씩 80 비트를 사용하기 때문입니다 64 비트 산술 (또는 근사값, 예를 들어 80 비트 산술을 사용하지만 결과를 64 비트 부동 소수점으로 반올림)을 사용하는 경우도 있습니다.

는 우선, 테스트는 1-U11 상이 U1되도록들을 발견하고 1-U11 사이 표현할 값은 없다. 즉, U11에서 부동 소수점 형식의 다음 표현 가능 값까지의 단계 크기입니다. 귀하의 경우, 테스트 결과 U1은 약 5.4210109e-20입니다. 이 U1은 정확히 2 -64입니다. 실행중인 Intel 프로세서에는 유효 숫자 (부동 소수점 표현의 일부)가 64 비트 인 80 비트 부동 소수점 형식이 있습니다. 이 임시 값의 64 비트 폭은 2의 크기가 2 -64이되므로 U1이 2 -64 인 이유입니다.

나중에 시험은 (1-U1)-1/2을 평가하고 1/2과 비교합니다. 1-U1이 1보다 작으므로 1/2을 빼면 결과가 1/2 미만이됩니다. 그러나이 경우 C 구현은 62 비트 산술로 1-U1을 평가하며 53 비트 유효성을가집니다. 53 비트 유효 숫자를 사용하면 1-U1을 정확하게 나타낼 수 없습니다. 1에 가깝기 때문에 1-U1의 수학적 값은 64 비트 형식에서 1로 반올림됩니다. 그런 다음이 1에서 1/2을 빼면 1/2이됩니다. 이 1/2은 1/2보다 작지 않으므로 비교가 실패하고 프로그램에서 오류를보고합니다.

이것은 C 구현의 결함입니다. 실제로 1-U1을 다른 위치에서 한 위치에서 다르게 평가합니다. 한 곳에서는 80 비트 산술 연산을 사용하고 다른 곳에서는 64 비트 산술 연산을 사용하며이를 제어하는 ​​좋은 방법은 제공하지 않습니다. (그러나 64 비트 산술만을 사용하는 스위치가있을 수도 있지만 사용중인 GCC의 버전을 알지 못합니다.)

좋은 부동 소수점 연산을 원하는 사람들의 표준에 의한 결함이지만, C 표준에 따른 결함. C 언어 표준은이 동작을 허용합니다.

첫 번째 이후에보고 된 실패를 조사하지 않았습니다. 그들은 비슷한 원인에서 기인 한 것 같습니다.

+0

GCC 버전은 4.4.7입니다. 최적화가 부동 소수점 정밀도를 변경합니까? 그렇다면 왜 최적화를하지 않고 컴파일하면 정답이 생기는가? –

+0

@ArdalanPouyabahar 구형 GCC 버전은 최적화가 있거나없는 부동 소수점 계산으로 동일한 결과가 생성되는 것을 보장하지 않습니다. 런타임 시맨틱과는 다른 시맨틱을 사용하여 컴파일 타임에 간단한 계산을 수행 할 수 있습니다. 이런 종류의 컴파일러로 예측 부동 소수점 동작의 어려움에 대한보다 완전한 보고서를 보려면 http://arxiv.org/abs/cs/0701192를 참조하십시오. http://blog.frama-c.com/index.php ? post/2013/07/06/FLT_EVAL_METHOD-2 및 http://blog.frama-c.com/index.php?post/2013/07에 대한 C 프로그램에 대한 정확한 분석/24/More-on-FLT_EVAL_METHOD_2 –

+0

@ PascaCuoq 링크가 도움이되었지만 4.4.7 버전이 2012 버전인지 확인했을 때 문제가 너무 많습니까? –

관련 문제