2012-01-26 2 views
7

는 Visual C++은 C4738 warning을 방출 할 수있다 : 예 성능이중으로 C4738과 같은 경고가 표시되지 않는 이유는 무엇입니까?

메모리에 32 비트 부동 소수점 결과를 저장 가능한 손실을 32 비트 float 대신 메모리에 기억 되려고 할 때 레지스터에 저장됩니다.

설명에 따르면 double을 사용하면 문제가 해결됩니다. 나는 왜 후자가 진실인지 알지 못한다.

float을 메모리에 저장하면 성능 손실이 발생하고 double을 저장하는 것이 왜 그렇지 않습니까?

답변

7

경고는 두 가지 문제 결합 : (

  • 수레가 반올림됩니다 (메모리는 레지스터보다 훨씬 느린 때문에) 성능이 저하 될 수 있습니다 수레 오히려 레지스터보다 메모리에 저장 될 필요가

    • 을, 레지스터 때문에 항상 64 비트 또는 80 비트가 있지만 메모리에는 32 비트 만 있습니다.

    double을 사용하면 두 번째 문제 (적어도 부분적으로 64 비트는 여전히 80 비트보다 정확하지 않음)를 해결할 수 있지만 가능한 성능 손실에는 영향을주지 않습니다. 경고 ENT 버튼을 누르면 DVR은 두 치료 언급 이유입니다 :

    이 경고를 해결하고 라운딩을 방지하기를, /의 FP 컴파일 : 빠르거나 사용하는 대신 수레의 두 배.

    이 경고를 해결하고 레지스터의 부족 방지하기 위해, 계산의 순서를 변경하고 나는 원인을 확실히 100 % 아니에요 동안

  • +0

    왜'float'이 성능 손실을 가져 오지만'double'이 아닌가? – tenfour

    +0

    @tenfour : * both *는 성능 손실을 가져 오지만 double은 반올림되지 않습니다. –

    +2

    @tenfour : 32 비트 메모리 위치에 64 비트 부동 소수점 레지스터를 숨길 때 반올림해야하며 반올림에는 시간이 필요합니다. 64 비트 부동 소수점 레지스터를 64 비트 메모리 위치에 숨길 때 라운드 만하지 않고 저장할 수 있습니다. (대부분의 부동 소수점은 이제 SSE 레지스터로 인해 다운되었으므로 80 비트는 무의미합니다.) –

    3

    를 인라인의 사용을 수정, 여기에 내 생각이다.

    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을 메모리에 유지할 수 있으므로 메모리로 가고 메모리에서 오는 오버 헤드를 건너 뜁니다.


    왜 그것이 등록을 다 떨어 뜨릴 수 있는지 ... 나는 잘 모른다. 프로그램의 의미가 동일한 값의 배정 밀도 값과 단 정밀도 값을 가질 수 있습니다.이 경우에는 추가 레지스터가 필요합니다.