使用 DirectXMath 程式庫的程式碼優化
本主題描述 DirectXMath 程式庫的優化考慮和策略。
- 謹慎使用存取子
- 使用正確的編譯設定
- 適當時使用 Est 函式
- 使用對齊的資料類型和作業
- 正確對齊配置
- 盡可能避免運算子多載
- 非正規數
- 利用整數浮點雙重
- 偏好範本表單
- 搭配 Direct3D 使用 DirectXMath
- 相關主題
謹慎使用存取子
向量型作業會使用 SIMD 指令集,而這些作業會使用特殊暫存器。 存取個別元件需要從 SIMD 暫存器移至純量暫存器,然後再次返回。
可能的話,一次初始化 XMVECTOR 的所有元件會更有效率,而不是使用一系列的個別向量存取子。
使用正確的編譯設定
針對 Windows x86 目標,請啟用 /arch:SSE2。 針對所有 Windows 目標,啟用 /fp:fast。
根據預設,針對 Window x86 目標的 DirectXMath 程式庫進行編譯時,會定義_XM_SSE_INTRINSICS_。 這表示所有 DirectXMath 功能都會使用 SSE2 指示。 不過,其他程式碼也是如此。
DirectXMath 以外的程式碼會使用編譯器預設值來處理。 如果沒有此參數,產生的程式碼通常會使用較不有效率的 x87 程式碼。
強烈建議您一律使用最新可用的編譯器版本。
適當時使用 Est 函式
許多函式都有以 Est 結尾的對等估計函式。 這些函式會交易一些精確度,以改善效能。 Est 函式適用于可犧牲速度的非關鍵計算。 確切的遺失精確度和速度增加量取決於平臺。
例如, XMVector3AngleBetweenNormalsEst 函式可用來取代 XMVector3AngleBetweenNormals 函 式。
使用對齊的資料類型和作業
支援 SSE2 之 Windows 版本的 SIMD 指令集通常會對齊和未對齊的記憶體作業版本。 對齊作業的使用速度較快,而且應該盡可能優先使用。
DirectXMath 程式庫可透過變異向量類型、結構和函式,提供對齊和未對齊的功能。 這些變體會以名稱結尾的 「A」 表示。
例如,有未對齊的 XMFLOAT4X4結構和對齊的XMFLOAT4X4A結構,分別由XMStoreFloat4 和 XMStoreFloat4A函式使用。
正確對齊配置
DirectXMath 程式庫基礎的 SSE 內建對齊版本比未對齊的快。
基於這個理由,使用 XMVECTOR 和 XMMATRIX 物件的 DirectXMath 作業會假設這些物件對齊 16 位元組。 如果使用建議的 Windows 來針對 DirectXMath 程式庫編譯器代碼,這會自動進行堆疊式配置, (請參閱 使用正確的編譯 設定) 編譯器設定。 不過,請務必確保包含 XMVECTOR 和 XMMATRIX 物件的堆積配置,或轉換成這些類型,符合這些對齊需求。
雖然 64 位 Windows 記憶體配置對齊 16 位元組,但根據預設,32 位版本的已配置的 Windows 記憶體只會對齊 8 位元組。 如需控制記憶體對齊的資訊,請參閱 _aligned_malloc。
使用對齊的 DirectXMath 類型搭配標準範本程式庫 (STL) 時,您必須提供自訂配置器,以確保 16 位元組對齊。 如需撰寫自訂配置器 (的範例,請參閱 Visual C++ 小組 部落格 ,而不要使用 malloc/free,而您想要在實作) 中使用_aligned_malloc和_aligned_free。
注意
某些 STL 範本會修改提供的型別對齊方式。 例如,make_shared <>新增一些內部追蹤資訊,這可能會遵守所提供使用者類型的對齊方式,因而造成未對齊的資料成員。 在此情況下,您必須使用未對齊的類型,而不是對齊的類型。 如果您衍生自現有的類別,包括許多 Windows 執行時間物件,您也可以修改類別或結構的對齊方式。
盡可能避免運算子多載
為了方便起見,許多類型,例如 XMVECTOR 和 XMMATRIX 都有一般算數運算的運算子多載。 這類運算子多載通常會建立許多暫存物件。 建議您避免這些運算子多載在效能敏感的程式碼中。
非正規數
為了支援接近 0 的計算,IEEE 754 浮點標準包含漸進式下溢的支援。 漸進式下流是透過使用反正規化值來實作,而處理反正規化時許多硬體實作速度很慢。 要考慮的優化是停用 DirectXMath 所使用向量作業的反惡意程式碼處理。
變更反惡意程式碼的處理是透過線上程前使用 _controlfp_s 常式來完成,而且可能會導致效能改善。 使用此程式碼來變更反惡意程式碼的處理:
#include <float.h>;
unsigned int control_word;
_controlfp_s( &control_word, _DN_FLUSH, _MCW_DN );
注意
在 64 位版本的 Windows 上, SSE 指令會用於所有計算,而不只是向量作業。 變更反正規處理會影響程式中的所有浮點運算,而不只是 DirectXMath 所使用的向量運算。
利用整數浮點雙重
DirectXMath 支援 4 個單精確度浮點數或四個 32 位 (帶正負號或無符號) 值的向量。
由於用來實作 DirectXMath 程式庫的指令集能夠將相同的資料視為多個不同類型,例如,可以將相同的向量視為浮點和整數資料特定優化。 您可以使用整數向量初始化常式和位運算子來操作浮點值,以取得這些優化。
DirectXMath 程式庫所使用的單精確度浮點數二進位格式完全符合 IEEE 754 標準:
SIGN EXPONENT MANTISSA
X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX
1 bit 8 bits 23 bits
使用 IEEE 754 單精確度浮點數時,請務必記住,某些標記法具有特殊意義 (也就是說,它們不符合上述描述) 。 範例包括:
- 正零為 0
- 負零0x80000000
- Q_NAN為 07FC0000
- +INF 已0x7F800000
- -INF 0xFF800000
偏好範本表單
XMVectorSwizzle、XMVectorPermute、XMVectorInsert、XMVectorShiftLeft、XMVectorRotateLeft 和 XMVectorRotateRight的範本表單存在。 使用這些而非一般函式表單,可讓編譯器建立更多 efficent 實作。 針對 SSE,這通常會折迭為一或兩個_mm_shuffle_ps值。 針對 ARM-NEON, XMVectorSwizzle 範本可以利用許多特殊案例,而不是更一般的 VTBL swizzle/permute。
搭配 Direct3D 使用 DirectXMath
DirectXMath 的常見用法是執行圖形計算,以搭配 Direct3D 使用。 透過 Direct3D 10.x 和 Direct3D 11.x,您可以透過下列直接方式使用 DirectXMath 程式庫:
在呼叫ID3D11DeviceCoNtext::ClearRenderTargetView或ID3D10Device::ClearRenderTargetView方法時,直接在ColorRGBA參數中使用 Colors 命名空間常數。 針對 Direct3D 9,您必須轉換成XMCOLOR類型,才能在呼叫IDirect3DDevice9::Clear方法時將其當做Color參數使用。
使用XMFLOAT4/XMVECTOR和XMFLOAT4X4/XMMATRIX類型來設定常數緩衝區結構,以供 HLSL float4或matrix/float4x4 類型參考。
注意
XMFLOAT4X4/XMMATRIX類型是資料列主要格式。 因此,如果您使用 /Zpr 編譯器參數 (D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR 編譯旗標) 或在 HLSL 中宣告矩陣類型時省略 row_major 關鍵字 ,則必須在將矩陣設定為常數緩衝區時轉置矩陣。
使用 Direct3D 10.x 和 Direct3D 11.x,您可以假設 Map 方法所傳回的指標 (例如ID3D11DeviceCoNtext::Map) pData成員 (D3D10_MAPPED_TEXTURE2D。pData,D3D10_MAPPED_TEXTURE3D。pData或D3D11_MAPPED_SUBRESOURCE。如果您使用功能層級10_0 或更新版本,或每當使用D3D11_USAGE_STAGING資源時,pData) 為 16 位元組對齊。