Pergunta

Estou tendo um problema muito estranho ao usar o GCC para ARM com as otimizações ativadas.A compilação do meu aplicativo C ++ sem as otimizações produz um executável que, em tempo de execução, produz os resultados esperados.Assim que eu ative as otimizações - ou seja, -o1 - meu aplicativo falha em produzir os resultados esperados.Tentei por alguns dias identificar o problema, mas não tenho ideia.Eliminei quaisquer variáveis ​​não iniciadas do meu código, corrigi os pontos onde o alias rígido pode causar problemas, mas ainda não tenho os resultados adequados.

Estou usando o GCC 4.2.0 para o ARM (o processador é um ARM926EJ-S) e executando o aplicativo em uma distribuição Montavista Linux.

Abaixo estão os sinalizadores que estou usando:

-O1 -fno-unroll-loops fno-merge-constants -fno-omit-frame-pointer -fno-toplevel-reorder \
-fno-defer-pop -fno-function-cse -Wuninitialized -Wstrict-aliasing=3 -Wstrict-overflow=3 \
-fsigned-char -march=armv5te -mtune=arm926ej-s -ffast-math

Assim que eu removo o sinalizador -O1 e recompilei/revinculei o aplicativo, obtenho os resultados de saída adequados.Como você pode ver pelos sinalizadores, tentei desabilitar qualquer otimização que pensei que poderia causar problemas, mas ainda sem sorte.

Alguém tem alguma dica sobre como eu poderia resolver ainda mais esse problema?

Obrigado

Foi útil?

Solução

De modo geral, se você disser “a otimização quebra meu programa”, 99,9% é sua programa isso está quebrado.Habilitando apenas otimizações descobre as falhas em seu código.

Você também deve ir devagar com as opções de otimização.Somente em circunstâncias muito específicas você precisará de algo além das opções padrão -O0, -O2, -O3 e talvez -Os.Se você sente você fazer precisar de configurações mais específicas do que isso, preste atenção ao mantra das otimizações:

Meça, otimize, meça.

Nunca vá por "intuição" aqui.Prove que uma determinada opção de otimização não padrão beneficia significativamente seu aplicativo, e entenda por que (ou seja, entenda exatamente o que essa opção faz e por que ela afeta seu código).

Este não é um bom lugar para navegar com os olhos vendados.

E vendo como você usa a opção mais defensiva (-O1), desative meia dúzia de otimizações e então add -ffast-math, me leva a supor que você está fazendo exatamente isso.

Bem, talvez com um olho só.

Mas o resultado final é:Se a ativação da otimização quebrar seu código, provavelmente a culpa é dele.

EDITAR: Acabei de encontrar isso no manual do GCC:

-ffast-math:Essa opção nunca deve ser ativada por qualquer opção -O, pois pode resultar em saída incorreta para programas que dependem de uma implementação exata das regras/especificações IEEE ou ISO para funções matemáticas.

Isto diz, basicamente, que o seu -O1 -ffast-math poderia de fato quebrar correto código.Porém, mesmo tirando -ffast-math remove seu problema atual, você deve pelo menos ter uma ideia por que.Caso contrário, você pode simplesmente trocar o seu problema agora com um problema em um momento mais inconveniente mais tarde (como quando seu produto quebra no local do seu cliente).É realmente -ffast-math esse era o problema ou você quebrou o código matemático que é descoberto por -ffast-math?

Outras dicas

-ffast-math devem ser evitados se possível.Apenas use -O1 por enquanto e abandone todas as outras opções de otimização.Se você ainda encontrar problemas, é hora de começar a depurar.

Sem ver seu código, é difícil ser mais específico do que "você provavelmente tem um bug".

Existem dois cenários em que a ativação de otimizações altera a semântica do programa:

  • há um bug no compilador ou
  • há um bug no seu código.

Este último é provavelmente o mais provável.Especificamente, você provavelmente depende do comportamento indefinido em algum lugar do seu programa.Você confia em algo que é verdade quando você compila usando esse compilador ativado esse computador com esses sinalizadores do compilador, mas que não são garantidos pela linguagem.E assim, quando você habilita as otimizações, o GCC não tem obrigação de preservar esse comportamento.

Mostre-nos seu código.Ou percorra-o no depurador até chegar ao ponto em que as coisas dão errado.

Não posso ser mais específico.Pode ser um ponteiro pendente, variáveis ​​não inicializadas, quebra de regras de alias ou até mesmo uma das muitas coisas que produzem resultados indefinidos (como i = i++)

Tente fazer um caso de teste mínimo. Reescreva o programa, removendo coisas que não afetam o erro.É provável que você mesmo descubra o bug no processo, mas se não descobrir, você deve ter um programa de exemplo de uma tela que você pode usar. pode publicar.

Aliás, se, como outros especularam, é -ffast-math que causa o seu problema (ou seja,compilando com apenas -O1 funciona bem), então é provável que você tenha alguma matemática que deva reescrever de qualquer maneira.É um pouco simplificado demais, mas -ffast-math permite que o compilador essencialmente reorganize os cálculos como você poderia abstrair números matemáticos - mesmo que isso em hardware real possa causar resultados ligeiramente diferentes, já que os números de ponto flutuante não são exatos.Depender desse tipo de detalhe de ponto flutuante provavelmente não será intencional.

Se você quiser entender o bug, um caso de teste mínimo é fundamental em qualquer caso.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top