Condividi tramite


Ottimizzazione del codice con la libreria DirectXMath

In questo argomento vengono descritte le considerazioni e le strategie di ottimizzazione con la libreria DirectXMath.

Usare le funzioni di accesso con moderazione

Le operazioni basate su vettori usano i set di istruzioni SIMD e questi usano registri speciali. L'accesso ai singoli componenti richiede lo spostamento dai registri SIMD a quelli scalari e di nuovo.

Quando possibile, è più efficiente inizializzare tutti i componenti di un XMVECTOR contemporaneamente, anziché usare una serie di singole funzioni di accesso vettoriali.

Usare le impostazioni di compilazione corrette

Per le destinazioni Windows x86, abilitare /arch:SSE2. Per tutte le destinazioni Windows, abilitare /fp:fast.

Per impostazione predefinita, la compilazione sulla libreria DirectXMath per le destinazioni Window x86 viene eseguita con _XM_SSE_INTRINSICS_ definito. Ciò significa che tutte le funzionalità DirectXMath useranno le istruzioni di SSE2. Tuttavia, lo stesso non è vero per altri codici.

Il codice all'esterno di DirectXMath viene gestito usando le impostazioni predefinite del compilatore. Senza questa opzione, il codice generato può spesso usare il codice x87 meno efficiente.

È consigliabile usare sempre la versione più recente disponibile del compilatore.

Usare le funzioni Est quando appropriato

Molte funzioni hanno una funzione di stima equivalente che termina in Est. Queste funzioni scambiano una certa precisione per migliorare le prestazioni. Le funzioni Est sono appropriate per calcoli non critici in cui l'accuratezza può essere sacrificata per la velocità. La quantità esatta di accuratezza e aumento della velocità persa dipende dalla piattaforma.

Ad esempio, la funzione XMVector3AngleBetweenNormalsEst può essere usata al posto della funzione XMVector3AngleBetweenNormals .

Usare tipi di dati e operazioni allineati

I set di istruzioni SIMD nelle versioni di windows che supportano SSE2 in genere hanno versioni allineate e non idonee delle operazioni di memoria. L'uso delle operazioni allineate è più veloce e deve essere preferito laddove possibile.

La libreria DirectXMath fornisce l'accesso alle funzionalità allineate e non idonee tramite tipi di vettore varianti, struttura e funzioni. Queste varianti sono indicate da una "A" alla fine del nome.

Ad esempio, sono presenti una struttura di XMFLOAT4X4 non allineata e una struttura XMFLOAT4X4A allineata, che vengono usate rispettivamente dalle funzioni XMStoreFloat4 e XMStoreFloat4A .

Allinea correttamente le allocazioni

Le versioni allineate delle funzioni intrinseche SSE sottostanti la libreria DirectXMath sono più veloci rispetto a quelle non allineate.

Per questo motivo, le operazioni DirectXMath che usano oggetti XMVECTOR e XMMATRIX presuppongono che tali oggetti siano allineati a 16 byte. Questa operazione è automatica per le allocazioni basate su stack, se il codice viene compilato in base alla libreria DirectXMath usando le impostazioni consigliate del compilatore (vedere Usare le impostazioni di compilazione corrette). Tuttavia, è importante assicurarsi che l'allocazione dell'heap contenente oggetti XMVECTOR e XMMATRIX o il cast a questi tipi soddisfi questi requisiti di allineamento.

Anche se le allocazioni di memoria di Windows a 64 bit sono allineate a 16 byte, per impostazione predefinita nelle versioni a 32 bit della memoria di Windows allocate è allineato solo a 8 byte. Per informazioni sul controllo dell'allineamento della memoria, vedere _aligned_malloc.

Quando si usano tipi DirectXMath allineati con la libreria di modelli standard (STL), è necessario fornire un allocatore personalizzato che garantisce l'allineamento a 16 byte. Vedere il blog del team di Visual C++ per un esempio di scrittura di un allocatore personalizzato (invece di malloc/free, è consigliabile usare _aligned_malloc e _aligned_free nell'implementazione).

Annotazioni

Alcuni modelli STL modificano l'allineamento del tipo specificato. Ad esempio, make_shared<> aggiunge alcune informazioni di rilevamento interne che potrebbero o meno rispettare l'allineamento del tipo di utente specificato, generando membri dati non idonei. In questo caso, è necessario usare tipi non allineati anziché tipi allineati. Se si deriva da classi esistenti, inclusi molti oggetti Windows Runtime, è anche possibile modificare l'allineamento di una classe o di una struttura.

 

Evitare overload degli operatori quando possibile

Come funzionalità di praticità, diversi tipi, ad esempio XMVECTOR e XMMATRIX , dispongono di overload degli operatori per operazioni aritmetiche comuni. Tali overload di operatore tendono a creare numerosi oggetti temporanei. È consigliabile evitare questi overload degli operatori nel codice sensibile alle prestazioni.

Denormali

Per supportare i calcoli vicini a 0, lo standard IEEE 754 a virgola mobile include il supporto per un underflow graduale. L'underflow graduale viene implementato tramite l'uso di valori denormalizzati e molte implementazioni hardware sono lente durante la gestione dei denormali. Un'ottimizzazione da considerare consiste nel disabilitare la gestione dei denormali per le operazioni vettoriali usate da DirectXMath.

La modifica della gestione dei denormali viene eseguita usando la routine _controlfp_s su base prethread e può comportare miglioramenti delle prestazioni. Usare questo codice per modificare la gestione dei denormali:

  #include <float.h>;
    unsigned int control_word;
    _controlfp_s( &control_word, _DN_FLUSH, _MCW_DN );

Annotazioni

Nelle versioni a 64 bit di Windows, le istruzioni SSE vengono usate per tutti i calcoli, non solo per le operazioni vettoriali. La modifica della gestione denormale influisce su tutti i calcoli a virgola mobile nel programma, non solo sulle operazioni vettoriali usate da DirectXMath.

 

Sfruttare i vantaggi della dualità a virgola mobile integer

DirectXMath supporta vettori di 4 valori a virgola mobile e precisione singola o quattro valori a 32 bit (con segno o senza segno).

Poiché i set di istruzioni usati per implementare la libreria DirectXMath hanno la possibilità di trattare gli stessi dati come più tipi diversi, ad esempio, trattare lo stesso vettore come ottimizzazioni a virgola mobile e integer di dati determinati. È possibile ottenere queste ottimizzazioni usando le routine di inizializzazione del vettore integer e gli operatori bit-wise per modificare i valori a virgola mobile.

Il formato binario dei numeri a virgola mobile a precisione singola usata dalla libreria DirectXMath è completamente conforme allo standard IEEE 754:

     SIGN    EXPONENT   MANTISSA
     X       XXXXXXXX   XXXXXXXXXXXXXXXXXXXXXXX
     1 bit   8 bits     23 bits

Quando si lavora con il numero a virgola mobile a precisione singola IEEE 754, è importante tenere presente che alcune rappresentazioni hanno un significato speciale ,ovvero non sono conformi alla descrizione precedente. Gli esempi includono:

  • Zero positivo è 0
  • Zero negativo è 0x80000000
  • Q_NAN è 07FC0000
  • +INF è 0x7F800000
  • -INF è 0xFF800000

Preferisce moduli modello

Il modulo modello esiste per XMVectorSwizzle, XMVectorPermute, XMVectorInsert, XMVectorShiftLeft, XMVectorRotateLeft e XMVectorRotateRight. L'uso di questi invece del formato di funzione generale consente al compilatore di creare implementazioni molto più efficienti. Per la crittografia del servizio di archiviazione, spesso si comprime fino a uno o due valori _mm_shuffle_ps. Per ARM-NEON, il modello XMVectorSwizzle può usare un certo numero di casi speciali anziché il vtbl più generale swizzle/permute.

Uso di DirectXMath con Direct3D

Un uso comune per DirectXMath consiste nell'eseguire calcoli grafici da usare con Direct3D. Con Direct3D 10.x e Direct3D 11.x, è possibile usare la libreria DirectXMath in questi modi diretti:

Guida per programmatori DirectXMath