문제

내 응용 프로그램은 릴리스 모드와 디버그 모드에서 컴파일 할 때 다른 부동 소수점 값을 생성합니다. 내가 알게 된 유일한 이유는 바이너리 트레이스 로그를 저장하고 릴리스 빌드에서 나온 것이 디버그 빌드에서 약간 떨어져 있기 때문입니다. 사례의.

이 "차이"가 버그라고 생각하거나 이러한 유형의 차이가 예상 될 수 있습니까? 이것은 컴파일러 버그 또는 내부 라이브러리 버그일까요?

예를 들어:

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

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

문제는 X360 컴파일러와 관련이 있습니다.

도움이 되었습니까?

해결책

릴리스 모드에는 다른 FP 전략 세트가있을 수 있습니다. 원하는 최적화 수준에 따라 다른 부동 소수점 산술 모드가 있습니다. 예를 들어 MSVC는 엄격하고 빠르며 정확한 모드를 가지고 있습니다.

다른 팁

PC에서 플로팅 포인트 레지스터의 폭은 80 비트라는 것을 알고 있습니다. 따라서 FPU 내에서 계산이 완전히 수행되면 80 비트의 정밀도의 이점을 얻습니다. 반면에, 중간 결과가 일반 레지스터로 옮겨지고 뒤로 이동하면 32 비트로 잘려서 결과가 다릅니다.

이제 릴리스 빌드에는 FPU 레지스터에서 중간 결과를 유지하는 최적화가 있으며 디버그 빌드는 아마도 메모리와 레지스터 사이의 중간 결과를 순진하게 복사 할 것입니다. 그리고 행동에 차이가 있습니다.

이것이 x360에서도 발생하는지 모르겠습니다.

동료가 자신의 차이를 일으키는 릴리스 대 디버그 빌드에서 다른 컴파일러 스위치를 찾도록 도와주었습니다.

보세요 /fp (부동 소수점 행동 지정).

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

다른 사람들이 지적한 다양한 부동 소수점 모드 외에도 SSE 또는 Similiar Vector Optimization이 릴리스를 위해 켜질 수 있습니다. 플로팅 포인트 산술을 표준 레지스터에서 벡터 레지스터로 변환하면 벡터 레지스터가 일반적으로 표준 부동 소수점 레지스터보다 더 좁아지기 때문에 결과의 낮은 비트에 영향을 줄 수 있습니다.

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

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

이 불일치는 일반적으로 릴리스 모드에서 수행되지만 디버그 모드에서는 그렇지 않은 컴파일러 최적화로 인해 발생할 수 있습니다. 예를 들어, 컴파일러는 일부 작업을 재정렬하여 실행 속도를 높이기 위해 부동 소수점 결과에 약간의 차이를 유발할 수 있습니다.

그래서 나는 그것이 버그가 아니라고 말할 것입니다. 이것에 대해 정말로 걱정이된다면 디버그 모드에서 최적화를 켜십시오.

다른 사람들과 마찬가지로, 부동 소수점 레지스터는 플로트보다 정밀도가 높기 때문에 최종 결과의 정확도는 레지스터 할당에 따라 다릅니다.

일관된 결과가 필요하면 변수를 휘발성으로 만들 수 있으므로 느리고 정확하지 않지만 일관된 결과를 얻을 수 있습니다.

컴파일러가 플로팅 포인트 작업 (예 : /FP : FAST)을 재주문 할 수있는 컴파일러 스위치를 설정하면 분명히 버그가 아닙니다.

이러한 스위치를 설정하지 않은 경우 버그입니다. C 및 C ++ 표준은 컴파일러가 귀하의 권한없이 작업을 재정렬 할 수 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top