Codeoptimierung mit der DirectXMath-Bibliothek
In diesem Thema werden Optimierungsüberlegungen und Strategien mit der DirectXMath-Bibliothek beschrieben.
- Sparsame Verwendung von Accessoren
- Verwenden der richtigen Kompilierungseinstellungen
- Verwenden von Est-Funktionen bei Bedarf
- Verwenden von ausgerichteten Datentypen und Vorgängen
- Zuordnungen ordnungsgemäß ausrichten
- Vermeiden von Operatorüberladungen nach Möglichkeit
- Denormals
- Nutzen der Ganzzahl-Gleitkomma-Dualität
- Vorlagenformulare bevorzugen
- Verwenden von DirectXMath mit Direct3D-
- Verwandte Themen
Sparsames Verwenden von Accessoren
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 Skalaren und wieder zurück zu wechseln.
Wenn möglich, ist es effizienter, alle Komponenten eines XMVECTOR gleichzeitig zu initialisieren, anstatt eine Reihe einzelner Vektoraccessoren zu verwenden.
Verwenden der richtigen Kompilierungseinstellungen
Aktivieren Sie für Windows x86-Ziele /arch:SSE2. Aktivieren Sie für alle Windows-Ziele /fp:fast.
Standardmäßig erfolgt die Kompilierung der DirectXMath-Bibliothek für Fenster x86-Ziele mit _XM_SSE_INTRINSICS_ definiert. Dies bedeutet, dass alle DirectXMath-Funktionen SSE2-Anweisungen verwenden. Dasselbe gilt jedoch nicht für anderen Code.
Code außerhalb von DirectXMath wird mithilfe von Compilerstandardeinstellungen behandelt. Ohne diesen Schalter kann der generierte Code häufig den weniger effizienten x87-Code verwenden.
Es wird dringend empfohlen, immer die neueste verfügbare Version des Compilers zu verwenden.
Verwenden von Est-Funktionen bei Bedarf
Viele Funktionen haben eine entsprechende Schätzungsfunktion, die auf "Est" endet. Diese Funktionen tauschen eine gewisse Genauigkeit für eine verbesserte Leistung aus. Die Est-Funktionen eignen sich für nicht kritische Berechnungen, bei denen die Genauigkeit für Geschwindigkeit geopfert werden kann. Die genaue Menge an verlorener Genauigkeit und Geschwindigkeitssteigerung sind plattformabhängig.
Beispielsweise kann die XMVector3AngleBetweenNormalsEst Funktion anstelle der XMVector3AngleBetweenNormals Funktion verwendet werden.
Verwenden von ausgerichteten Datentypen und Vorgängen
Die SIMD-Anweisungssätze für Versionen von Windows, die SSE2 unterstützen, weisen in der Regel ausgerichtete und nicht ausgerichtete Versionen von Speichervorgängen auf. Die Verwendung der ausgerichteten Vorgänge ist schneller und sollte möglichst bevorzugt werden.
Die DirectXMath-Bibliothek bietet Zugriff auf ausgerichtete und nicht ausgerichtete Funktionen über Variantenvektortypen, -struktur und -funktionen. Diese Varianten werden am Ende des Namens durch ein "A" angegeben.
Beispielsweise gibt es eine nicht ausgerichtete XMFLOAT4X4 Struktur und eine ausgerichtete XMFLOAT4X4A Struktur, die von den funktionen XMStoreFloat4 bzw. XMStoreFloat4A verwendet werden.
Zuordnungen ordnungsgemäß ausrichten
Die ausgerichteten Versionen der SSE systeminternen Zugrunde liegenden DirectXMath-Bibliothek sind schneller als die nicht ausgerichtete.
Aus diesem Grund gehen DirectXMath-Vorgänge mit XMVECTOR- und XMMATRIX- Objekte davon aus, dass diese Objekte 16-Byte ausgerichtet sind. Dies ist automatisch für stapelbasierte Zuordnungen, wenn Code mithilfe der empfohlenen Windows-Compilereinstellungen (siehe Verwenden der korrekten Kompilierungseinstellungen) kompiliert wird. Es ist jedoch wichtig, sicherzustellen, dass die Heap-Zuordnung, die XMVECTOR- und XMMATRIX--Objekte enthält, oder diese Typen zu umwandeln, diese Ausrichtungsanforderungen erfüllen.
Während 64-Bit-Windows-Speicherzuordnungen 16-Byte ausgerichtet sind, ist standardmäßig für 32-Bit-Versionen des zugewiesenen Windows-Speichers nur 8 Byte ausgerichtet. Informationen zum Steuern der Speicherausrichtung finden Sie unter _aligned_malloc.
Bei Verwendung ausgerichteter DirectXMath-Typen mit der Standardvorlagenbibliothek (Standard Template Library, STL) müssen Sie einen benutzerdefinierten Allocator bereitstellen, der die Ausrichtung von 16 Byte gewährleistet. Im Visual C++-Team Blog- finden Sie ein Beispiel zum Schreiben eines benutzerdefinierten Allocators (anstelle von malloc/free möchten Sie _aligned_malloc und _aligned_free in Ihrer Implementierung verwenden).
Anmerkung
Einige STL-Vorlagen ändern die Ausrichtung des bereitgestellten Typs. Beispielsweise fügt make_shared<> einige interne Nachverfolgungsinformationen hinzu, die möglicherweise die Ausrichtung des bereitgestellten Benutzertyps respektieren, was zu nicht ausgerichteten Datenmitgliedern führt. In diesem Fall müssen Sie nicht ausgerichtete Typen verwenden, sondern nicht ausgerichtete Typen. Wenn Sie von vorhandenen Klassen ableiten, einschließlich vieler Windows-Runtime-Objekte, können Sie auch die Ausrichtung einer Klasse oder Struktur ändern.
Vermeiden von Operatorüberladungen nach Möglichkeit
Eine Reihe von Typen wie XMVECTOR und XMMATRIX haben Operatorüberladungen für gängige arithmetische Vorgänge. Solche Operatorüberladungen erzeugen in der Regel zahlreiche temporäre Objekte. Es wird empfohlen, diese Operatorüberladungen im leistungssensitiven Code zu vermeiden.
Denormals
Zur Unterstützung von Berechnungen in der Nähe von 0 umfasst der IEEE 754-Gleitkommastandard Unterstützung für schrittweisen Unterlauf. Schrittweiser Unterlauf wird durch die Verwendung von denormalisierten Werten implementiert, und bei der Behandlung von Denormalen sind viele Hardwareimplementierungen langsam. Eine Optimierung ist die Deaktivierung der Behandlung von Denormalen für die von DirectXMath verwendeten Vektorvorgänge.
Das Ändern der Behandlung von Denormalen erfolgt mithilfe der _controlfp_s Routine auf Vorabthreadbasis und kann zu Leistungsverbesserungen führen. Verwenden Sie diesen Code, um die Behandlung von Denormalen zu ändern:
#include <float.h>;
unsigned int control_word;
_controlfp_s( &control_word, _DN_FLUSH, _MCW_DN );
Anmerkung
In 64-Bit-Versionen von Windows werden SSE- Anweisungen für alle Berechnungen verwendet, nicht nur für die Vektorvorgänge. Das Ändern der Denormalbehandlung wirkt sich auf alle Gleitkommaberechnungen in Ihrem Programm aus, nicht nur auf die von DirectXMath verwendeten Vektorvorgänge.
Nutzen der Ganzzahl-Gleitkomma-Dualität
DirectXMath unterstützt Vektoren von 4 Gleitkommawerten mit einfacher Genauigkeit oder vier 32-Bit-Werten (signiert oder nicht signiert).
Da die zum Implementieren der DirectXMath-Bibliothek verwendeten Anweisungssätze die Möglichkeit haben, dieselben Daten wie mehrere verschiedene Typen zu behandeln, können Sie beispielsweise denselben Vektor wie Gleitkomma- und ganzzahlige Datenoptimierungen erzielen. Sie können diese Optimierungen mithilfe der Ganzzahlvektorinitialisierungsroutinen und bitweisen Operatoren abrufen, um Gleitkommawerte zu bearbeiten.
Das binäre Format von Gleitkommazahlen mit einfacher Genauigkeit, die von der DirectXMath Library verwendet werden, entspricht vollständig dem IEEE 754-Standard:
SIGN EXPONENT MANTISSA
X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX
1 bit 8 bits 23 bits
Beim Arbeiten mit der IEEE 754-Gleitkommazahl mit einfacher Genauigkeit ist es wichtig zu beachten, dass einige Darstellungen eine besondere Bedeutung haben (d. h., sie entsprechen nicht der vorherigen Beschreibung). Beispiele sind:
- Positive Null ist 0
- Negative Null ist 0x80000000
- Q_NAN ist 07FC0000
- +INF ist 0x7F800000
- -INF ist 0xFF800000
Vorlagenformulare bevorzugen
Vorlagenformular ist für XMVectorSwizzle, XMVectorPermute, XMVectorInsert, XMVectorShiftLeft, XMVectorRotateLeft, und XMVectorRotateRight. Die Verwendung dieser anstelle des allgemeinen Funktionsformulars ermöglicht es dem Compiler, wesentlich effizientere Implementierungen zu erstellen. Bei SSE-reduziert sich dies häufig auf einen oder zwei _mm_shuffle_ps Werte. Bei ARM-NEON kann die XMVectorSwizzle Vorlage eine Reihe von Sonderfällen anstelle der allgemeineren VTBL-Swizzle/Permute verwenden.
Verwenden von DirectXMath mit Direct3D
Eine häufige Verwendung für DirectXMath ist das Ausführen von Grafikberechnungen für die Verwendung mit Direct3D. Mit Direct3D 10.x und Direct3D 11.x können Sie die DirectXMath-Bibliothek auf folgende direkte Weise verwenden:
Verwenden Sie den Colors-Namespace Konstanten 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 XMFLOAT4X4/XMMATRIX- Typen, um konstanten Pufferstrukturen für den Verweis durch HLSL float4-- oder Matrixtypen/float4x4-Typen einzurichten.
Anmerkung
XMFLOAT4X4/XMMATRIX- Typen im Zeilen-Hauptformat vorliegen. Wenn Sie daher den Compilerschalter /Zpr (das D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR Kompilierungskennzeichen) verwenden oder das row_major Schlüsselwort weglassen, wenn Sie den Matrixtyp in HLSL deklarieren, müssen Sie die Matrix transponieren, wenn Sie sie in den Konstantenpuffer 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.pData, D3D10_MAPPED_TEXTURE3D.pDataoder D3D11_MAPPED_SUBRESOURCE.pData) ist 16-Byte ausgerichtet, wenn Sie Featureebene 10_0 oder höher oder immer, wenn Sie D3D11_USAGE_STAGING Ressourcen verwenden.