Оптимизация кода с помощью библиотеки DirectXMath

В этом разделе описываются рекомендации по оптимизации и стратегии использования библиотеки DirectXMath.

Использование методов доступа с осторожностью

Операции на основе векторов используют наборы инструкций SIMD и используют специальные регистры. Для доступа к отдельным компонентам требуется переход от регистров SIMD к скалярным и обратно.

По возможности эффективнее инициализировать все компоненты XMVECTOR одновременно, а не использовать ряд отдельных векторных методов доступа.

Использование правильных параметров компиляции

Для целевых объектов Windows x86 включите параметр /arch:SSE2. Для всех целевых объектов Windows включите параметр /fp:fast.

По умолчанию компиляция для целевых объектов Библиотеки DirectXMath для Windows x86 выполняется с помощью _XM_SSE_INTRINSICS_ определенных. Это означает, что все функции DirectXMath будут использовать инструкции SSE2. Однако то же самое не относится к другому коду.

Код за пределами DirectXMath обрабатывается с помощью значений по умолчанию компилятора. Без этого параметра созданный код часто может использовать менее эффективный код x87.

Настоятельно рекомендуется всегда использовать последнюю доступную версию компилятора.

При необходимости используйте функции Est

Многие функции имеют эквивалентную функцию оценки, заканчивающуюся на Est. Эти функции торгуют некоторой точностью для повышения производительности. Функции Est подходят для некритических вычислений, где точность может быть пожертвована для скорости. Точный объем потерянной точности и увеличение скорости зависят от платформы.

Например, вместо функции XMVector3AngleBetweenNormalsEst можно использовать функцию XMVector3AngleBetweenNormals .

Использование согласованных типов данных и операций

Наборы инструкций SIMD для версий Windows, поддерживающих SSE2, обычно имеют выровненные и несогласованные версии операций с памятью. Использование выровненных операций выполняется быстрее и должно быть предпочтительнее везде, где это возможно.

Библиотека DirectXMath предоставляет доступ к выровненным и несвязанным функциям с помощью типов вариантных векторов, структуры и функций. Эти варианты обозначены "A" в конце имени.

Например, существуют неровная структура XMFLOAT4X4 и выровненная структура XMFLOAT4X4A , которые используются функциями XMStoreFloat4 и XMStoreFloat4A соответственно.

Правильное выравнивание выделений

Выровненные версии встроенных компонентов SSE , лежащих в основе библиотеки DirectXMath, быстрее, чем несвязанные.

По этой причине операции DirectXMath с использованием объектов XMVECTOR и XMMATRIX предполагают, что эти объекты выровнены по 16 байтам. Это автоматическое действие для распределения на основе стека, если код компилируется в библиотеке DirectXMath с помощью рекомендуемых параметров компилятора Windows (см . раздел Использование правильных параметров компиляции). Однако важно убедиться, что выделение кучи, содержащее объекты 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. Использование этих функций вместо общей формы функции позволяет компилятору создавать гораздо более емкие реализации. Для SSE это часто сворачивается до одного или двух _mm_shuffle_ps значений. Для ARM-NEON шаблон XMVectorSwizzle может использовать несколько особых случаев, а не более общий swizzle/permute.

Использование DirectXMath с Direct3D

Обычно DirectXMath используется для выполнения графических вычислений для использования с Direct3D. В Direct3D 10.x и Direct3D 11.x библиотеку DirectXMath можно использовать следующими прямыми способами:

Руководство по программированию DirectXMath