/fp (Angeben des Gleitkommaverhaltens)

Gibt an, wie der Compiler Gleitkommaausdrücke, Optimierungen und Ausnahmen behandelt. Die /fp Optionen geben an, ob der generierte Code Gleitkommaumgebungsänderungen im Rundungsmodus, Ausnahmemasken und Unternormalverhalten zulässt und ob Gleitkommastatusprüfungen aktuelle, genaue Ergebnisse zurückgeben. Er steuert, ob der Compiler Code generiert, der den Quellvorgang und die Ausdrucksreihenfolge Standard und dem Standard für die NaN-Verteilung entspricht. Oder wenn sie stattdessen effizienteren Code generiert, der Vorgänge neu anordnen oder kombinieren kann, und vereinfachende algebraische Transformationen, die vom IEEE-754-Standard nicht zulässig sind.

Syntax

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

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

Argumente

/fp:contract

Mit /fp:contract der Option kann der Compiler Gleitkommakontraktionen generieren, wenn Sie die /fp:precise Optionen /fp:except angeben. Eine Kontraktion ist eine Maschinenanweisung, die Gleitkommavorgänge wie Fused-Multiplikations-Add (FMA) kombiniert. FMA, definiert als basisbasierter Betrieb durch IEEE-754, rundet das Zwischenprodukt nicht vor dem Zusatz ab, sodass sich das Ergebnis von separaten Multiplikations- und Additionsvorgängen unterscheiden kann. Da sie als einzelne Anweisung implementiert wird, kann sie schneller als separate Anweisungen sein. Die Geschwindigkeit kostet bitweise genaue Ergebnisse und eine Unfähigkeit, den Zwischenwert zu untersuchen.

Standardmäßig aktiviert /fp:contractdie /fp:fast Option . Die /fp:contract Option ist nicht kompatibel mit /fp:strict.

Die /fp:contract Option ist neu in Visual Studio 2022.

/fp:precise

Standardmäßig verwendet /fp:precise der Compiler verhalten.

Im Folgenden /fp:precisebehält der Compiler die Quellausdrucksortierungs- und Rundungseigenschaften von Gleitkommacode bei, wenn er Objektcode für den Zielcomputer generiert und optimiert. Der Compiler rundet während der Ausdrucksauswertung auf die Quellcodegenauigkeit zu vier bestimmten Punkten ab: bei Zuordnungen, Typecasts, wenn Gleitkommaargumente an einen Funktionsaufruf übergeben werden und wenn ein Funktionsaufruf einen Gleitkommawert zurückgibt. Zwischenberechnungen können bei der Maschinengenauigkeit durchgeführt werden. Typecasts können zum expliziten Runden von Zwischenberechnungen verwendet werden.

Der Compiler führt keine algebraischen Transformationen für Gleitkommaausdrücke aus, z. B. eine Erneute Zuordnung oder Verteilung, es sei denn, die Transformation kann garantieren, dass ein bitweises identisches Ergebnis entsteht. Ausdrücke, die spezielle Werte (NaN, +infinity, -infinity, -0,0) enthalten, werden gemäß IEEE-754-Spezifikationen verarbeitet. Beispielsweise wird ausgewertettrue, x != x ob x naN ist. Gleitkommakontraktionen werden standardmäßig nicht generiert unter /fp:precise. Dieses Verhalten ist neu in Visual Studio 2022. In früheren Compilerversionen können Kontraktionen standardmäßig unter /fp:precise.

Der Compiler führt keine algebraischen Transformationen für Gleitkommaausdrücke aus, z. B. eine Erneute Zuordnung oder Verteilung, es sei denn, die Transformation kann garantieren, dass ein bitweises identisches Ergebnis entsteht. Ausdrücke, die spezielle Werte (NaN, +infinity, -infinity, -0,0) enthalten, werden gemäß IEEE-754-Spezifikationen verarbeitet. Beispielsweise wird ausgewertettrue, x != x ob x naN ist. Gleitkommakontraktionen können unter /fp:precise.

Der Compiler generiert Code, der in der Standard-Gleitkommaumgebung ausgeführt werden soll. Außerdem wird davon ausgegangen, dass zur Laufzeit nicht auf die Gleitkommaumgebung zugegriffen oder geändert wird. Das heißt, es wird davon ausgegangen, dass der Code: Lässt Gleitkomma-Ausnahmen maskiert, liest oder schreibt keine Gleitkommastatusregister und ändert keine Rundungsmodi.

Wenn Ihr Gleitkommacode nicht von der Reihenfolge von Vorgängen und Ausdrücken in Ihren Gleitkommaanweisungen abhängt (z. B. wenn Sie sich nicht um die Berechnung (b + c) * a als oder 2 * a as a + akümmern), sollten Sie die /fp:fast Option in Betracht ziehena * b + a * c, die schnelleren, effizienteren Code erzeugen kann. Wenn Ihr Code beide von der Reihenfolge von Vorgängen und Ausdrücken abhängt und auf die Gleitkommaumgebung zugreift oder ändert (z. B. um Roundingmodi zu ändern oder Gleitkommaausnahmen abzufangen), verwenden Sie /fp:strict.

/fp:strict

/fp:strict weist ein ähnliches Verhalten auf /fp:precise, d. h., der Compiler behält die Quellsortierungs- und Rundungseigenschaften von Gleitkommacode bei, wenn er Objektcode für den Zielcomputer generiert und optimiert, und beobachtet den Standard beim Behandeln von Sonderwerten. Das Programm kann auch sicher auf die Gleitkommaumgebung zur Laufzeit zugreifen oder ändern.

Unter /fp:strictdiesem Code generiert der Compiler Code, mit dem das Programm Gleitkomma-Ausnahmen sicher entmasken, Gleitkommastatusregister lesen oder schreiben oder Roundingmodi ändern kann. Sie rundet auf die Quellcodegenauigkeit an vier bestimmten Punkten während der Ausdrucksauswertung ab: bei Zuordnungen, Typecasts, wenn Gleitkommaargumente an einen Funktionsaufruf übergeben werden und wenn ein Funktionsaufruf einen Gleitkommawert zurückgibt. Zwischenberechnungen können bei der Maschinengenauigkeit durchgeführt werden. Typecasts können zum expliziten Runden von Zwischenberechnungen verwendet werden. Der Compiler macht keine algebraischen Transformationen für Gleitkommaausdrücke, wie z. B. die Neuzuordnung oder Verteilung, es sei denn, sie kann garantieren, dass die Transformation ein bitweise identisches Ergebnis erzeugt. Ausdrücke, die spezielle Werte (NaN, +infinity, -infinity, -0,0) enthalten, werden gemäß IEEE-754-Spezifikationen verarbeitet. Beispielsweise wird ausgewertettrue, x != x ob x naN ist. Gleitkommakontraktionen werden unter /fp:strictquot; nicht generiert.

/fp:strict ist rechenintensiver als /fp:precise weil der Compiler zusätzliche Anweisungen einfügen muss, um Ausnahmen abzufangen und Programmen den Zugriff auf die Gleitkommaumgebung zur Laufzeit zu ermöglichen. Wenn Ihr Code diese Funktion nicht verwendet, aber Quellcode sortieren und runden muss oder auf speziellen Werten basiert, verwenden Sie /fp:precise. Ziehen Sie andernfalls die Verwendung in /fp:fastBetracht, die schnelleren und kleineren Code erzeugen kann.

/fp:fast

Mit /fp:fast der Option kann der Compiler Gleitkommavorgänge neu anordnen, kombinieren oder vereinfachen, um Gleitkommacode für Geschwindigkeit und Platz zu optimieren. Der Compiler kann das Runden bei Zuordnungsanweisungen, Typecasts oder Funktionsaufrufen weglassen. Sie kann Vorgänge neu anordnen oder algebraische Transformationen vornehmen, z. B. durch Verwendung von assoziativen und verteilungsrechtlichen Gesetzen. Es kann Code neu anordnen, auch wenn solche Transformationen zu einem observablen unterschiedliche Rundungsverhalten führen. Aufgrund dieser verbesserten Optimierung kann sich das Ergebnis einiger Gleitkommaberechnungen von den von anderen /fp Optionen erzeugten unterscheiden. Sonderwerte (NaN, +infinity, -infinity, -0,0) werden möglicherweise nicht gemäß dem IEEE-754-Standard weitergegeben oder verhalten. Gleitkommakontraktionen können unter /fp:fast. Der Compiler ist nach wie vor an die zugrunde liegende Architektur /fp:fastgebunden, und weitere Optimierungen können über die Verwendung der /arch Option verfügbar sein.

Unter /fp:fastdiesem Code generiert der Compiler Code, der in der Standard-Gleitkommaumgebung ausgeführt werden soll, und geht davon aus, dass zur Laufzeit nicht auf die Gleitkommaumgebung zugegriffen oder geändert wird. Das heißt, es wird davon ausgegangen, dass der Code: Lässt Gleitkomma-Ausnahmen maskiert, liest oder schreibt keine Gleitkommastatusregister und ändert keine Rundungsmodi.

/fp:fast ist für Programme vorgesehen, die keine strikte Quellcodesortierung und Rundung von Gleitkommaausdrücken erfordern und nicht auf die Standardregeln für die Behandlung spezieller Werte wie z NaN. B. basieren. Wenn Ihr Gleitkommacode die Erhaltung der Quellcodesortierung und -rundung erfordert oder das Standardverhalten spezieller Werte verwendet, verwenden Sie /fp:precise. Wenn Ihr Code auf die Gleitkommaumgebung zugreift oder ändert, um Rundungsmodi zu ändern, Gleitkomma-Ausnahmen aufzuheben oder den Gleitkommastatus zu überprüfen, verwenden Sie /fp:strict.

/fp:except

Die /fp:except Option generiert Code, um zu gewährleisten, dass alle ungemasketen Gleitkomma-Ausnahmen an dem genauen Punkt ausgelöst werden, an dem sie auftreten, und dass keine anderen Gleitkomma-Ausnahmen ausgelöst werden. Standardmäßig wird die /fp:strict Option aktiviert /fp:exceptund /fp:precise nicht. Die /fp:except Option ist nicht kompatibel mit /fp:fast. Die Option kann mithilfe von /fp:except-.

/fp:except Allein werden keine Gleitkomma-Ausnahmen aktiviert. Es ist jedoch erforderlich, dass Programme Gleitkomma-Ausnahmen aktivieren. Weitere Informationen zum Aktivieren von Gleitkomma-Ausnahmen finden Sie unter _controlfp.

Hinweise

Mehrere /fp Optionen können in derselben Compiler-Befehlszeile angegeben werden. Es kann jeweils nur eine der /fp:strictOptionen /fp:fast/fp:precise und Optionen wirksam sein. Wenn Sie mehr als eine dieser Optionen in der Befehlszeile angeben, hat die spätere Option Vorrang, und der Compiler generiert eine Warnung. Die /fp:strict Optionen sind /fp:except nicht kompatibel mit /clr.

Die /Za Option (ANSI-Kompatibilität) ist nicht kompatibel mit /fp.

Verwenden von Compilerdirektiven zum Steuern des Gleitkommaverhaltens

Der Compiler stellt drei Pragmadirektiven bereit, um das in der Befehlszeile angegebene Gleitkommaverhalten außer Kraft zu setzen: float_control, fenv_accessund fp_contract. Sie können diese Direktiven verwenden, um das Gleitkommaverhalten auf Funktionsebene zu steuern, nicht innerhalb einer Funktion. Diese Direktiven entsprechen nicht direkt den /fp Optionen. In dieser Tabelle wird gezeigt, wie sich die /fp Optionen und Pragma-Direktiven einander zuordnen. Weitere Informationen finden Sie in der Dokumentation zu den einzelnen Optionen und Pragma-Direktiven.

Option 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

* In Versionen von Visual Studio vor Visual Studio 2022 ist das /fp:precise Verhalten standardmäßig auf fp_contract(on).

Option 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

* In Versionen von Visual Studio ab Visual Studio 2022 wird standardmäßig das /fp:precise Verhalten verwendet fp_contract(off).

Die Standard-Gleitkommaumgebung

Wenn ein Prozess initialisiert wird, wird die Standard-Gleitkommaumgebung festgelegt. Diese Umgebung maskiert alle Gleitkomma-Ausnahmen, legt den Rundungsmodus so fest, dass er auf die nächsten (FE_TONEAREST), unternormalen (Denormal)-Werten gerundet wird, verwendet die Standardgenauigkeit von Significand (Mantissa) für float, doubleund long double Werte, und wo unterstützt, legt das Unendlichkeitssteuerelement auf den Standardaffin-Modus fest.

Zugriff und Änderung der Gleitkommaumgebung

Die Microsoft Visual C++-Laufzeit bietet mehrere Funktionen, um auf die Gleitkommaumgebung zuzugreifen und sie zu ändern. Dazu gehören _controlfp, _clearfpund _statusfp ihre Varianten. Um das richtige Programmverhalten sicherzustellen, wenn Ihr Code auf die Gleitkommaumgebung zugreift oder ändert, fenv_access muss entweder durch die /fp:strict Option oder die Verwendung des fenv_access Pragmas aktiviert werden, damit diese Funktionen auswirkungen haben. Wenn fenv_access diese Option nicht aktiviert ist, kann der Zugriff oder die Änderung der Gleitkommaumgebung zu unerwartetem Programmverhalten führen:

  • Code berücksichtigt möglicherweise nicht angeforderte Änderungen an der Gleitkommaumgebung,

  • Die Gleitkommastatusregister melden möglicherweise keine erwarteten oder aktuellen Ergebnisse,

  • Unerwartete Gleitkomma-Ausnahmen können auftreten oder erwartete Gleitkomma-Ausnahmen können nicht auftreten.

Wenn Ihr Code auf die Gleitkommaumgebung zugreift oder ändert, müssen Sie vorsichtig sein, wenn Sie Code kombinieren, der fenv_access mit Code aktiviert ist, der nicht fenv_access aktiviert ist. In Code, in dem fenv_access nicht aktiviert ist, geht der Compiler davon aus, dass die Plattformstandard-Gleitkommaumgebung wirksam ist. Außerdem wird davon ausgegangen, dass auf den Gleitkommastatus nicht zugegriffen oder geändert wird. Es wird empfohlen, die lokale Gleitkommaumgebung in ihrem Standardzustand zu speichern und wiederherzustellen, bevor das Steuerelement auf eine Funktion übertragen wird, die nicht aktiviert ist fenv_access . In diesem Beispiel wird veranschaulicht, wie das float_control Pragma festgelegt und wiederhergestellt werden kann:

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

Gleitkomma-Rundungsmodi

Sowohl unter als auch /fp:precise/fp:fast, generiert der Compiler Code, der in der Standard-Gleitkommaumgebung ausgeführt werden soll. Es wird davon ausgegangen, dass zur Laufzeit nicht auf die Umgebung zugegriffen oder geändert wird. Das heißt, der Compiler geht davon aus, dass der Code niemals Gleitkomma-Ausnahmen entpackt, Gleitkommastatusregister liest oder schreibt oder Roundingmodi ändert. Einige Programme müssen jedoch die Gleitkommaumgebung ändern. In diesem Beispiel werden beispielsweise Fehlergrenzen für eine Gleitkomma-Multiplikation durch Ändern von Gleitkomma-Rundungsmodi berechnet:

// 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;
}

Da der Compiler die Standard-Gleitkommaumgebung unternimmt /fp:fast und /fp:precise, ist es frei, die Aufrufe zu _controlfp_signorieren. Wenn Sie beispielsweise sowohl die x86-Architektur als auch /O2/fp:precise die x86-Architektur kompiliert haben, werden die Grenzen nicht berechnet, und die Beispielprogrammausgabe wird ausgegeben:

cLower = -inf
cUpper = -inf

Bei der Kompilierung mithilfe sowohl der x86-Architektur als auch /O2/fp:strict der x86-Architektur gibt das Beispielprogramm Folgendes aus:

cLower = -inf
cUpper = -3.40282e+38

Gleitkomma-Sonderwerte

Unter /fp:precise - und /fp:strict, Ausdrücke, die spezielle Werte (NaN, +infinity, -infinity, -0,0) enthalten, verhalten sich gemäß den IEEE-754-Spezifikationen. Unter /fp:fast, das Verhalten dieser speziellen Werte kann mit IEEE-754 inkonsistent sein.

In diesem Beispiel wird das unterschiedliche Verhalten spezieller Werte unter /fp:precise, /fp:strictund /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;
}

Bei der Kompilierung mithilfe /O2 /fp:precise oder /O2 /fp:strict für die x86-Architektur entsprechen die Ausgaben der IEEE-754-Spezifikation:

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

Bei der Kompilierung mithilfe /O2 /fp:fastvon ** für die x86-Architektur sind die Ausgaben nicht mit IEEE-754 konsistent:

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

Algebraische Gleitkommatransformationen

Unter /fp:precise und /fp:strict, der Compiler führt keine mathematische Transformation durch, es sei denn, die Transformation wird garantiert ein bitweise identisches Ergebnis erzeugen. Der Compiler kann solche Transformationen unter /fp:fast. Beispielsweise kann der Ausdruck a * b + a * c in der Beispielfunktion algebraic_transformation in der /fp:fastFolgenden kompiliert a * (b + c) werden. Solche Transformationen werden nicht unter /fp:precise oder /fp:strict, und der Compiler generiert a * b + a * c.

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

Explizite Gleitkomma-Umwandlungspunkte

Unter /fp:precise und /fp:strict, der Compiler rundet auf die Quellcodegenauigkeit an vier bestimmten Punkten während der Ausdrucksauswertung: bei Zuordnungen, Typecasts, wenn Gleitkommaargumente an einen Funktionsaufruf übergeben werden, und wenn ein Funktionsaufruf einen Gleitkommawert zurückgibt. Typecasts können zum expliziten Runden von Zwischenberechnungen verwendet werden. Der /fp:fastCompiler generiert an diesen Punkten keine expliziten Umwandlungen, um die Genauigkeit des Quellcodes zu gewährleisten. In diesem Beispiel wird das Verhalten unter verschiedenen /fp Optionen veranschaulicht:

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

Bei der Kompilierung mithilfe /O2 /fp:precise oder /O2 /fp:strictkönnen Sie sehen, dass explizite Typ casts sowohl am Typecast als auch am Funktionsrücklaufpunkt im generierten Code für die x64-Architektur eingefügt werden:

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

Unter /O2 /fp:fast dem generierten Code wird vereinfacht, da alle Typ casts weg optimiert sind:

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

So legen Sie diese Compileroption in der Visual Studio-Entwicklungsumgebung fest

  1. Öffnen Sie das Dialogfeld Eigenschaftenseiten des Projekts. Weitere Informationen erhalten Sie unter Set C++ compiler and build properties in Visual Studio (Festlegen der Compiler- und Buildeigenschaften (C++) in Visual Studio).

  2. Wählen Sie die Eigenschaftenseite Konfigurationseigenschaften>C/C++>Codegenerierung aus.

  3. Ändern Sie die Gleitkommamodelleigenschaft .

So legen Sie diese Compileroption programmgesteuert fest

Siehe auch

MSVC-Compileroptionen
MSVC-Compiler-Befehlszeilensyntax