Codeoptimierung mit der DirectXMath-Bibliothek
In diesem Thema werden Optimierungsüberlegungen und Strategien mit der DirectXMath-Bibliothek beschrieben.
- Verwenden Von Accessoren mit Sparing
- Verwenden der richtigen Kompilierungseinstellungen
- Verwenden Sie gegebenenfalls Est-Funktionen.
- Verwenden von ausgerichteten Datentypen und Vorgängen
- Ordnungsgemäßes Ausrichten von Zuordnungen
- Operatorüberladungen nach Möglichkeit vermeiden
- Abbrüche
- Nutzen der Dualität ganzzahliger Gleitkommawerte
- Vorlagenformulare bevorzugen
- Verwenden von DirectXMath mit Direct3D
- Zugehörige Themen
Verwenden Von Accessoren mit Sparing
Vektorbasierte Vorgänge verwenden die SIMD-Anweisungssätze, und diese verwenden spezielle Register. Für den Zugriff auf einzelne Komponenten ist es erforderlich, von den SIMD-Registern zu den Skalarregistern und wieder zurück zu gehen.
Wenn möglich, ist es effizienter, alle Komponenten eines XMVECTOR gleichzeitig zu initialisieren, anstatt eine Reihe einzelner Vektorzugriffsmethoden zu verwenden.
Verwenden der richtigen Kompilierungseinstellungen
Für Windows x86-Ziele aktivieren Sie /arch:SSE2. Aktivieren Sie für Windows-Ziele /fp:fast.
Standardmäßig erfolgt die Kompilierung für die DirectXMath Library für Window x86-Ziele mit definierten _ XM _ SSE _ _ INTRINSICS. Dies bedeutet, dass alle DirectXMath-Funktionen SSE2-Anweisungen verwenden. Dies gilt jedoch nicht für anderen Code.
Code außerhalb von DirectXMath wird mit Compiler-Standardwerten verarbeitet. Ohne diesen Schalter verwendet der generierte Code häufig den weniger effizienten x87-Code.
Es wird dringend empfohlen, immer die neueste verfügbare Version des Compilers zu verwenden.
Verwenden Sie gegebenenfalls Est-Funktionen.
Viele Funktionen verfügen über eine entsprechende Schätzfunktion, die auf Est endet. Diese Funktionen handeln mit einer bestimmten Genauigkeit, um die Leistung zu verbessern. Est-Funktionen sind für nicht kritische Berechnungen geeignet, bei denen genauigkeitsgefährdt werden kann. Die genaue Menge an verloren gegangener Genauigkeit und Geschwindigkeitssteigerung ist plattformabhängig.
Beispielsweise könnte die XMVector3AngleBetweenNormalsEst-Funktion statt der XMVector3AngleBetweenNormals-Funktion verwendet werden.
Verwenden von ausgerichteten Datentypen und Vorgängen
Die SIMD-Anweisungssätze in Windows-Versionen, die SSE2 unterstützen, verfügen in der Regel über ausgerichtete und nicht ausgerichtete Versionen von Speichervorgängen. Die Verwendung der ausgerichteten Vorgänge ist schneller und sollte nach Möglichkeit bevorzugt werden.
Die DirectXMath-Bibliothek bietet über Variantenvektortypen, -strukturen und -funktionen zugriffsbündige und nicht ausgerichtete Funktionen. Diese Varianten werden durch ein "A" am Ende des Namens angegeben.
Beispielsweise gibt es eine nicht ausgerichtete XMFLOAT4X4-Struktur und eine ausgerichtete XMFLOAT4X4A-Struktur, die von den XMStoreFloat4- bzw. XMStoreFloat4A-Funktionen verwendet werden.
Ordnungsgemäßes Ausrichten von Zuordnungen
Die ausgerichteten Versionen der systeminternen SSE-Eigenschaften, die der DirectXMath-Bibliothek zugrunde liegen, sind schneller als die nicht ausgerichtete.
Aus diesem Grund gehen DirectXMath-Vorgänge mit XMVECTOR- und XMMATRIX-Objekten davon aus, dass diese Objekte 16-Byte-ausgerichtet sind. Dies erfolgt automatisch für stapelbasierte Zuordnungen, wenn Code mithilfe der empfohlenen Windows-Compilereinstellungen für die DirectXMath-Bibliothek kompiliert wird (siehe Verwenden der richtigen Kompilierung Einstellungen). Es ist jedoch wichtig, sicherzustellen, dass die Heapzuordnung, die XMVECTOR- und XMMATRIX-Objekte oder -Casts in diese Typen enthält, diese Ausrichtungsanforderungen erfüllt.
Während 64-Bit-Windows Speicherzuordnungen auf 16 Byte ausgerichtet sind, wird bei 32-Bit-Versionen von Windows der zugeordnete Arbeitsspeicher standardmäßig nur mit 8 Byte ausgerichtet. Informationen zum Steuern der Speicherausrichtung finden Sie unter _ aligned _ malloc.
Wenn Sie ausgerichtete DirectXMath-Typen mit der Standardvorlagenbibliothek (STL) verwenden, müssen Sie eine benutzerdefinierte Zuweisung bereitstellen, die die 16-Byte-Ausrichtung sicherstellt. Im blog Visual C++ Team finden Sie ein Beispiel für das Schreiben einer benutzerdefinierten Zuweisung (anstelle von malloc/free sollten Sie aligned malloc und aligned free in Ihrer Implementierung _ _ _ _ verwenden).
Hinweis
Einige STL-Vorlagen ändern die Ausrichtung des bereitgestellten Typs. Wenn Sie _ beispielsweise freigegebene<>, werden einige interne Nachverfolgungsinformationen hinzufügt, die die Ausrichtung des bereitgestellten Benutzertyps möglicherweise nicht achten, was zu nicht ausgerichteten Datenmitgliedern führt. In diesem Fall müssen Sie nicht ausgerichtete Typen anstelle ausgerichteter Typen verwenden. Wenn Sie von vorhandenen Klassen ableiten, einschließlich vieler Windows Runtime-Objekte, können Sie auch die Ausrichtung einer Klasse oder Struktur ändern.
Operatorüberladungen nach Möglichkeit vermeiden
Zur Vereinfachung verfügen eine Reihe von Typen wie XMVECTOR und XMMATRIX über Operatorüberladungen für gängige arithmetische Operationen. Solche Operatorüberladungen erstellen tendenziell zahlreiche temporäre Objekte. Es wird empfohlen, diese Operatorüberladungen in leistungsempfindlichen Code zu vermeiden.
Abbrüche
Um Berechnungen nahe 0 zu unterstützen, bietet der IEEE 754-Gleitkommastandard Unterstützung für den schrittweisen Unterlauf. Der schrittweise Unterlauf wird durch die Verwendung von denormalisierten Werten implementiert, und viele Hardwareimplementierungen sind langsam, wenn Denormalwerte verwendet werden. Eine zu berücksichtigende Optimierung besteht in der Deaktivierung der Behandlung von Denormals für die von DirectXMath verwendeten Vektoroperationen.
Das Ändern der Behandlung von Denormalen erfolgt mithilfe der _ routine von controlfp _ auf Präthreadbasis und kann zu Leistungsverbesserungen führen. Verwenden Sie diesen Code, um die Behandlung von Denormals zu ändern:
#include <float.h>;
unsigned int control_word;
_controlfp_s( &control_word, _DN_FLUSH, _MCW_DN );
Hinweis
Bei 64-Bit-Versionen von Windows werden SSE-Anweisungen für alle Berechnungen verwendet, nicht nur für Vektorvorgänge. Das Ändern der denormalen Behandlung wirkt sich auf alle Gleitkommaberechnungen in Ihrem Programm aus, nicht nur auf die Vektoroperationen, die von DirectXMath verwendet werden.
Nutzen der Dualität ganzzahliger Gleitkommawerte
DirectXMath unterstützt Vektoren von 4 Gleitkommawerten mit einzelner Genauigkeit oder vier 32-Bit-Werten (mit oder ohne Vorzeichen).
Da die Anweisungssätze, die zum Implementieren der DirectXMath-Bibliothek verwendet werden, dieselben Daten wie mehrere verschiedene Typen behandeln können, können sie z. B. denselben Vektor als Gleitkomma- und ganzzahlige Daten behandeln. Sie können diese Optimierungen erhalten, indem Sie die Initialisierungsroutinen für ganzzahlige Vektoren und bitweise Operatoren verwenden, um Gleitkommawerte zu bearbeiten.
Das binäre Format von Gleitkommazahlen mit einzelner Genauigkeit, das von der DirectXMath Library verwendet wird, entspricht vollständig dem IEEE 764-Standard:
SIGN EXPONENT MANTISSA
X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX
1 bit 8 bits 23 bits
Bei der Arbeit mit der IEEE 764-Gleitkommazahl mit einmaliger Genauigkeit ist es wichtig zu beachten, dass einige Darstellungen eine besondere Bedeutung haben (d. h., sie entsprechen nicht der vorherigen Beschreibung). Beispiele:
- Positive Null ist 0
- Negative Null ist 0x80000000
- Q _ NAN ist 07FC0000
- +INF ist 0x7F800000
- -INF ist 0xFF800000
Vorlagenformulare bevorzugen
Das Vorlagenformular ist für XMVectorSwizzle, XMVectorPermute, XMVectorInsert, XMVectorShiftLeft, XMVectorRotateLeftund XMVectorRotateRight vorhanden. Wenn Sie diese anstelle der allgemeinen Funktionsform verwenden, kann der Compiler wesentlich efficent-Implementierungen erstellen. Bei SSEwird dies häufig auf einen oder zwei _ _ MM-Shuffle-PS-Werte _ reduziert. Für ARM-NEON kann die XMVectorSwizzle-Vorlage eine Reihe von Sonderfällen anstelle der allgemeineren VTBL-Swizzle/Permute verwenden.
Verwenden von DirectXMath mit Direct3D
DirectXMath wird häufig verwendet, um Grafikberechnungen für die Verwendung mit Direct3D durchzuführen. Mit Direct3D 10.x und Direct3D 11.x können Sie die DirectXMath-Bibliothek auf die folgenden direkten Weisen verwenden:
Verwenden Sie die Colors-Namespacekonst constants direkt im ColorRGBA-Parameter in einem Aufruf der ID3D11DeviceContext::ClearRenderTargetView- oder ID3D10Device::ClearRenderTargetView-Methode. Für Direct3D 9 müssen Sie in den XMCOLOR-Typ konvertieren, um ihn als Color-Parameter in einem Aufruf der IDirect3DDevice9::Clear-Methode zu verwenden.
Verwenden Sie die XMFLOAT4 / XMVECTOR- und XMFLOAT4X4XMMATRIX-Typen, um konstante Pufferstrukturen einzurichten, die von / HLSL float4- oder matrix/float4x4-Typen referenziert werden.
Hinweis
XMFLOAT4X4 / XMMATRIX-Typen haben das Zeilen-Hauptformat. Wenn Sie daher den Compilerschalter /Zpr (das Kompilierungsflag D3DCOMPILE _ PACK MATRIX COLUMN _ _ _ MAJOR) verwenden oder das Schlüsselwort row major weglassen, wenn Sie den Matrixtyp in HLSL deklarieren, müssen Sie die Matrix transponieren, wenn Sie sie in den konstanten Puffer _ festlegen.
Bei Direct3D 10.x und Direct3D 11.x können Sie davon ausgehen, dass der von der Map-Methode zurückgegebene Zeiger (z. B. ID3D11DeviceContext::Map)im pData-Member (D3D10 _ MAPPED _ TEXTURE2D) ist.pData, D3D10 _ MAPPED _ TEXTURE3D.pData oder D3D11 _ MAPPED _ SUBRESOURCE.pData) ist auf 16 Byte ausgerichtet, wenn Sie Featureebene 10 0 oder höher verwenden oder wenn Sie _ D3D11 _ USAGE _ STAGING-Ressourcen verwenden.