Share via


Ottimizzazione del codice con la libreria DirectXMath

Questo argomento descrive 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 usano registri speciali. Per accedere ai singoli componenti è necessario passare dai registri SIMD a quelli scalari e tornare indietro.

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ù rapido e deve essere preferito laddove possibile.

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

Ad esempio, sono presenti una struttura XMFLOAT4X4 non allineata e una struttura XMFLOAT4X4A allineata, usata rispettivamente dalle funzioni XMStoreFloat4 e XMStoreFloat4A .

Allinea correttamente le allocazioni

Le versioni allineate degli intrinseci 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 alle impostazioni del compilatore DirectXMath usando le impostazioni del compilatore consigliate (vedere Usa impostazioni di compilazione corrette). Tuttavia, è importante assicurarsi che l'allocazione dell'heap contenente oggetti XMVECTOR e XMMATRIX o esegue il cast a questi tipi, soddisfi questi requisiti di allineamento.

Sebbene le allocazioni di memoria di Windows a 64 bit siano 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).

Nota

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 allineati. 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

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

Valori denormalizzati

Per supportare i calcoli vicini a 0, lo standard IEEE 754 a virgola mobile include il supporto per l'underflow graduale. L'underflow graduale viene implementato tramite l'uso di valori denormalizzati e molte implementazioni hardware sono lente durante la gestione delle 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 );

Nota

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 la doppia virgola mobile integer

DirectXMath supporta vettori con 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, considerare lo stesso vettore come ottimizzazioni a virgola mobile e dati integer-certain. È possibile ottenere queste ottimizzazioni usando le routine di inizializzazione dei vettori integer e gli operatori bit-wise per modificare i valori a virgola mobile.

Il formato binario dei numeri a virgola mobile e precisione singola usati 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. Tra gli esempi sono inclusi:

  • 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ù efficenti. Per la crittografia del servizio di archiviazione, questo spesso comprime uno o due valori _mm_shuffle_ps. Per ARM-NEON, il modello XMVectorSwizzle può usare diversi casi speciali anziché vtbl swizzle/permute più generali.

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