Que tipo de otimizações a opção -ffast-math
faz?
Eu vi que o tempo gasto para um algoritmo $ O (n ^ 2) $ simples ser reduzido ao de um algoritmo $ O (n) $ usando a opção.
Comentários
- Acho que esta pergunta já tem uma resposta no Stack Overflow: stackoverflow.com/questions/7420665/…
- Eu ' estou votando para fechar esta pergunta como uma duplicata de uma pergunta em um SE diferente .
- @BillBarth: Fechar uma pergunta como uma duplicata geralmente funciona apenas em um determinado site StackExchange, com exceção de postagens cruzadas óbvias. Consulte meta.stackexchange.com/questions/172307/… no Meta StackExchange para discussão e possíveis soluções.
- @GeoffOxberry, eu vi isso e tentei um plano B.
- @BillBarth onde você acha que eu poderia encontrar uma resposta elaborada?
Resposta
Há uma resposta canônica para essa pergunta no wiki do GCC , que é presumivelmente mantida, é de longe a fonte de informação mais confiável para este tipo de questão. Esta questão, por outro lado, pode eventualmente ficar desatualizada. Tudo isso é explicado em mais detalhes no wiki, com exemplos. O seguinte é essencialmente uma citação dele para ilustrar como ele responde a essa pergunta exata, com pequenos comentários:
-
-fno-signaling-nans
-
-fno-trapping-math
O padrão IEEE recomenda que as implementações permitam que os manipuladores de armadilhas lidem com exc epções como divisão por zero e estouro. Este sinalizador pressupõe que nenhuma armadilha visível ao uso acontecerá.
-
-funsafe-math-optimizations
– Essas otimizações quebram as leis da aritmética de ponto flutuante e podem substituí-las pelas leis da aritmética de precisão infinita comum:Devido a erros de arredondamento, o associativo lei da álgebra não é necessária para números de ponto flutuante e, portanto, expressões como (x + y) + z não são necessariamente iguais a x + (y + z).
-
-ffinite-math-only
– quantidades especiais comoinf
ounan
nunca apareça, isso economiza o tempo gasto procurando por eles e tratando-os de maneira adequada. Por exemplo, $ x – x $ deve ser sempre igual a $ 0,0 $? -
-fno-errno-math
desativa a configuração da variável errno conforme exigido pelo C89 / C99 na chamada de rotinas da biblioteca matemática. Para Fortran, este é o padrão.
-
-fcx-limited-range
faz com que a etapa de redução do intervalo seja omitida ao realizar a divisão complexa. Isso usa $ a / b = ((ar * br + ai * bi) / t) + i ((ai * br – ar * bi) / t) $ com $ t = br * br + bi * bi $ e pode não funciona bem em intervalos arbitrários de entradas.
-
-fno-rounding-math
-
-fno-signed-zeros
Devido a erros de arredondamento, a lei associativa da álgebra não é necessária para números de ponto flutuante e, portanto, expressões como (x + y) + z não são necessariamente iguais a x + (y + z).
Falando estritamente, as implicações dos dois últimos nem sempre são tão intuitivas quanto se possa pensar. Por exemplo (veja wiki), que tal $ – (a – a) = a – a $, é $ + 0,0 $ ou $ -0,0 $? Acredito que haja uma boa quantidade de literatura sobre as implicações exatas, especialmente por Bill Kahan .
- Não mencionado diretamente (eu não vê isso?), mas com
-ffast-math
, certas funções especiais comuns, como $ 1 / x $ recíproco e raiz quadrada $ \ sqrt {x} $ são substituídas por menos versões precisas que são mais rápidas, mas que ainda têm alguns níveis de erro “toleráveis” (versus o erro 0ulp exigido pelo padrão) – aqui, por exemplo, é o que a precisão geralmente é fornecida glibc “s libm . Na verdade, esta é a causa mais comum de aceleração de-ffast-math
, em código que faz muita aritmética com divisões e raízes quadradas, quase a ponto de eu ( pessoalmente ) acho que as outras subopções (-ffinite-math-only
e similares especialmente – sinalizandoNaN
s são bastante úteis para depuração) também causam um pouco muito incômodo em termos de custo / benefício.
Eu vi que o tempo gasto para um simples $ O (n ^ 2) $ algoritmo sendo reduzido ao de um algoritmo $ O (n) $ usando a opção.
Eu acredito que isso é improvável e é possível que você tenha cometido um erro em sua análise.Otimizações de ponto flutuante inseguras podem tornar expressões individuais um pouco mais baratas de avaliar em virtude de ter uma escolha maior de otimizações. Mas a aceleração deve ser sempre, no máximo, um fator constante. É possível que você comparou um algoritmo $ O (n ^ 2) $ com um $ O (n) $ para $ n $ insuficientemente grande?
Resposta
Um algoritmo $ n ^ 2 $ pode ser reduzido a algo que se comporta $ O (n) $ se, por exemplo, se $ n $ for conhecido pelo compilador e for um múltiplo do tamanho do vetor para as instruções vetoriais (se houver) suportadas pelo processador. Se o compilador pode ver tudo isso, ele pode desenrolar um loop interno e usar instruções vetoriais para fazer o trabalho. Isso pode reduzir as operações gerais feitas a um punhado e melhorar o desempenho substancialmente.
Minha leitura é que fast-math
não permite essa otimização, mas poderia se eles estivessem implicitamente ativados pelo unsafe-math-optimizations
devido às restrições de associatividade que estão desativadas.