Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

190
Visualizações
¿Por qué el compilador no puede optimizar la adición de punto flotante con 0?

Tengo cuatro funciones de identidad que esencialmente no hacen nada. Solo la multiplicación con 1 podría optimizarse haciendo sonar una sola instrucción ret .

 float id0(float x) { return x + 1 - 1; } float id1(float x) { return x + 0; } float id2(float x) { return x * 2 / 2; } float id3(float x) { return x * 1; }

Y la siguiente salida del compilador es: (clang 10, at -O3)

 .LCPI0_0: .long 1065353216 # float 1 .LCPI0_1: .long 3212836864 # float -1 id0(float): # @id0(float) addss xmm0, dword ptr [rip + .LCPI0_0] addss xmm0, dword ptr [rip + .LCPI0_1] ret id1(float): # @id1(float) xorps xmm1, xmm1 addss xmm0, xmm1 ret .LCPI2_0: .long 1056964608 # float 0.5 id2(float): # @id2(float) addss xmm0, xmm0 mulss xmm0, dword ptr [rip + .LCPI2_0] ret id3(float): # @id3(float) ret

Puedo entender por qué id0 e id2 no se pueden optimizar. Aumentan el valor que luego podría convertirse en infinito positivo y la segunda operación no lo volvería a cambiar.

Pero, ¿por qué no se puede optimizar id1 ? La suma con infinito daría infinito, la suma con cualquier número regular daría ese número y la suma con NaN daría NaN . Entonces, ¿por qué no es una operación de identidad "verdadera" como * 1 ?

Ejemplo con Compiler Explorer

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

Los números de punto flotante IEEE 754 tienen dos valores cero, uno negativo y otro positivo. Cuando se suman, el resultado es positivo.

Entonces id1(-0.f) es 0.f , no -0.f .
Tenga en cuenta que id1(-0.f) == -0.f porque 0.f == -0.f .

Manifestación

Además, tenga en cuenta que compilar con -ffast-math en GCC realiza la optimización y cambia el resultado.

over 4 years ago · Santiago Trujillo Relatório

0

"Tengo cuatro funciones de identidad que esencialmente no hacen nada".

Eso no es cierto.

Para números de punto flotante x + 1 - 1 no es igual a x + 0 , es igual a (x + 1) - 1 . Entonces, si tiene, por ejemplo, una x muy pequeña, perderá esa porción muy pequeña en el paso x + 1 , y el compilador no puede saber si esa fue su intención o no.

Y en el caso de x * 2 / 2 , es posible que x * 2 tampoco sea exacto, debido a la precisión del punto flotante, por lo que tiene un caso similar aquí, el compilador no sabe si por alguna razón desea cambiar el valor de x de esa manera.

Entonces estos serían iguales:

 float id0(float x) { return x + (1. - 1.); } float id1(float x) { return x + 0; }

Y estos serían iguales:

 float id2(float x) { return x * (2. / 2.); } float id3(float x) { return x * 1; }

El comportamiento deseado seguramente podría definirse de otra manera. Pero como ya mencionó Nelfeal, esta optimización debe activarse explícitamente usando -ffast-math

Habilite el modo matemático rápido. Esta opción le permite al compilador hacer suposiciones agresivas y potencialmente con pérdidas sobre las matemáticas de punto flotante. Éstos incluyen:

  • Las matemáticas de punto flotante obedecen reglas algebraicas regulares para números reales (p. ej., + y * son asociativos, x/y == x * (1/y) y (a + b) * c == a * c + b * c) ,
  • Los operandos de las operaciones de coma flotante no son iguales a NaN e Inf, y
  • +0 y -0 son intercambiables.

fast-math es para clang y gcc una colección de banderas (aquí la listada por clang):

  • -fno-honor-infinitos
  • -fno-honor-nans
  • -fno-math-errno
  • -matemáticas finitas
  • -matemáticas fasociativas
  • -matemáticas-freciprocas
  • -fno-ceros con signo
  • -fno-trapping-matemáticas
  • -ffp-contrato=rápido
over 4 years ago · Santiago Trujillo Relatório

0

Lea la página web float-number-gui.de , más información sobre IEEE 754 , el estándar C11 n1570 , el estándar C++11 n3337 .

 float id1(float x) { return x + 0; }

Si x resulta ser un NaN de señalización, es posible que su id1 incluso no regrese (y probablemente no debería regresar).

Si x es un NaN silencioso, entonces id1(x) != x ya que NaN != NaN (al menos NaN == NaN debería ser falso).

En algunos casos, desea aritmética de precisión arbitraria costosa. Entonces considere usar GMPlib .

PD. Los números de coma flotante pueden provocarle pesadillas o un doctorado, a su elección. A veces matan a personas o al menos provocan grandes desastres financieros (por ejemplo, una pérdida de varios cientos de millones de dólares estadounidenses o euros).

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda