Codeoptimalisatie met de DirectXMath-bibliotheek
In dit onderwerp worden overwegingen en strategieën voor optimalisatie beschreven met de DirectXMath-bibliotheek.
- Gebruik spaarzaam toegangsbeheer
- Juiste compilatie-instellingen gebruiken
- Est-functies gebruiken indien van toepassing
- uitgelijnde gegevenstypen en bewerkingen gebruiken
- toewijzingen correct uitlijnen
- vermijd indien mogelijk operatoroverbelastingen
- Denormals
- profiteren van het dualiteits- voor gehele getallen
- Voorkeur geven aan sjabloonformulieren
- DirectXMath gebruiken met Direct3D-
- Verwante onderwerpen
Toegangsbeheer spaarzaam gebruiken
Vectorgebaseerde bewerkingen maken gebruik van de SIMD-instructiesets en deze maken gebruik van speciale registers. Voor toegang tot afzonderlijke onderdelen moet u overstappen van de SIMD-registers naar de scalaire en weer terug.
Indien mogelijk is het efficiënter om alle onderdelen van een XMVECTOR- tegelijk te initialiseren in plaats van een reeks afzonderlijke vectortoegangsors te gebruiken.
Juiste compilatie-instellingen gebruiken
Schakel /arch:SSE2 in voor Windows x86-doelen. Schakel /fp:fast in voor alle Windows-doelen.
Standaard wordt compilatie uitgevoerd op basis van de DirectXMath-bibliotheek voor Venster x86-doelen met _XM_SSE_INTRINSICS_ gedefinieerd. Dit betekent dat alle DirectXMath-functionaliteit gebruikmaakt van SSE2-instructies. Hetzelfde geldt echter niet voor andere code.
Code buiten DirectXMath wordt verwerkt met behulp van de standaardinstellingen van de compiler. Zonder deze schakeloptie kan de gegenereerde code vaak de minder efficiënte x87-code gebruiken.
We raden u ten zeerste aan altijd de nieuwste beschikbare versie van de compiler te gebruiken.
Est-functies gebruiken indien van toepassing
Veel functies hebben een equivalente schattingsfunctie die eindigt op Est. Deze functies ruilen enige nauwkeurigheid in voor verbeterde prestaties. Est-functies zijn geschikt voor niet-kritieke berekeningen waarbij nauwkeurigheid voor snelheid kan worden opgeofferd. De exacte hoeveelheid verloren nauwkeurigheid en snelheidsverhoging is afhankelijk van het platform.
De functie XMVector3AngleBetweenNormalsEst kan bijvoorbeeld worden gebruikt in plaats van de functie XMVector3AngleBetweenNormals.
Uitgelijnde gegevenstypen en bewerkingen gebruiken
De SIMD-instructiesets op versies van Windows die SSE2 ondersteunen, hebben doorgaans uitgelijnde en niet-uitgelijnde versies van geheugenbewerkingen. Het gebruik van de uitgelijnde bewerkingen is sneller en moet waar mogelijk de voorkeur krijgen.
De DirectXMath-bibliotheek biedt toegang uitgelijnde en niet-uitgelijnde functionaliteit via variantvectortypen, structuur en functies. Deze varianten worden aangegeven door een "A" aan het einde van de naam.
Er is bijvoorbeeld een niet-uitgelijnde XMFLOAT4X4 structuur en een uitgelijnde XMFLOAT4X4A structuur, die respectievelijk worden gebruikt door de XMStoreFloat4- en XMStoreFloat4A functies.
Toewijzingen correct uitlijnen
De uitgelijnde versies van de SSE intrinsieke elementen die onder de DirectXMath-bibliotheek liggen, zijn sneller dan de niet-uitgelijnde bibliotheek.
Daarom gaan DirectXMath-bewerkingen met behulp van XMVECTOR- en XMMATRIX--objecten ervan uit dat deze objecten 16 byte zijn uitgelijnd. Dit is automatisch voor stacktoewijzingen, als code wordt gecompileerd op basis van de DirectXMath-bibliotheek met behulp van de aanbevolen Windows (zie Juiste compilatie-instellingen) compilerinstellingen gebruiken. Het is echter belangrijk om ervoor te zorgen dat heaptoewijzing met XMVECTOR- en XMMATRIX- objecten, of casts naar deze typen, voldoet aan deze uitlijningsvereisten.
Hoewel 64-bits Windows-geheugentoewijzingen 16 byte zijn uitgelijnd, is standaard 32 bitsversies van toegewezen Windows-geheugen slechts 8 byte uitgelijnd. Zie _aligned_mallocvoor meer informatie over het beheren van geheugenuitlijning.
Wanneer u uitgelijnde DirectXMath-typen gebruikt met de Standaardsjabloonbibliotheek (STL), moet u een aangepaste allocator opgeven die zorgt voor de uitlijning van 16 byte. Zie het Visual C++-team blog voor een voorbeeld van het schrijven van een aangepaste allocator (in plaats van malloc/free wilt u _aligned_malloc en _aligned_free gebruiken in uw implementatie).
Notitie
Sommige STL-sjablonen wijzigen de uitlijning van het opgegeven type. make_shared<> bijvoorbeeld enkele interne traceringsgegevens toevoegt die de uitlijning van het opgegeven gebruikerstype wel of niet respecteren, wat resulteert in niet-uitgelijnde gegevensleden. In dit geval moet u niet-uitgelijnde typen gebruiken in plaats van uitgelijnde typen. Als u afgeleid bent van bestaande klassen, inclusief veel Windows Runtime-objecten, kunt u ook de uitlijning van een klasse of structuur wijzigen.
Overbelasting van operatoren voorkomen indien mogelijk
Als handige functie hebben een aantal typen zoals XMVECTOR en XMMATRIX- operatorbelastingen voor algemene rekenkundige bewerkingen. Dergelijke operator-overbelastingen hebben de neiging om talloze tijdelijke objecten te maken. We raden u aan om te voorkomen dat deze operator overbelast raakt in prestatiegevoelige code.
Denormalen
Ter ondersteuning van berekeningen dicht bij 0, bevat de IEEE 754 float-point-standaard ondersteuning voor geleidelijke onderloop. Geleidelijke onderloop wordt geïmplementeerd door het gebruik van gedenormaliseerde waarden en veel hardware-implementaties zijn traag bij het verwerken van denormalen. Een optimalisatie waarmee u rekening moet houden, is het uitschakelen van de verwerking van de denormalen voor de vectorbewerkingen die door DirectXMath worden gebruikt.
Het wijzigen van de verwerking van denormalen wordt uitgevoerd met behulp van de _controlfp_s routine op basis van een pre-thread en kan leiden tot prestatieverbeteringen. Gebruik deze code om de verwerking van denormalen te wijzigen:
#include <float.h>;
unsigned int control_word;
_controlfp_s( &control_word, _DN_FLUSH, _MCW_DN );
Notitie
In 64-bits versies van Windows worden SSE instructies gebruikt voor alle berekeningen, niet alleen voor vectorbewerkingen. Het wijzigen van de normale verwerking is van invloed op alle berekeningen met drijvende komma's in uw programma, niet alleen de vectorbewerkingen die door DirectXMath worden gebruikt.
Profiteer van de dualiteit van gehele getallen
DirectXMath ondersteunt vectoren van vier drijvende kommawaarden met één precisie of vier 32-bits (ondertekende of niet-ondertekende) waarden.
Omdat de instructiesets die worden gebruikt voor het implementeren van de DirectXMath-bibliotheek, dezelfde gegevens kunnen behandelen als meerdere verschillende typen, kunnen bijvoorbeeld dezelfde vector worden behandeld als drijvendekomma- en gehele getallen die bepaalde optimalisaties bieden. U kunt deze optimalisaties verkrijgen met behulp van de initialisatieroutines voor gehele getallen en bitgewijze operators om drijvende-kommawaarden te manipuleren.
De binaire indeling van getallen met één precisie die door de DirectXMath-bibliotheek worden gebruikt, voldoet volledig aan de IEEE 754-standaard:
SIGN EXPONENT MANTISSA
X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX
1 bit 8 bits 23 bits
Wanneer u met het IEEE 754 single precision drijvendekommagetal werkt, is het belangrijk om er rekening mee te houden dat sommige representaties een speciale betekenis hebben (dat wil zeggen dat ze niet voldoen aan de voorgaande beschrijving). Voorbeelden zijn:
- Positief nul is 0
- Negatieve nul is 0x80000000
- Q_NAN is 07FC0000
- +INF is 0x7F800000
- -INF is 0xFF800000
Voorkeur geven aan sjabloonformulieren
Sjabloonformulier bestaat voor XMVectorSwizzle, XMVectorPermute, XMVectorInsert, XMVectorShiftLeft, XMVectorRotateLeften XMVectorRotateRight. Door deze te gebruiken in plaats van de algemene functievorm, kan de compiler veel efficiëntere implementaties maken. Voor SSE-wordt dit vaak samengevouwen tot een of twee _mm_shuffle_ps waarden. Voor ARM-NEON kan de XMVectorSwizzle sjabloon een aantal speciale gevallen gebruiken in plaats van de meer algemene VTBL-swizzle/permute.
DirectXMath gebruiken met Direct3D
Een veelvoorkomend gebruik voor DirectXMath is het uitvoeren van grafische berekeningen voor gebruik met Direct3D. Met Direct3D 10.x en Direct3D 11.x kunt u de DirectXMath-bibliotheek op deze directe manieren gebruiken:
Gebruik de naamruimte Colors constant en rechtstreeks in de parameter ColorRGBA in een aanroep naar de methode ID3D11DeviceContext::ClearRenderTargetView of ID3D10Device::ClearRenderTargetView methode. Voor Direct3D 9 moet u converteren naar het XMCOLOR- type om deze te gebruiken als de parameter Color in een aanroep naar de methode IDirect3DDevice9::Clear.
Gebruik de XMFLOAT4/XMVECTOR en XMFLOAT4X4/XMMATRIX- typen om constante bufferstructuren in te stellen voor referentie door HLSL float4- of matrix/float4x4-typen.
Notitie
XMFLOAT4X4/XMMATRIX- typen hebben een primaire indeling voor rijen. Dus als u de /Zpr compiler-switch (de D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR compiler vlag) gebruikt of het row_major trefwoord weglaat wanneer u het matrixtype in HLSL declareert, moet u de matrix transponeren wanneer u deze in de constante buffer instelt.
Met Direct3D 10.x en Direct3D 11.x kunt u ervan uitgaan dat de aanwijzer wordt geretourneerd door de kaartmethode (bijvoorbeeld ID3D11DeviceContext::Map) in het pData lid (D3D10_MAPPED_TEXTURE2D.pData, D3D10_MAPPED_TEXTURE3D.pDataof D3D11_MAPPED_SUBRESOURCE.pData) is uitgelijnd als u functieniveau 10_0 of hoger of wanneer u D3D11_USAGE_STAGING resources gebruikt.