Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este tópico descreve as considerações e estratégias de otimização com a Biblioteca DirectXMath.
- Usar acessadores com moderação
- Usar as configurações de compilação corretas
- Usar funções Est quando apropriado
- Usar tipos e operações de dados alinhados
- Alinhar corretamente alocações
- Evitar sobrecargas de operador quando possível
- Desnormals
- Aproveitar a dualidade do ponto flutuante inteiro
- Preferir formulários de modelo
- Usando DirectXMath com Direct3D
- tópicos relacionados
Usar acessadores com moderação
As operações baseadas em vetor usam os conjuntos de instruções SIMD e usam registros especiais. Acessar componentes individuais requer a migração dos registros SIMD para os escalares e voltar novamente.
Quando possível, é mais eficiente inicializar todos os componentes de um XMVECTOR ao mesmo tempo, em vez de usar uma série de acessadores de vetores individuais.
Usar as configurações de compilação corretas
Para destinos do Windows x86, habilite /arch:SSE2. Para todos os destinos do Windows, habilite /fp:fast.
Por padrão, a compilação em relação aos destinos da Biblioteca DirectXMath para Janela x86 é feita com _XM_SSE_INTRINSICS_ definido. Isso significa que todas as funcionalidades do DirectXMath usarão as instruções SSE2. No entanto, o mesmo não é verdadeiro para outro código.
O código fora do DirectXMath é tratado usando padrões do compilador. Sem essa opção, o código gerado geralmente pode usar o código x87 menos eficiente.
É altamente recomendável que você sempre use a versão mais recente disponível do compilador.
Usar funções Est quando apropriado
Muitas funções têm uma função de estimativa equivalente terminando em Est. Essas funções negociam alguma precisão para melhorar o desempenho. As funções Est são apropriadas para cálculos não críticos em que a precisão pode ser sacrificada por velocidade. A quantidade exata de precisão perdida e aumento de velocidade dependem da plataforma.
Por exemplo, a função XMVector3AngleBetweenNormalsEst pode ser usada no lugar da função XMVector3AngleBetweenNormals .
Usar tipos e operações de dados alinhados
Os conjuntos de instruções SIMD em versões do Windows que dão suporte ao SSE2 normalmente têm versões alinhadas e não alinhadas de operações de memória. O uso das operações alinhadas é mais rápido e deve ser preferencial sempre que possível.
A Biblioteca DirectXMath fornece funcionalidade alinhada e desalinhada de acesso por meio de tipos de vetor, estrutura e funções variantes. Essas variantes são indicadas por um "A" no final do nome.
Por exemplo, há uma estrutura de XMFLOAT4X4 não alinhada e uma estrutura XMFLOAT4X4A alinhada, que são usadas pelas funções XMStoreFloat4 e XMStoreFloat4A , respectivamente.
Alinhar corretamente alocações
As versões alinhadas dos intrínsecos da SSE subjacentes à Biblioteca DirectXMath são mais rápidas do que as não atribuídas.
Por esse motivo, as operações DirectXMath usando objetos XMVECTOR e XMMATRIX pressupõem que esses objetos estejam alinhados com 16 bytes. Isso é automático para alocações baseadas em pilha, se o código for compilado na Biblioteca DirectXMath usando as configurações recomendadas do compilador Windows ( consulte Usar Configurações de Compilação Corretas). No entanto, é importante garantir que a alocação de heap que contém objetos XMVECTOR e XMMATRIX ou conversões para esses tipos atenda a esses requisitos de alinhamento.
Embora as alocações de memória do Windows de 64 bits estejam alinhadas a 16 bytes, por padrão, as versões de 32 bits da memória do Windows alocadas são alinhadas apenas a 8 bytes. Para obter informações sobre como controlar o alinhamento de memória, consulte _aligned_malloc.
Ao usar tipos DirectXMath alinhados com a STL (Biblioteca de Modelos Padrão), você precisará fornecer um alocador personalizado que garanta o alinhamento de 16 bytes. Consulte o blog da Equipe do Visual C++ para obter um exemplo de como escrever um alocador personalizado (em vez de malloc/gratuito, você desejará usar _aligned_malloc e _aligned_free em sua implementação).
Observação
Alguns modelos STL modificam o alinhamento do tipo fornecido. Por exemplo, make_shared<> adiciona algumas informações de acompanhamento internas que podem ou não respeitar o alinhamento do tipo de usuário fornecido, resultando em membros de dados não atribuídos. Nesse caso, você precisa usar tipos não alinhados em vez de tipos alinhados. Se você derivar de classes existentes, incluindo muitos objetos do Windows Runtime, também poderá modificar o alinhamento de uma classe ou estrutura.
Evitar sobrecargas de operador quando possível
Como um recurso de conveniência, vários tipos, como XMVECTOR e XMMATRIX , têm sobrecargas de operador para operações aritméticas comuns. Essas sobrecargas de operador tendem a criar vários objetos temporários. Recomendamos que você evite essas sobrecargas de operador no código sensível ao desempenho.
Desnormals
Para dar suporte a cálculos próximos a 0, o padrão de ponto flutuante do IEEE 754 inclui suporte para o fluxo de subfluxo gradual. O fluxo de subfluxo gradual é implementado por meio do uso de valores desnormalizados e muitas implementações de hardware são lentas ao lidar com desnormals. Uma otimização a ser considerada é desabilitar o tratamento de desnormals para as operações de vetor usadas pelo DirectXMath.
A alteração da manipulação de denormal é feita usando a rotina de _controlfp_s em uma base pré-thread e pode resultar em melhorias de desempenho. Use este código para alterar o tratamento de desnormals:
#include <float.h>;
unsigned int control_word;
_controlfp_s( &control_word, _DN_FLUSH, _MCW_DN );
Observação
Em versões de 64 bits do Windows, as instruções SSE são usadas para todos os cálculos, não apenas para as operações de vetor. Alterar o tratamento desnormal afeta todos os cálculos de ponto flutuante em seu programa, não apenas as operações de vetor usadas pelo DirectXMath.
Aproveitar a dualidade do ponto flutuante inteiro
O DirectXMath dá suporte a vetores de 4 valores de ponto flutuante de precisão única ou quatro de 32 bits (assinados ou não assinados).
Como os conjuntos de instruções usados para implementar a Biblioteca DirectXMath têm a capacidade de tratar os mesmos dados que vários tipos diferentes, por exemplo, trate o mesmo vetor que as otimizações de determinados dados de ponto flutuante e inteiro podem ser obtidas. Você pode obter essas otimizações usando as rotinas de inicialização de vetor inteiro e operadores bit a bit para manipular valores de ponto flutuante.
O formato binário de números de ponto flutuante de precisão única usados pela Biblioteca DirectXMath está completamente em conformidade com o padrão IEEE 754:
SIGN EXPONENT MANTISSA
X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX
1 bit 8 bits 23 bits
Ao trabalhar com o número de ponto flutuante de precisão única do IEEE 754, é importante ter em mente que algumas representações têm um significado especial (ou seja, não estão em conformidade com a descrição anterior). Os exemplos incluem:
- Zero positivo é 0
- Zero negativo é 0x80000000
- Q_NAN é 07FC0000
- +INF é 0x7F800000
- -INF é 0xFF800000
Preferir formulários de modelo
O formulário de modelo existe para XMVectorSwizzle, XMVectorPermute, XMVectorInsert, XMVectorShiftLeft, XMVectorRotateLeft e XMVectorRotateRight. Usá-los em vez do formulário de função geral permite que o compilador crie implementações muito mais eficientes. Para a SSE, isso geralmente cai para um ou dois valores _mm_shuffle_ps. Para ARM-NEON, o modelo XMVectorSwizzle pode utilizar vários casos especiais em vez do swizzle/permute VTBL mais geral.
Usando DirectXMath com Direct3D
Um uso comum para DirectXMath é executar cálculos gráficos para uso com o Direct3D. Com o Direct3D 10.x e o Direct3D 11.x, você pode usar a biblioteca DirectXMath destas maneiras diretas:
Use as constantes de namespace Colors diretamente no parâmetro ColorRGBA em uma chamada para o método ID3D11DeviceContext::ClearRenderTargetView ou ID3D10Device::ClearRenderTargetView . Para o Direct3D 9, você deve converter para o tipo XMCOLOR para usá-lo como o parâmetro Color em uma chamada para o método IDirect3DDevice9::Clear .
Use os tiposXMVECTOR/ eXMFLOAT4X4 XMMATRIXXMFLOAT4/ para configurar estruturas de buffer constantes para referência por tipos HLSL float4 ou matrix/float4x4.
Observação
/ XMFLOAT4X4Os tipos XMMATRIX estão em formato de linha principal. Portanto, se você usar o comutador do compilador /Zpr (o sinalizador de compilação D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR) ou omitir a palavra-chave row_major ao declarar o tipo de matriz em HLSL, será necessário transpor a matriz ao defini-la no buffer constante.
Com o Direct3D 10.x e o Direct3D 11.x, você pode supor que o ponteiro retornado pelo método Map (por exemplo, ID3D11DeviceContext::Map) no membro pData (D3D10_MAPPED_TEXTURE2D.pData, D3D10_MAPPED_TEXTURE3D. pData ou D3D11_MAPPED_SUBRESOURCE. pData) será alinhado em 16 bytes se você usar o nível de recurso 10_0 ou superior ou sempre que usar D3D11_USAGE_STAGING recursos.
Tópicos relacionados
-
Guia de Programação DirectXMath