Share via


使用 DirectXMath 程式庫的程式碼優化

本主題描述 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 內建對齊版本比未對齊的快。

基於這個理由,使用 XMVECTORXMMATRIX 物件的 DirectXMath 作業會假設這些物件對齊 16 位元組。 如果使用建議的 Windows 來針對 DirectXMath 程式庫編譯器代碼,這會自動進行堆疊式配置, (請參閱 使用正確的編譯 設定) 編譯器設定。 不過,請務必確保包含 XMVECTORXMMATRIX 物件的堆積配置,或轉換成這些類型,符合這些對齊需求。

雖然 64 位 Windows 記憶體配置對齊 16 位元組,但根據預設,32 位版本的已配置的 Windows 記憶體只會對齊 8 位元組。 如需控制記憶體對齊的資訊,請參閱 _aligned_malloc

使用對齊的 DirectXMath 類型搭配標準範本程式庫 (STL) 時,您必須提供自訂配置器,以確保 16 位元組對齊。 如需撰寫自訂配置器 (的範例,請參閱 Visual C++ 小組 部落格 ,而不要使用 malloc/free,而您想要在實作) 中使用_aligned_malloc和_aligned_free。

注意

某些 STL 範本會修改提供的型別對齊方式。 例如,make_shared <>新增一些內部追蹤資訊,這可能會遵守所提供使用者類型的對齊方式,因而造成未對齊的資料成員。 在此情況下,您必須使用未對齊的類型,而不是對齊的類型。 如果您衍生自現有的類別,包括許多 Windows 執行時間物件,您也可以修改類別或結構的對齊方式。

 

盡可能避免運算子多載

為了方便起見,許多類型,例如 XMVECTORXMMATRIX 都有一般算數運算的運算子多載。 這類運算子多載通常會建立許多暫存物件。 建議您避免這些運算子多載在效能敏感的程式碼中。

非正規數

為了支援接近 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

偏好範本表單

XMVectorSwizzleXMVectorPermuteXMVectorInsertXMVectorShiftLeftXMVectorRotateLeft 和 XMVectorRotateRight的範本表單存在。 使用這些而非一般函式表單,可讓編譯器建立更多 efficent 實作。 針對 SSE,這通常會折迭為一或兩個_mm_shuffle_ps值。 針對 ARM-NEON, XMVectorSwizzle 範本可以利用許多特殊案例,而不是更一般的 VTBL swizzle/permute。

搭配 Direct3D 使用 DirectXMath

DirectXMath 的常見用法是執行圖形計算,以搭配 Direct3D 使用。 透過 Direct3D 10.x 和 Direct3D 11.x,您可以透過下列直接方式使用 DirectXMath 程式庫:

DirectXMath 程式設計手冊