Поделиться через


Оптимизация кода с помощью библиотеки 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 можно использовать вместо функции XMVector3AngleBetweenNormalsXMVector3AngleBetweenNormals.

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

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

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

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

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

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

По этой причине операции DirectXMath с помощью XMVECTOR и объектов XMMATRIX предполагают, что эти объекты выровнены по 16 байтам. Это автоматически для выделения на основе стека, если код компилируется в библиотеке DirectXMath с помощью рекомендуемых параметров компилятора (см. раздел Использовать правильные параметры компиляции) компилятора. Однако важно убедиться, что выделение кучи, содержащее XMVECTOR и объекты XMMATRIX или приведение к этим типам, соответствуют этим требованиям выравнивания.

Хотя 64-разрядные выделения памяти Windows выровнены по 16 байтам, по умолчанию выделены 32-разрядные версии памяти Windows, выравниваются только 8-байтов. Сведения об управлении выравниванием памяти см. в _aligned_malloc.

При использовании выровненных типов DirectXMath с стандартной библиотекой шаблонов (STL) необходимо предоставить пользовательский распределитель, обеспечивающий выравнивание 16-байтов. Пример написания настраиваемого распределителя (вместо malloc/free), который вы хотите использовать _aligned_malloc и _aligned_free в реализации, см. в блоге команды Visual C++.

Заметка

Некоторые шаблоны 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 может использовать ряд особых случаев, а не более общий swizzle/permute.

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

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

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