2008-09-26 4 views
6

릴리스 모드 및 디버그 모드로 컴파일 할 때 내 응용 프로그램이 다른 부동 소수점 값을 생성합니다. 내가 발견 한 유일한 이유는 바이너리 추적 로그를 저장하고 릴리스 빌드의 디버그 빌드가 디버그 빌드에서 약간 벗어 났기 때문에 32 비트 부동 소수점 값의 아래쪽 두 비트가 1/2 정도 차이가 나는 것처럼 보입니다. 케이스의.릴리스 및 디버그 빌드에서 다르게 동작하는 부동 값

이 "차이점"을 버그로 간주하거나 이러한 유형의 차이가 발생할 것으로 생각하십니까? 이것은 컴파일러 버그 또는 내부 라이브러리 버그일까요? 예를 들어

:

LEFTPOS and SPACING are defined floating point values. 
float def_x; 
int xpos; 

def_x = LEFTPOS + (xpos * (SPACING/2)); 

문제는 X360 컴파일러에 관해서입니다.

답변

11

해제 모드의 FP 전략이 다를 수 있습니다. 원하는 최적화 수준에 따라 부동 소수점 산술 모드가 다릅니다. 예를 들어, MSVC는 엄격하고, 빠르며 정확한 모드를 가지고 있습니다.

2

이것은 버그가 아닙니다. 부동 소수점 연산에는 특정 부정확성이 있습니다. 릴리스 모드에서는 최적화 작업 순서가 변경되며 약간 다른 결과가 나타납니다. 그러나 차이는 작아야합니다. 큰 문제라면 다른 문제가있을 수 있습니다.

1

버그가 없습니다. 이러한 유형의 차이가 예상됩니다.

예를 들어 일부 플랫폼에는 메모리에 저장된 것보다 많은 비트를 사용하는 부동 소수점 레지스터가 있으므로 레지스터에 값을 저장하면 메모리에 저장하고 메모리에서 다시로드하는 것과 약간 다른 결과가 발생할 수 있습니다.

0

이 불일치는 일반적으로 릴리스 모드에서 수행되지만 디버그 모드에서는 수행되지 않는 컴파일러 최적화로 인해 발생할 수 있습니다. 예를 들어, 컴파일러는 실행 속도를 높이기 위해 일부 연산 순서를 변경할 수 있습니다. 이는 부동 소수점 결과에 약간의 차이가 발생할 수 있습니다.

따라서 버그 일 가능성이 높습니다. 정말로 걱정이된다면, 디버그 모드에서 최적화를 켜보십시오.

4

나는 PC에서 부동 소수점 레지스터가 80 비트 폭이라는 ​​것을 알고있다. 따라서 FPU 내에서 계산이 완전히 완료되면 80 비트의 정밀도를 얻을 수 있습니다. 반대로, 중간 결과가 일반 레지스터로 이동되어 다시 돌아 오면 32 비트로 잘려서 결과가 달라집니다.

이제 릴리스 빌드에서 중간 결과를 FPU 레지스터에 보관하는 반면 디버그 빌드는 중간 결과를 메모리와 레지스터간에 앞뒤로 복사 할 가능성이 높다는 점을 고려하면 동작에 차이가 있습니다.

이 문제가 X360에서도 발생하는지 여부는 알 수 없습니다.

0

부동 소수점 레지스터는 부동 소수점보다 정밀도가 높기 때문에 최종 결과의 정확도는 레지스터 할당에 따라 달라집니다.

일관된 결과가 필요한 경우 변수를 휘발성으로 만들 수 있습니다. 결과가 더 느리고 정확하지는 않지만 일관된 결과가됩니다.

2

다른 부동 소수점 모드 외에도 다른 사람들이 지적한 바와 같이 SSE 또는 유사한 벡터 최적화가 릴리스 될 수 있습니다. 표준 레지스터에서 부동 소수점 산술을 벡터 레지스터로 변환하면 벡터 레지스터가 일반적으로 표준 부동 소수점 레지스터보다 좁아집니다 (비트 수가 적음) 결과의 하위 비트에 영향을 줄 수 있습니다.

0

컴파일러가 부동 소수점 연산을 재정렬하도록 허용하는 컴파일러 스위치를 설정 한 경우 - 예 :/fp : fast - 그러면 분명히 버그가 아닙니다.

스위치를 설정하지 않으면 버그가 발생합니다. C 및 C++ 표준은 컴파일러가 사용자의 허가없이 조작을 재정렬하도록 허용하지 않습니다.