Lapack: Requisitos del procesador para LAPACK

Creado en 4 jun. 2021  ·  16Comentarios  ·  Fuente: Reference-LAPACK/lapack

Estamos trabajando en una traducción de LAPACK a .NET. Escribimos un compilador FORTRAN que traduce con éxito todo LAPACK, incluidas todas las pruebas. En tipos de datos reales (casi) todas las pruebas pasan. En datos complejos, todavía estamos viendo algunos problemas de precisión.

Ejemplo:
XEIGTSTZ <zec.in: falla debido a un desbordamiento en ZLAHQR.
Pasos para reproducir: ZGET37 -> knt == 31, ZHSEQR -> ZLAHQR -> al final del segundo paso QR (ITS == 2), el siguiente código causa subdesbordamiento (en ciertos registros, ver más abajo)

TEMP = H( I, I-1 )
    IF( DIMAG( TEMP ).NE.RZERO ) THEN
        RTEMP = ABS( TEMP)    ! <-- underflow on TEMP = (~1e-0173, ~1e-0173)
        IF (RTEMP .EQ. RZERO) RTEMP = CABS1(TEMP)
        H( I, I-1 ) = RTEMP
        TEMP = TEMP / RTEMP
        IF( I2.GT.I )

Nuestro compilador apunta a .NET CLR. Su JIT decide utilizar registros SSE para ABS (TEMP), lo que conduce al subdesbordamiento en el cálculo intermedio de la magnitud. Ifort (como otro ejemplo) usa registros de punto flotante en esta situación, por lo tanto, no se desborda (debido a su mayor longitud: 80 bits). Estoy tratando de obtener una imagen (más) clara de qué esperar de LAPACK con respecto a qué rango de precisión / número requiere del compilador / procesador en tiempo de ejecución.

¿Todas las pruebas de doble precisión están diseñadas para requerir registros de 64 bits como mínimo ? ¿O están diseñados de manera que tengan éxito para el conjunto de compiladores FORTRAN populares disponibles en la actualidad? (En el primer caso, el problema anterior (y otros similares) puede requerir atención. ¿Debo presentar un problema para ellos?)

Busqué alguna especificación pero aún no la encontré. También se agradecería cualquier enlace. ¡Gracias por adelantado!

Question

Todos 16 comentarios

El desbordamiento en sí no es el verdadero problema. Después del subdesbordamiento, el algoritmo cambia a CABS1, que es menos propenso al subdesbordamiento. El problema que crea es que TEMP no será exactamente unitario, lo que provocará un redondeo en Z.

Una posible solución es preescalar usando CABS1 y luego corregir usando ABS (debido a la primera escala, ABS ya no debería desbordarse). (No obtengo el desbordamiento en mi máquina, así que no puedo probarlo por ti)

IF (RTEMP .EQ. RZERO) THEN
    RTEMP = CABS1(TEMP)
    H( I, I-1 ) = RTEMP
    TEMP = TEMP / RTEMP
    RTEMP = ABS( TEMP)
    H( I, I-1 ) = H( I, I-1 )*RTEMP
    TEMP = TEMP / RTEMP
END IF

Creo que las pruebas definitivamente están diseñadas para tener éxito para el conjunto de compiladores FORTRAN populares, porque así es simplemente como se ejecutan. Es increíblemente difícil predecir el subdesbordamiento o el desbordamiento. Al menos en mi caso, estas subrutinas están diseñadas simplemente probándolas (usando los compiladores populares) a fondo y arreglando cualquier exceso / defecto que encontremos.

¡Gracias! Esto es muy útil.
Intentamos recuperarnos del subdesbordamiento utilizando CABS1. Pero nuestro intento no fue lo suficientemente lejos. Tu sugerencia parece funcionar mucho mejor. Utilizando ...

*
*        Ensure that H(I,I-1) is real.
*
         TEMP = H( I, I-1 )
         IF( DIMAG( TEMP ).NE.RZERO ) THEN
            RTEMP = ABS( TEMP)
            IF (RTEMP .EQ. RZERO) THEN 
                RTEMP = CABS1(TEMP)
                H( I, I-1 ) = RTEMP
                TEMP = TEMP / RTEMP
                RTEMP = ABS( TEMP)
                H( I, I-1 ) = H( I, I-1 )*RTEMP
            ELSE 
                H( I, I-1 ) = RTEMP
            END IF
            TEMP = TEMP / RTEMP
            IF( I2.GT.I )
     $         CALL ZSCAL( I2-I, DCONJG( TEMP ), H( I, I+1 ), LDH )
            CALL ZSCAL( I-I1, TEMP, H( I1, I ), 1 )
            IF( WANTZ ) THEN
               CALL ZSCAL( NZ, TEMP, Z( ILOZ, I ), 1 )
            END IF
         END IF
*
  130 CONTINUE

... esta iteración se completa con éxito (incluso cuando se utilizan registros SSE para ABS ()).

Creo que las pruebas definitivamente están diseñadas para tener éxito para el conjunto de compiladores FORTRAN populares, porque así es simplemente como se ejecutan. Es increíblemente difícil predecir el subdesbordamiento o el desbordamiento. Al menos en mi caso, estas subrutinas están diseñadas simplemente probándolas (usando los compiladores populares) a fondo y arreglando cualquier exceso / defecto que encontremos.

¡El conjunto de pruebas es de gran ayuda! Mi estimación aproximada es que mucho menos del 1% de las pruebas se ven afectadas por este o problemas de desbordamiento similares (cuando se usa nuestro compilador). Hacer que las pruebas sean aún más robustas contra subflujo / desbordamiento podría ayudar a llevar LAPACK a más plataformas. Sin embargo, nuestro intento (fallido) anterior es solo un ejemplo, que muestra claramente que difícilmente podríamos encontrar una solución de nuestro lado. Antes de abrir varios temas relacionados, me gustaría comenzar una discusión, si hay interés en tal viaje y cuál sería un buen enfoque.

¡Gracias por la mejora @hokb y @thijssteel! ¿Debo escribir un PR con las modificaciones o estás dispuesto a hacerlo, @hokb?

Dada mi experiencia limitada con el proyecto, agradecería su esfuerzo y la oportunidad de tomar sus relaciones públicas como una guía para la marihuana. futuros RP de nuestra parte ... (¿si está bien?)

Hola @hokb ,

Busqué alguna especificación pero aún no la encontré. También se agradecería cualquier enlace. ¡Gracias por adelantado!

No estoy seguro de que se especifique nada en alguna parte.

Nuestro compilador apunta a .NET CLR. Su JIT decide utilizar registros SSE para ABS (TEMP), lo que conduce al subdesbordamiento en el cálculo intermedio de la magnitud. Ifort (como otro ejemplo) usa registros de punto flotante en esta situación, por lo tanto, no se desborda (debido a su mayor longitud: 80 bits). Estoy tratando de obtener una imagen (más) clara de qué esperar de LAPACK con respecto a qué rango de precisión / número requiere del compilador / procesador en tiempo de ejecución.

Declaración en negrita: si todos los cálculos se realizan utilizando aritmética IEEE de 64 bits, LAPACK debería funcionar.

LAPACK no espera que el registro de 80 bits ayude a su cálculo en ningún momento. Los algoritmos están diseñados teniendo en cuenta la aritmética de 64 bits. Ahora, como lo menciona @thijssteel , LAPACK se prueba con varios compiladores / arquitecturas, y estos compiladores / arquitecturas usan registros de 80 bits a veces, y podríamos pensar que nuestros algoritmos solo necesitan 64 bits todo el tiempo, pero no es así, y en efecto, requieren un 80 bits.

No hemos hecho nada sistemático en nuestro viaje para perseguir estos problemas. En general, estamos bastante contentos cuando los algoritmos pasan el conjunto de pruebas y, si hay alguna ayuda del registro de 80 bits, que así sea.

¿Todas las pruebas de doble precisión están diseñadas para requerir registros de 64 bits como mínimo? ¿O están diseñados de manera que tengan éxito para el conjunto de compiladores FORTRAN populares disponibles en la actualidad? (En el primer caso, el problema anterior (y otros similares) puede requerir atención. ¿Debo presentar un problema para ellos?)

Mi estimación aproximada es que mucho menos del 1% de las pruebas se ven afectadas por este o problemas de desbordamiento similares (cuando se usa nuestro compilador).

Oh mi. 1%? Ese es un gran número aterrador.

Las pruebas están probando mucho alrededor de la región de subdesbordamiento y desbordamiento, por lo que podría esperarse que las pruebas sean mucho más probables en términos de desencadenar este problema que el código de los usuarios, pero aún así.

Hacer que las pruebas sean aún más robustas contra subflujo / desbordamiento podría ayudar a llevar LAPACK a más plataformas.

La portabilidad a más plataformas es realmente un interés. Otro interés es la precisión extendida con paquetes como GMP donde, según tengo entendido, la precisión se fija en todo el cálculo. (Entonces, por ejemplo, está pensado en 256 bits y no hay un registro de 300 bits para ayudarlo).

Sin embargo, nuestro intento (fallido) anterior es solo un ejemplo, que muestra claramente que difícilmente podríamos encontrar una solución de nuestro lado. Antes de abrir varios temas relacionados, me gustaría comenzar una discusión, si hay interés en tal viaje y cuál sería un buen enfoque.

Si. Estamos interesados. Sin embargo, solo podemos hacer mucho. Y tenemos mucho en nuestros platos. Entonces, tal vez tomemos este tema a la vez, y veamos hasta dónde llegamos.

En cualquier caso, publicar problemas en GitHub siempre es una buena idea. Da conciencia del problema y ayuda a reunir ayuda e ideas para solucionar los problemas.

Estoy feliz de que vayamos por este camino, pero recomendaría tomárselo con calma.

Quizás, para gfortran, deberíamos compilar con las banderas -mfpmath=sse -msse2 con fines de prueba. Creo que esto obligará a que todos los cálculos se realicen con aritmética de 64 bits. Aunque no estoy seguro.

Dada mi experiencia limitada con el proyecto, agradecería su esfuerzo y la oportunidad de tomar sus relaciones públicas como una guía para la marihuana. futuros RP de nuestra parte ... (¿si está bien?)

¡Seguro! Por favor, vea el n. ° 577.

@weslleyspereira ¡Impresionante! Todavía estoy comprobando si esto se aplica a CLAHQR de la misma manera. Publicaré mi resultado lo antes posible (mañana)

¡Hola @langou !

Declaración en negrita: si todos los cálculos se realizan utilizando aritmética IEEE de 64 bits, LAPACK debería funcionar.

¡Bonito! Supongo que por 'trabajo' queremos decir: cuando se alimenta con datos 'en un cierto rango', ¿no se desbordará debido a un tamaño de registro dado?

LAPACK no espera que el registro de 80 bits ayude a su cálculo en ningún momento. Los algoritmos están diseñados teniendo en cuenta la aritmética de 64 bits. Ahora, como lo menciona @thijssteel , LAPACK se prueba con varios compiladores / arquitecturas, y estos compiladores / arquitecturas usan registros de 80 bits a veces, y podríamos pensar que nuestros algoritmos solo necesitan 64 bits todo el tiempo, pero no es así, y en efecto, requieren un 80 bits.

No hemos hecho nada sistemático en nuestro viaje para perseguir estos problemas. En general, estamos bastante contentos cuando los algoritmos pasan el conjunto de pruebas y, si hay alguna ayuda del registro de 80 bits, que así sea.

¡Suena muy razonable!

Mi estimación aproximada es que mucho menos del 1% de las pruebas se ven afectadas por este o problemas de desbordamiento similares (cuando se usa nuestro compilador).

Oh mi. 1%? Ese es un gran número aterrador.

Bueno, probablemente sea 'mucho menos' que eso;)

La portabilidad a más plataformas es realmente un interés. Otro interés es la precisión extendida con paquetes como GMP donde, según tengo entendido, la precisión se fija en todo el cálculo. (Entonces, por ejemplo, está pensado en 256 bits y no hay un registro de 300 bits para ayudarlo).

Suena interesante, pero no puedo comentar sobre esto, ya que carezco de experiencia con intentos de precisión tan fija.

Si. Estamos interesados. Sin embargo, solo podemos hacer mucho. Y tenemos mucho en nuestros platos. Entonces, tal vez tomemos este tema a la vez, y veamos hasta dónde llegamos.

Todavía no estoy seguro de cuál sería un buen enfoque general. Desnudo conmigo, si mi comprensión es demasiado ingenua. Pero, ¿el desbordamiento / subdesbordamiento no depende siempre de ambos: datos de entrada y algoritmo? Entonces, en lugar de inundar el código con nuevas pruebas condicionales y un nuevo código para recuperarse de ellos, ¿podríamos disminuir el 'rango permitido' para los datos de entrada? Sin embargo, no tengo la información necesaria sobre el esfuerzo requerido para ninguno de los enfoques. Entonces no puedo juzgar qué sería más factible.

En cualquier caso, publicar problemas en GitHub siempre es una buena idea. Da conciencia del problema y ayuda a reunir ayuda e ideas para solucionar los problemas.

Bueno. Archivaremos los problemas a medida que avancemos. Entiendo que será un desafío encontrar una solución sin poder reproducir un subdesbordamiento. Entonces, ¿qué información podemos proporcionar para aclarar el problema? ¿Ayuda el camino hasta el desagüe de hormigón? Es decir: ¿proporcionar recuentos de iteraciones, valores actuales de los locales junto con los nombres de los archivos, etc.?

Estoy feliz de que vayamos por este camino, pero recomendaría tomárselo con calma.

¡Lo mismo aqui! :)

Un resultado de # 577 es que LAPACK se basa en el compilador FORTRAN para implementar una división compleja razonablemente robusta (bajo / desbordamiento) y ABS (). Me pregunto si deberíamos empezar a mantener un documento, recopilando requisitos de este tipo y otros similares. ¿Serán igualmente importantes y útiles para cualquiera que desee utilizar LAPACK con otros compiladores nuevos, para los constructores de compiladores y para transferir partes o todos los algoritmos LAPACK a otros lenguajes?

¡Seguro! Será bueno tener esta información bien documentada.

Para empezar, pasé algún tiempo rastreando (tal vez) todas las divisiones en los archivos LAPACK/SRC/z*.f (COMPLEJO * 16 algoritmos) del formulario

 REAL / COMPLEX   or   COMPLEX / COMPLEX

Encontré un total de 53 archivos. Vea el archivo adjunto: complexDivisionFound.code-search

  • Para eso, utilicé la expresión REGEX en Visual Studio Code:

    \ n. * / ^ 0-9 (?! DBLE) (?! REAL) (?! MIN) (?! MAX) [^ 0-9]

Quizás, para gfortran, deberíamos compilar con las banderas -mfpmath=sse -msse2 con fines de prueba. Creo que esto obligará a que todos los cálculos se realicen con aritmética de 64 bits. Aunque no estoy seguro.

Sí, debería hacerlo al usar GCC, pero este indicador también debería estar configurado de forma predeterminada en x86-64. El extracto de la documentación a continuación es para GCC 11, pero las versiones de GCC mucho más antiguas deberían mostrar el mismo comportamiento. Usando la colección de compiladores GNU (GCC): 3.19.59 Opciones x86

sse

Utilice las instrucciones escalares de coma flotante presentes en el conjunto de instrucciones SSE. Este conjunto de instrucciones es compatible con Pentium III y chips más nuevos, y en la línea AMD con los chips Athlon-4, Athlon XP y Athlon MP. La versión anterior del conjunto de instrucciones SSE solo admite aritmética de precisión simple, por lo que la aritmética de precisión doble y extendida todavía se realiza utilizando 387. Una versión posterior, presente solo en los chips Pentium 4 y AMD x86-64, admite aritmética de doble precisión también.

Para el compilador x86-32, debe usar los interruptores -march=cpu-type , -msse o -msse2 para habilitar las extensiones SSE y hacer que esta opción sea efectiva. Para el compilador x86-64, estas extensiones están habilitadas de forma predeterminada.

El código resultante debería ser considerablemente más rápido en la mayoría de los casos y evitar los problemas de inestabilidad numérica del código 387, pero puede romper algún código existente que espera que los temporales sean de 80 bits.

Esta es la opción predeterminada para el compilador x86-64, los destinos Darwin x86-32 y la opción predeterminada para los destinos x86-32 con la instrucción SSE2 establecida cuando -ffast-math está habilitado.

Ejemplo:
XEIGTSTZ <zec.in: falla debido a un desbordamiento en ZLAHQR.
Pasos para reproducir: ZGET37 -> knt == 31, ZHSEQR -> ZLAHQR -> al final del segundo paso QR (ITS == 2), el siguiente código causa subdesbordamiento (en ciertos registros, ver más abajo)

TEMP = H( I, I-1 )
    IF( DIMAG( TEMP ).NE.RZERO ) THEN
        RTEMP = ABS( TEMP)    ! <-- underflow on TEMP = (~1e-0173, ~1e-0173)
        IF (RTEMP .EQ. RZERO) RTEMP = CABS1(TEMP)
        H( I, I-1 ) = RTEMP
        TEMP = TEMP / RTEMP
        IF( I2.GT.I )

Nuestro compilador apunta a .NET CLR. Su JIT decide utilizar registros SSE para ABS (TEMP), lo que conduce al subdesbordamiento en el cálculo intermedio de la magnitud. Ifort (como otro ejemplo) usa registros de punto flotante en esta situación, por lo tanto, no se desborda (debido a su mayor longitud: 80 bits). Estoy tratando de obtener una imagen (más) clara de qué esperar de LAPACK con respecto a qué rango de precisión / número requiere del compilador / procesador en tiempo de ejecución.

Recordar:

  • Transpiló medio millón de líneas de Fortran77 en C #.
  • La prueba del código transpilado falla cuando se usa el compilador Just-In-Time de .NET.
  • La prueba del código LAPACK de vainilla se realiza correctamente cuando se utiliza el compilador Intel Fortran (ifort).
  • La diferencia observada entre los dos casos es el uso de intermedios de 80 bits por ifort que evita un subdesbordamiento.

¿Correcto?

Por defecto, GCC genera solo código para registros flotantes de 64 bits en x86-64 y en mis máquinas generalmente pasan todas las pruebas LAPACK excepto una o dos.

¿Pasa el conjunto de pruebas Netlib LAPACK cuando se compila con GCC?

editar: resuelto https://github.com/Reference-LAPACK/lapack/pull/577#issuecomment -859496175

Tal vez, para gfortran, deberíamos compilar con los indicadores -mfpmath = sse -msse2 con fines de prueba. Creo que esto obligará a que todos los cálculos se realicen con aritmética de 64 bits. Aunque no estoy seguro.

Probé -mfpmath=sse -msse2 con GCC 11 tanto en MacOS como en Linux: https://github.com/weslleyspereira/lapack/actions/runs/966071530. No hubo errores adicionales en comparación con el flujo de trabajo sin esos indicadores: https://github.com/Reference-LAPACK/lapack/actions/runs/945060330. Ver # 591

@hokb , ¿podría reproducir los problemas de desbordamiento que mencionó en https://github.com/Reference-LAPACK/lapack/issues/575#issuecomment -855880000 con GCC usando indicadores SSE? ¿Me puede ayudar con eso?

@weslleyspereira Ni siquiera he probado GCC. Todo lo que tengo acceso a / una configuración en ejecución es ifort en Windows. Me tomaría algunos días poner en funcionamiento GCC a través de cygwin para realizar la prueba (especialmente desde mi habitación de hotel de vacaciones actual ...: |) ¡Avíseme si necesita que acepte este desafío!
Al menos y según https://godbolt.org/z/YYv5oPxe9 el uso de las banderas no afecta el código generado por gfortran. Pero, por supuesto, solo una prueba lo dirá con seguridad ...

No uso Windows, pero lo tengo aquí. Comenzaré probando LAPACK con ifort en mi Ubuntu y veré qué sucede. ¡Disfruta las vacaciones!

¿Fue útil esta página
0 / 5 - 0 calificaciones