를 인라인의 사용을 수정, 여기에 내 생각이다.
x86에서 컴파일하고 SSE2를 사용할 수없는 경우 컴파일러는 모든 부동 소수점 레지스터에 대해 x87 FP 스택을 사용해야합니다. MSVC에서 FP 모드는 기본적으로 53 비트 정밀도 반올림으로 설정됩니다. (제 생각에는 100 % 확신 할 수 없습니다.)
따라서 FP 스택에서 수행 된 모든 연산은 배정도를 사용합니다.
그러나 무언가가 float
으로 캐스트 될 때 정밀도는 단 정밀도로 반올림되어야합니다. 이를 수행하는 유일한 방법은 4 바이트 메모리 피연산자에 대한 fstp
명령어를 통해 메모리에 저장 한 다음 다시로드하는 것입니다.
는의가에 예를 살펴 보자
C4738 warning page 당신이에 연결 : 당신이
func()
를 호출 할 때
d
은 아마 x87 레지스터에 저장되어,
float func(float f)
{
return f;
}
int main()
{
extern float f, f1, f2;
double d = 0.0;
f1 = func(d);
f2 = (float) d;
f = f1 + f2; // C4738
printf_s("%f\n", f);
}
. 그러나 func()
을 호출하려면 정밀도를 단 정밀도로 낮추어야합니다. 이로 인해 d
은 반올림되거나 메모리에 저장됩니다. 그런 다음 다시로드되고 f = f1 + f2;
라인의 배정도로 다시 승격됩니다.
그러나 전체적으로 double
을 사용하면 컴파일러에서 d
을 메모리에 유지할 수 있으므로 메모리로 가고 메모리에서 오는 오버 헤드를 건너 뜁니다.
왜 그것이 등록을 다 떨어 뜨릴 수 있는지 ... 나는 잘 모른다. 프로그램의 의미가 동일한 값의 배정 밀도 값과 단 정밀도 값을 가질 수 있습니다.이 경우에는 추가 레지스터가 필요합니다.
왜'float'이 성능 손실을 가져 오지만'double'이 아닌가? – tenfour
@tenfour : * both *는 성능 손실을 가져 오지만 double은 반올림되지 않습니다. –
@tenfour : 32 비트 메모리 위치에 64 비트 부동 소수점 레지스터를 숨길 때 반올림해야하며 반올림에는 시간이 필요합니다. 64 비트 부동 소수점 레지스터를 64 비트 메모리 위치에 숨길 때 라운드 만하지 않고 저장할 수 있습니다. (대부분의 부동 소수점은 이제 SSE 레지스터로 인해 다운되었으므로 80 비트는 무의미합니다.) –