O FastMath é uma biblioteca de matemática da Delphi que é otimizada para um desempenho rápido (às vezes ao custo de não executar a verificação de erros ou a perda de um pouco de precisão). Ele usa o código de montagem otimizado à mão para obter um desempenho muito melhor do que as funções equivalentes fornecidas pelo Delphi RTL.
Isso torna o FastMath ideal para aplicações de alto desempenho em matemática, como aplicativos e jogos multimídia. Para um desempenho ainda melhor, a biblioteca fornece uma variedade de funções "aproximadas" (que começam com um prefixo Fast ). Isso pode ser muito rápido, mas você perderá uma precisão (às vezes surpreendentemente pequena). Para jogos e animação, essa perda de precisão é geralmente perfeitamente aceitável e superada pelo aumento da velocidade. Não os use para cálculos científicos ...
Você pode ligar para DisableFloatingPointExceptions na inicialização do aplicativo para suprimir quaisquer exceções de ponto flutuante. Em vez disso, ele retornará valores extremos (como NAN ou Infinity) quando uma operação não puder ser executada. Se você usar o FastMath em vários threads, deverá ligar para DisableFloatingPointExceptions no bloco Execute desses threads.
A maioria das operações pode ser realizada em valores singulares (escalares) e vetores (consistindo em 2, 3 ou 4 valores). O código de montagem otimizado do SIMD é usado para calcular várias saídas ao mesmo tempo. Por exemplo, a adição de dois vetores de 4 valores é quase tão rápido quanto a adição de dois valores únicos, resultando em um aumento de velocidade de 4 vezes. Muitas funções são escritas de tal maneira que o desempenho é ainda melhor.
Aqui estão alguns exemplos de fatores de velocidade que você pode esperar em diferentes plataformas:
| Rtl | FastMath | x86-32 | x86-64 | ARM32 | ARM64 |
|---|---|---|---|---|---|
| TVector3D + TVector3D | TVector4 + TVector4 | 1.2x | 1.6x | 2.8x | 2.5x |
| Único * tVector3d | Único * tVector4 | 2.2x | 2.1x | 5.6x | 3.7x |
| TVector3D.Length | TVector4.Length | 3.0x | 5.6x | 19.9x | 17.1x |
| TVector3D.Normalize | TVector4.Normalize | 4.1x | 5.1x | 7.4x | 11.7x |
| TVECTOR3D * TMATRIX3D | TVector4 * tMatrix4 | 1.3x | 4.0x | 6.5x | 4.2x |
| TMatrix3d * tMatrix3d | TMatrix4 * tMatrix4 | 2.2x | 7.2x | 5.4x | 8.0x |
| Tmatrix3d.inverse | Tmatrix4.inverse | 9.8x | 9.2x | 8.0x | 9.8x |
| Pecado (único) (x4) | Fastsin (TVector4) | 14.8x | 7.7x | 42.6x | 40.1x |
| Sincos (single) (x4) | FastSincos (TVector4) | 19.1x | 9.0x | 67.9x | 93.3x |
| Exp2 (único) (x4) | FastExp2 (TVector4) | 22.4x | 32.7x | 275.0x | 302.4x |
Como você pode ver, algumas operações muito comuns (3D), como multiplicação de matrizes e inversão, podem ser quase 10 vezes mais rápidas que as versões RTL correspondentes. Além disso, o FastMath inclui várias funções de aproximação Fast* que sacrificam um pouco de precisão por um enorme aumento de velocidade. Por exemplo, o uso FastSinCos para calcular 4 funções senoidal e cosseno em paralelo pode ser até 90 vezes mais rápido do que chamar a função RTL SinCos 4 vezes, enquanto ainda oferece excelente precisão para ângulos de até +/4000 radianos (ou +/- 230.000 graus).
Em plataformas de desktop de 32 e 64 bits (Windows e OS X), esse desempenho é alcançado usando o conjunto de instruções SSE2. Isso significa que o computador deve suportar SSE2. No entanto, como o SSE2 foi introduzido em 2001, a grande maioria dos computadores em uso hoje o apoiará. Todos os computadores de desktop de 64 bits têm suporte SSE2 por padrão. No entanto, você sempre pode compilar esta biblioteca com o FM_NOSIMD Definir para desativar a otimização SIMD e usar versões Pascal simples. Isso também pode ser útil para comparar a velocidade das versões Pascal com as versões otimizadas do SIMD.
Em plataformas móveis de 32 bits (iOS e Android), o conjunto de instruções de néon é usado para otimização SIMD. Isso significa que seu dispositivo precisa suportar o neon. Mas como Delphi já requer isso, isso não representa restrições adicionais.
Em plataformas móveis de 64 bits (iOS), o conjunto de instruções ARM64/AARCH64 SIMD é usado.
Não há suporte acelerado de hardware para o simulador iOS (ele usará versões Pascal para todos os cálculos).
Operações FastMath apenas apenas valores de ponto flutuante de precisão única. A aritmética de ponto flutuante de precisão dupla é (atualmente) sem suporte.
A maioria das funções opera em valores únicos (do tipo Single ) e vetores 2-, 3 e 4 e 4-dimensionais (dos tipos TVector2 , TVector3 e TVector4 , respectivamente). Os vetores não são usados apenas para representar pontos ou direções no espaço, mas também podem ser considerados como matrizes de 2, 3 ou 4 valores que podem ser usados para executar cálculos em paralelo. Além dos vetores de ponto flutuante, também existem vetores que o operador nos valores inteiros ( TIVector2 , TIVector3 e TIVector4 ).
Também há suporte para matrizes 2x2, 3x3 e 4x4 (chamadas TMatrix2 , TMatrix3 e TMatrix4 ). Por padrão, as matrizes são armazenadas em ordem de rotação, como as da unidade System.Math.Vectors da RTL. No entanto, você pode alterar esse layout com o FM_COLUMN_MAJOR definir. Em vez disso, isso armazenará matrizes na ordem da coluna, o que é útil para aplicativos OpenGL (que funcionam melhor com este layout). Além disso, isso define também prenderá a profundidade das matrizes da câmera para -1..1 em vez do padrão 0..1. Novamente, isso está mais alinhado com o padrão para aplicativos OpenGL.
Para representar rotações no espaço 3D, há também um TQuaternion , que é semelhante ao tipo TQuaternion3D do RTL.
A operação da biblioteca é um pouco inspirada em linguagens shader (como GLSL e HLSL). Nesses idiomas, você também pode tratar valores e vetores únicos da mesma forma. Por exemplo, você pode usar a função Sin para calcular um único valor senoidal, mas também pode usá -lo com um tipo TVector4 para calcular 4 valores senoidais em uma chamada. Quando combinado com as funções aproximadas Fast* , isso pode resultar em um enorme impulso de desempenho, como mostrado anteriormente.
Todos os tipos de vetor e matriz suportam operadores sobrecarregados que permitem negar, adicionar, subtrair, multiplicar e dividir escalares, vetores e matrizes.
Também existem operadores sobrecarregados que comparam vetores e matrizes para a igualdade. Esses operadores verificam correspondências exatas (como o Delphi's = Operator). Eles não permitem variações muito pequenas (como SameValue funções de Delphi).
Os operadores aritméticos + , - , * e / geralmente funcionam em termos de componentes quando aplicados aos vetores. Por exemplo, se A e B forem do tipo TVector4 , então C := A * B definirá C como (AX * BX, AY * BY, AZ * BZ, AW * BW) . Ele não executará um produto ou produto cruzado (você pode usar o Dot e as funções Cross para calculá -las).
Para matrizes, os operadores + e - também operam em termos de componentes. No entanto, ao multiplicar (ou dividir) matrizes com vetores ou outras matrizes, é usada a multiplicação algébrica linear usual (ou divisão). Por exemplo:
M := M1 * M2 executa uma multiplicação de matriz algébrica linearV := M1 * V1 executa uma matriz * vetor de linha multiplicação algébrica linearV := V1 * M1 executa um vetor de coluna * Multiplicação algébrica linear da matriz Para multiplicar as matrizes em termos de componentes, você pode usar o método CompMult .
O FastMath fornece seus próprios tipos de vetor e matriz para desempenho superior. A maioria deles é equivalente em funcionalidade e armazenamento de dados aos tipos Delphi RTL. Você pode digitar entre eles ou converter implicitamente do tipo FastMath para o tipo RTL ou vice -versa (por exemplo, MyVector2 := MyPointF ). A tabela a seguir mostra o mapeamento:
| Propósito | FastMath | Delphi Rtl |
|---|---|---|
| 2d ponto/vetor | TVECTOR2 | TPOintf |
| 3D ponto/vetor | TVECTOR3 | TPOint3D |
| 4D Point/Vector | TVector4 | TVECTOR3D |
| Matriz 2x2 | TMatrix2 | N / D |
| Matriz 3x3 | TMatrix3 | TMatrix |
| Matriz 4x4 | TMatrix4 | TMatrix3d |
| quaternion | Tquaternion | Tquaternion3d |
A documentação pode ser encontrada no arquivo html de ajuda fastmath.chm no diretório Doc .
Como alternativa, você pode ler a documentação on-line.
O repositório FastMath mantém os seguintes diretórios:
Doc : documentação no formato HTMLHELP. Também contém uma planilha (Benchmarks.xlsx) com os resultados dos testes de desempenho em meus dispositivos (uma área de trabalho do Core i7 e iPad3).DocSource : contém arquivos em lote para gerar a documentação. Você precisa de Pasdocex para gerar a documentação, se quiser.FastMath : contém a principal unidade Neslib.FastMath , bem como vários incluem arquivos com otimizações específicas do processador e bibliotecas estáticas com versões otimizadas do ARM para iOS e Android.Arm : Código fonte e scripts específicos do braço.Arm32 : Contém o código -fonte da montagem para funções otimizadas do néon do ARM.Arm64 : Contém o código -fonte da montagem para funções otimizadas do ARM64.fastmath-android : contém um arquivo em lote e arquivos auxiliares para criar a biblioteca estática para Android usando o NDK do Android.fastmath-ios : contém um script do MacOS Shell para construir uma biblioteca estática universal para iOS.Tests : contém um aplicativo Firemonkey que executa testes de unidade e testes de desempenho. O FastMath é licenciado sob a licença BSD simplificada. Algumas de suas funções são baseadas no código de outras pessoas licenciadas no MIT, novas licenças de BSD e ZLIB. Essas licenças são tão permissivas quanto a licença BSD simplificada usada para todo o projeto.
Consulte License.txt para obter detalhes.