다음을 통해 공유


/fp (부동 소수점 동작 지정)

컴파일러가 부동 소수점 식, 최적화 및 예외를 처리하는 방법을 지정합니다. 이 /fp 옵션은 생성된 코드에서 반올림 모드, 예외 마스크 및 하위 동작에 대한 부동 소수점 환경 변경을 허용하는지 여부와 부동 소수점 상태 확인 현재 정확한 결과를 반환할지 여부를 지정합니다. 컴파일러가 소스 작업 및 식 순서를 유지하는 코드를 생성하고 NaN 전파에 대한 표준을 준수하는지 여부를 제어합니다. 또는 작업을 다시 정렬하거나 결합할 수 있는 보다 효율적인 코드를 생성하고 IEEE-754 표준에서 허용되지 않는 대수 변환 간소화를 사용하는 경우

구문

/fp:contract
/fp:except[-]
/fp:fast
/fp:precise
/fp:strict

/fp:except[-]
/fp:fast
/fp:precise
/fp:strict

인수

/fp:contract

/fp:contract 옵션을 사용하면 옵션 및 /fp:except 옵션을 지정할 때 컴파일러가 부동 소수점 수축을 생성할 /fp:precise 수 있습니다. 수축은 FMA(Fused-Multiply-Add)와 같은 부동 소수점 작업을 결합하는 컴퓨터 명령입니다. IEEE-754에 의해 기본 연산으로 정의된 FMA는 추가 전에 중간 제품을 반올림하지 않으므로 결과는 별도의 곱하기 및 추가 작업과 다를 수 있습니다. 단일 명령으로 구현되므로 별도의 명령보다 더 빠를 수 있습니다. 속도는 비트 정확한 결과의 비용과 중간 값을 검사할 수 없습니다.

기본적으로 이 /fp:fast 옵션은 .를 /fp:contract사용하도록 설정합니다. 이 /fp:contract 옵션은 .와 /fp:strict호환되지 않습니다.

Visual /fp:contract Studio 2022의 새로운 옵션입니다.

/fp:precise

기본적으로 컴파일러는 동작을 사용합니다 /fp:precise .

아래에서 /fp:precise컴파일러는 대상 컴퓨터에 대한 개체 코드를 생성하고 최적화할 때 부동 소수점 코드의 소스 식 순서 지정 및 반올림 속성을 유지합니다. 컴파일러는 식 평가 중에 할당, typecast, 부동 소수점 인수가 함수 호출에 전달되는 경우 및 함수 호출이 부동 소수점 값을 반환할 때의 네 가지 특정 지점에서 소스 코드 정밀도로 반올림합니다. 중간 계산은 기계 정밀도로 수행될 수 있습니다. Typecast는 중간 계산을 명시적으로 반올림하는 데 사용할 수 있습니다.

컴파일러는 변환이 비트와 동일한 결과를 생성할 수 없으면 재연합 또는 분포와 같은 부동 소수점 식에서 대수 변환을 수행하지 않습니다. 특수 값(NaN, +infinity, -infinity, -0.0)을 포함하는 식은 IEEE-754 사양에 따라 처리됩니다. 예를 들어 x != x NaN인지 x 평가 true 합니다. 부동 소수점 수축은 기본적으로 .에서 /fp:precise생성되지 않습니다. 이 동작은 Visual Studio 2022의 새로운 동작입니다. 이전 컴파일러 버전은 기본적으로 .에서 수축을 생성할 수 있습니다 /fp:precise.

컴파일러는 변환이 비트와 동일한 결과를 생성할 수 없으면 재연합 또는 분포와 같은 부동 소수점 식에서 대수 변환을 수행하지 않습니다. 특수 값(NaN, +infinity, -infinity, -0.0)을 포함하는 식은 IEEE-754 사양에 따라 처리됩니다. 예를 들어 x != x NaN인지 x 평가 true 합니다. 부동 소수점 수축은 아래에 /fp:precise생성될 수 있습니다.

컴파일러는 기본 부동 소수점 환경에서 실행하기 위한 코드를 생성합니다. 또한 부동 소수점 환경이 런타임에 액세스하거나 수정되지 않는다고 가정합니다. 즉, 코드는 부동 소수점 예외를 마스킹된 상태로 두고, 부동 소수점 상태 레지스터를 읽거나 쓰지 않으며, 반올림 모드를 변경하지 않는다고 가정합니다.

부동 소수점 코드가 부동 소수점 문의 작업 및 식 순서에 의존하지 않는 경우(예: 계산 a + a(b + c) * a 2 * a 여부를 a * b + a * c 고려하지 않는 경우) 더 빠르고 효율적인 코드를 생성할 수 있는 옵션을 고려 /fp:fast 합니다. 코드가 작업 및 식의 순서에 따라 달라지고 부동 소수점 환경에 액세스하거나 변경하는 경우(예: 반올림 모드를 변경하거나 부동 소수점 예외를 트래핑하기 위해) 사용합니다 /fp:strict.

/fp:strict

/fp:strict 와 유사한 /fp:precise동작이 있습니다. 즉, 컴파일러는 대상 머신에 대한 개체 코드를 생성하고 최적화할 때 부동 소수점 코드의 소스 순서 및 반올림 속성을 유지하고 특수 값을 처리할 때 표준을 관찰합니다. 또한 프로그램은 런타임에 부동 소수점 환경에 안전하게 액세스하거나 수정할 수 있습니다.

컴파일 /fp:strict러는 프로그램에서 부동 소수점 예외의 마스크를 안전하게 해제하거나, 부동 소수점 상태 레지스터를 읽거나 쓰거나, 반올림 모드를 변경할 수 있는 코드를 생성합니다. 식 평가 중에는 할당, typecast, 부동 소수점 인수가 함수 호출에 전달되고 함수 호출이 부동 소수점 값을 반환할 때의 네 가지 특정 지점에서 소스 코드 정밀도로 반올림됩니다. 중간 계산은 기계 정밀도로 수행될 수 있습니다. Typecast는 중간 계산을 명시적으로 반올림하는 데 사용할 수 있습니다. 컴파일러는 변환이 비트와 동일한 결과를 생성할 수 없으면 재연합 또는 분포와 같은 부동 소수점 식에서 대수 변환을 수행하지 않습니다. 특수 값(NaN, +infinity, -infinity, -0.0)을 포함하는 식은 IEEE-754 사양에 따라 처리됩니다. 예를 들어 x != x NaN인지 x 평가 true 합니다. 부동 소수점 수축은 아래에 /fp:strict생성되지 않습니다.

/fp:strict 는 컴파일러가 예외를 트래핑하고 프로그램이 런타임에 부동 소수점 환경에 액세스하거나 수정할 수 있도록 추가 명령을 삽입해야 하기 때문에 계산 비용이 더 많이 듭니다 /fp:precise . 코드에서 이 기능을 사용하지 않지만 소스 코드 순서 지정 및 반올림이 필요하거나 특수 값을 사용하는 경우 사용합니다 /fp:precise. 그렇지 않으면 더 빠르고 작은 코드를 생성할 수 있는 사용을 고려 /fp:fast합니다.

/fp:fast

/fp:fast 옵션을 사용하면 컴파일러가 부동 소수점 연산의 순서를 변경, 결합 또는 단순화하여 속도 및 공간에 대한 부동 소수점 코드를 최적화할 수 있습니다. 컴파일러는 할당 문, typecast 또는 함수 호출에서 반올림을 생략할 수 있습니다. 예를 들어 결합 및 분산 법률을 사용하여 작업을 다시 정렬하거나 대수 변환을 만들 수 있습니다. 이러한 변환으로 인해 반올림 동작이 눈에 띄게 달라지더라도 코드를 다시 정렬할 수 있습니다. 이 향상된 최적화로 인해 일부 부동 소수점 계산의 결과는 다른 /fp 옵션에서 생성된 계산과 다를 수 있습니다. 특수 값(NaN, +infinity, -infinity, -0.0)은 IEEE-754 표준에 따라 전파되거나 엄격하게 동작할 수 없습니다. 부동 소수점 수축은 아래에 /fp:fast생성될 수 있습니다. 컴파일러는 여전히 아래 /fp:fast의 기본 아키텍처에 의해 바인딩되며 옵션을 사용하여 더 많은 최적화를 /arch 사용할 수 있습니다.

아래 /fp:fast의 컴파일러는 기본 부동 소수점 환경에서 실행하기 위한 코드를 생성하고 런타임에 부동 소수점 환경에 액세스하거나 수정하지 않는다고 가정합니다. 즉, 코드는 부동 소수점 예외를 마스킹된 상태로 두고, 부동 소수점 상태 레지스터를 읽거나 쓰지 않으며, 반올림 모드를 변경하지 않는다고 가정합니다.

/fp:fast 는 부동 소수점 식의 엄격한 소스 코드 순서 지정 및 반올림이 필요하지 않고 , 와 같은 NaN특수 값을 처리하기 위한 표준 규칙에 의존하지 않는 프로그램을 위한 것입니다. 부동 소수점 코드에서 소스 코드 정렬 및 반올림을 보존해야 하거나 특수 값의 표준 동작에 의존하는 경우 사용합니다 /fp:precise. 코드가 부동 소수점 환경에 액세스하거나 수정하여 반올림 모드를 변경하거나, 부동 소수점 예외의 마스크를 해제하거나, 부동 소수점 상태를 확인하는 경우 사용합니다 /fp:strict.

/fp:except

/fp:except 옵션은 마스크되지 않은 부동 소수점 예외가 발생하는 정확한 지점에서 발생하고 다른 부동 소수점 예외가 발생하지 않도록 하는 코드를 생성합니다. 기본적으로 이 /fp:strict 옵션은 사용하도록 설정 /fp:except되며 /fp:precise 활성화되지 않습니다. 이 /fp:except 옵션은 .와 /fp:fast호환되지 않습니다. 옵션을 사용하여 /fp:except-명시적으로 비활성화할 수 있습니다.

그 자체로는 /fp:except 부동 소수점 예외를 사용하도록 설정하지 않습니다. 그러나 프로그램에서 부동 소수점 예외를 사용하도록 설정해야 합니다. 부동 소수점 예외를 사용하도록 설정하는 방법에 대한 자세한 내용은 다음을 참조하세요 _controlfp.

설명

동일한 컴파일러 명령줄에서 여러 /fp 옵션을 지정할 수 있습니다. 및 /fp:fast/fp:precise 옵션 중 /fp:strict하나만 한 번에 적용할 수 있습니다. 명령줄에서 이러한 옵션 중 하나 이상을 지정하면 이후 옵션이 우선적으로 적용되고 컴파일러가 경고를 생성합니다. /fp:strict 및 옵션은 .와 /fp:except /clr호환되지 않습니다.

/Za (ANSI 호환성) 옵션은 .와 /fp호환되지 않습니다.

컴파일러 지시문을 사용하여 부동 소수점 동작 제어

컴파일러는 명령줄에 지정된 부동 소수점 동작을 재정의하는 세 가지 float_controlfenv_accessfp_contractpragma 지시문을 제공합니다. 이러한 지시문을 사용하여 함수가 아닌 함수 수준에서 부동 소수점 동작을 제어할 수 있습니다. 이러한 지시문은 옵션에 /fp 직접 해당하지 않습니다. 이 표에서는 옵션과 pragma 지시문이 서로 매핑되는 방법을 /fp 보여 줍니다. 자세한 내용은 개별 옵션 및 pragma 지시문에 대한 설명서를 참조하세요.

옵션 float_control(precise, *) float_control(except, *) fenv_access(*) fp_contract(*)
/fp:fast off off off on
/fp:precise on off off off*
/fp:strict on on on off

* Visual Studio 2022 이전 버전의 Visual Studio에서는 동작이 /fp:precise 기본값으로 지정 fp_contract(on)됩니다.

옵션 float_control(precise, *) float_control(except, *) fenv_access(*) fp_contract(*)
/fp:fast off off off on
/fp:precise on off off on*
/fp:strict on on on off

* Visual Studio 2022부터 Visual Studio 버전에서는 동작이 /fp:precise 기본값으로 지정 fp_contract(off)됩니다.

기본 부동 소수점 환경

프로세스가 초기화 되면 기본 부동 소수점 환경 이 설정됩니다. 이 환경은 모든 부동 소수점 예외를 마스킹하고, 반올림 모드를 가장 가까운(FE_TONEAREST비정규) 값으로 반올림하도록 설정하고, 비정규(비정상) 값을 유지하고 , 및 long double 값에 대해 floatdoublesignificand(매니타사)의 기본 전체 자릿수를 사용하며, 지원되는 경우 무한대 컨트롤을 기본 아핀 모드로 설정합니다.

부동 소수점 환경 액세스 및 수정

Microsoft Visual C++ 런타임은 부동 소수점 환경에 액세스하고 수정하는 몇 가지 함수를 제공합니다. 여기에는 , _clearfp_statusfp 해당 변형이 포함_controlfp됩니다. 코드가 부동 소수점 환경에 fenv_access 액세스하거나 수정할 때 올바른 프로그램 동작을 보장하려면 이러한 함수가 영향을 미치려면 옵션 또는 pragma를 사용하여 fenv_access 사용하도록 설정 /fp:strict 해야 합니다. 사용하도록 설정되지 않은 경우 fenv_access 부동 소수점 환경의 액세스 또는 수정으로 인해 예기치 않은 프로그램 동작이 발생할 수 있습니다.

  • 코드는 부동 소수점 환경에 대한 요청된 변경 내용을 적용하지 않을 수 있습니다.

  • 부동 소수점 상태 레지스터는 예상 결과 또는 현재 결과를 보고하지 않을 수 있습니다.

  • 예기치 않은 부동 소수점 예외가 발생하거나 예상된 부동 소수점 예외가 발생하지 않을 수 있습니다.

코드가 부동 소수점 환경에 액세스하거나 수정하는 경우 사용하도록 설정된 코드를 사용하도록 설정하지 fenv_access 않은 코드 fenv_access 와 결합할 때는 주의해야 합니다. 사용하도록 설정되지 않은 코드 fenv_access 에서 컴파일러는 플랫폼 기본 부동 소수점 환경이 적용된다고 가정합니다. 또한 부동 소수점 상태가 액세스되거나 수정되지 않는다고 가정합니다. 컨트롤이 활성화되지 않은 fenv_access 함수로 전송되기 전에 로컬 부동 소수점 환경을 기본 상태로 저장하고 복원하는 것이 좋습니다. 이 예제에서는 pragma를 float_control 설정하고 복원하는 방법을 보여 줍니다.

#pragma float_control(precise, on, push)
// Code that uses /fp:strict mode
#pragma float_control(pop)

부동 소수점 반올림 모드

둘 다 /fp:precise /fp:fast에서 컴파일러는 기본 부동 소수점 환경에서 실행하기 위한 코드를 생성합니다. 런타임 시 환경에 액세스하거나 수정하지 않는다고 가정합니다. 즉, 컴파일러는 코드가 부동 소수점 예외의 마스크를 해제하거나, 부동 소수점 상태 레지스터를 읽거나 쓰거나, 반올림 모드를 변경하지 않는 것으로 가정합니다. 그러나 일부 프로그램은 부동 소수점 환경을 변경해야 합니다. 예를 들어 이 샘플에서는 부동 소수점 반올림 모드를 변경하여 부동 소수점 곱셈의 오류 범위를 계산합니다.

// fp_error_bounds.cpp
#include <iostream>
#include <limits>
using namespace std;

int main(void)
{
    float a = std::<float>::max();
    float b = -1.1;
    float cLower = 0.0;
    float cUpper = 0.0;
    unsigned int control_word = 0;
    int err = 0;

    // compute lower error bound.
    // set rounding mode to -infinity.
    err = _controlfp_s(&control_word, _RC_DOWN, _MCW_RC);
    if (err)
    {
        cout << "_controlfp_s(&control_word, _RC_DOWN, _MCW_RC) failed with error:" << err << endl;
    }  
    cLower = a * b;

    // compute upper error bound.
    // set rounding mode to +infinity.
    err = _controlfp_s(&control_word, _RC_UP, _MCW_RC);
    if (err)
    {
        cout << "_controlfp_s(&control_word, _RC_UP, _MCW_RC) failed with error:" << err << endl;
    }
    cUpper = a * b;

    // restore default rounding mode.
    err = _controlfp_s(&control_word, _CW_DEFAULT, _MCW_RC);
    if (err)
    {
        cout << "_controlfp_s(&control_word, _CW_DEFAULT, _MCW_RC) failed with error:" << err << endl;
    }
    // display error bounds.
    cout << "cLower = " << cLower << endl;
    cout << "cUpper = " << cUpper << endl;
    return 0;
}

컴파일러는 기본 부동 소수점 환경을 가정 /fp:fast 하므로 /fp:precise호출을 무시해도 됩니다 _controlfp_s. 예를 들어 x86 아키텍처와 /fp:precise x86 아키텍처를 모두 /O2 사용하여 컴파일하는 경우 범위는 계산되지 않으며 샘플 프로그램은 다음을 출력합니다.

cLower = -inf
cUpper = -inf

x86 아키텍처를 모두 /O2 /fp:strict 사용하여 컴파일하는 경우 샘플 프로그램은 다음을 출력합니다.

cLower = -inf
cUpper = -3.40282e+38

부동 소수점 특수 값

/fp:strict및 , /fp:precise 특수 값(NaN, +infinity, -infinity, -0.0)을 포함하는 식은 IEEE-754 사양에 따라 동작합니다. 아래에서 /fp:fast이러한 특수 값의 동작은 IEEE-754와 일치하지 않을 수 있습니다.

이 샘플에서는 다음과 같은 특수 /fp:precise값의 다양한 동작을 /fp:strict보여 줍니다 /fp:fast.

// fp_special_values.cpp
#include <stdio.h>
#include <cmath>

float gf0 = -0.0;

int main()
{
    float f1 = INFINITY;
    float f2 = NAN;
    float f3 = -INFINITY;
    bool a, b;
    float c, d, e;
    a = (f1 == f1);
    b = (f2 == f2);
    c = (f1 - f1);
    d = (f2 - f2);
    e = (gf0 / f3);
    printf("INFINITY == INFINITY : %d\n", a);
    printf("NAN == NAN           : %d\n", b);
    printf("INFINITY - INFINITY  : %f\n", c);
    printf("NAN - NAN            : %f\n", d);
    printf("std::signbit(-0.0/-INFINITY): %d\n", std::signbit(e));
    return 0;
}

x86 아키텍처를 사용 /O2 /fp:precise 하거나 /O2 /fp:strict 컴파일하는 경우 출력은 IEEE-754 사양과 일치합니다.

INFINITY == INFINITY : 1
NAN == NAN           : 0
INFINITY - INFINITY  : -nan(ind)
NAN - NAN            : nan
std::signbit(-0.0/-INFINITY): 0

x86 아키텍처에 **를 사용하여 /O2 /fp:fast컴파일하는 경우 출력은 IEEE-754와 일치하지 않습니다.

INFINITY == INFINITY : 1
NAN == NAN           : 1
INFINITY - INFINITY  : 0.000000
NAN - NAN            : 0.000000
std::signbit(-0.0/-INFINITY): 0

부동 소수점 대수 변환

/fp:strict변환 /fp:precise 이 약간 동일한 결과를 생성하도록 보장되지 않는 한 컴파일러는 수학 변환을 수행하지 않습니다. 컴파일러에서 이러한 변환을 만들 수 있습니다 /fp:fast. 예를 들어 샘플 함수의 식 a * b + a * c 은 아래/fp:fasta * (b + c) 컴파일될 수 algebraic_transformation 있습니다. 이러한 변환은 아래 /fp:precise 또는 /fp:strict아래에서 수행되지 않으며 컴파일러는 생성합니다 a * b + a * c.

float algebraic_transformation (float a, float b, float c)
{
    return a * b + a * c;
}

부동 소수점 명시적 캐스팅 지점

/fp:strict컴파일 /fp:precise 러는 식 계산 중에 할당, typecast, 부동 소수점 인수가 함수 호출에 전달되는 경우 및 함수 호출이 부동 소수점 값을 반환할 때의 네 가지 특정 지점에서 소스 코드 정밀도로 반올림합니다. Typecast는 중간 계산을 명시적으로 반올림하는 데 사용할 수 있습니다. 아래에서 /fp:fast컴파일러는 소스 코드 정밀도를 보장하기 위해 이러한 지점에서 명시적 캐스트를 생성하지 않습니다. 이 샘플은 다음과 같은 다양한 /fp 옵션에서 동작을 보여 줍니다.

float casting(float a, float b)
{
    return 5.0*((double)(a+b));
}

사용하거나 /O2 /fp:strict컴파일 /O2 /fp:precise 하는 경우 명시적 형식 캐스트가 x64 아키텍처에 대해 생성된 코드의 typecast 및 함수 반환 지점에 삽입되는 것을 볼 수 있습니다.

        addss    xmm0, xmm1
        cvtss2sd xmm0, xmm0
        mulsd    xmm0, QWORD PTR __real@4014000000000000
        cvtsd2ss xmm0, xmm0
        ret      0

생성된 코드에서는 /O2 /fp:fast 모든 형식 캐스트가 최적화되므로 간소화됩니다.

        addss    xmm0, xmm1
        mulss    xmm0, DWORD PTR __real@40a00000
        ret      0

Visual Studio 개발 환경에서 이 컴파일러 옵션을 설정하려면

  1. 프로젝트의 속성 페이지 대화 상자를 엽니다. 자세한 내용은 Visual Studio에서 C++ 컴파일러 및 빌드 속성 설정을 참조하세요.

  2. 구성 속성>C/C++>코드 생성 속성 페이지를 선택합니다.

  3. 부동 소수점 모델 속성을 수정합니다.

프로그래밍 방식으로 이 컴파일러 옵션을 설정하려면

참고 항목

MSVC 컴파일러 옵션
MSVC 컴파일러 명령줄 구문