Lapack: Exigences du processeur pour LAPACK

Créé le 4 juin 2021  ·  16Commentaires  ·  Source: Reference-LAPACK/lapack

Nous travaillons sur une traduction de LAPACK en .NET. Nous avons écrit un compilateur FORTRAN qui traduit avec succès tout LAPACK, y compris tous les tests. Sur les types de données réels (presque) tous les tests réussissent. Sur les données complexes, nous constatons encore quelques problèmes de précision.

Exemple:
XEIGTSTZ < zec.in - échoue en raison d'un débordement dans ZLAHQR.
Etapes à reproduire : ZGET37 -> knt == 31, ZHSEQR -> ZLAHQR -> à la fin de la deuxième étape QR (ITS == 2) le code suivant provoque un débordement (sur certains registres, voir ci-dessous)

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 )

Notre compilateur cible le .NET CLR. Son JIT décide d'utiliser des registres SSE pour ABS(TEMP), ce qui conduit au dépassement dans le calcul intermédiaire de la grandeur. Ifort (comme autre exemple) utilise des registres à virgule flottante dans cette situation, donc ne déborde pas (en raison de sa plus grande longueur : 80 bits). J'essaie d'avoir une (plus) image claire de ce à quoi s'attendre de LAPACK en ce qui concerne la précision / plage de nombres requise du compilateur / processeur au moment de l'exécution.

Tous les tests de double précision sont-ils conçus pour nécessiter au moins des registres de 64 bits ? Ou sont-ils conçus de manière à réussir pour l'ensemble des compilateurs FORTRAN populaires disponibles aujourd'hui ? (Dans le premier cas ci-dessus, le problème (et d'autres similaires) peut nécessiter votre attention. Dois-je déposer un problème pour eux ?)

J'ai cherché des spécifications mais je ne les ai pas encore trouvées. Tout lien serait également apprécié. Merci d'avance!

Question

Tous les 16 commentaires

Le débordement en lui-même n'est pas le vrai problème. Après le sous-débordement, l'algorithme passe à CABS1, qui est moins sujet au sous-débordement. Le problème que cela crée est que TEMP ne sera pas exactement unitaire, conduisant à un arrondi en Z.

Une solution possible est de pré-échelonner à l'aide de CABS1 puis de corriger à l'aide de l'ABS (à cause de la première mise à l'échelle, l'ABS ne devrait plus déborder). (Je n'ai pas le débordement sur ma machine, donc je ne peux pas le tester pour vous)

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

Je pense que les tests sont définitivement conçus pour réussir pour l'ensemble des compilateurs FORTRAN populaires, car c'est simplement ainsi qu'ils sont exécutés. Prédire le sous/débordement est incroyablement difficile. Au moins dans mon cas, ces sous-routines sont conçues en les testant simplement (à l'aide des compilateurs populaires) de manière approfondie et en corrigeant tout dépassement / dépassement de capacité que nous trouvons.

Merci! C'est très utile.
Nous avions essayé de récupérer du débordement en utilisant CABS1. Mais notre tentative n'allait pas assez loin. Votre suggestion semble faire beaucoup mieux. À l'aide de ...

*
*        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

... cette itération se termine avec succès (même lors de l'utilisation des registres SSE pour ABS()).

Je pense que les tests sont définitivement conçus pour réussir pour l'ensemble des compilateurs FORTRAN populaires, car c'est simplement ainsi qu'ils sont exécutés. Prédire le sous/débordement est incroyablement difficile. Au moins dans mon cas, ces sous-routines sont conçues en les testant simplement (à l'aide des compilateurs populaires) de manière approfondie et en corrigeant tout dépassement / dépassement de capacité que nous trouvons.

La suite de tests est d'une aide précieuse ! Mon estimation approximative est que bien moins de 1% des tests sont affectés par ce problème ou des problèmes de débordement similaires (lors de l'utilisation de notre compilateur). Rendre les tests encore plus robustes contre le sous-/débordement pourrait aider à amener LAPACK sur plus de plates-formes. Notre tentative (échoué) ci-dessus n'est qu'un exemple, qui montre clairement que nous serions à peine en mesure de trouver une solution de notre côté, cependant. Avant d'ouvrir plusieurs questions connexes, je voudrais lancer une discussion, savoir s'il y a ou non un intérêt pour un tel voyage et quelle serait une bonne approche.

Merci pour l'amélioration @hokb et @thijssteel ! Dois-je écrire un PR avec les modifications ou êtes-vous prêt à le faire, @hokb ?

Compte tenu de mon expérience limitée avec le projet, j'apprécierais vos efforts et la chance de prendre votre RP comme ligne directrice pour le pot. futurs PR de notre part... (si c'est d'accord ?)

Salut @hokb ,

J'ai cherché des spécifications mais je ne les ai pas encore trouvées. Tout lien serait également apprécié. Merci d'avance!

Je ne suis pas sûr que quoi que ce soit soit spécifié nulle part.

Notre compilateur cible le .NET CLR. Son JIT décide d'utiliser des registres SSE pour ABS(TEMP), ce qui conduit au dépassement dans le calcul intermédiaire de la grandeur. Ifort (comme autre exemple) utilise des registres à virgule flottante dans cette situation, donc ne déborde pas (en raison de sa plus grande longueur : 80 bits). J'essaie d'avoir une (plus) image claire de ce à quoi s'attendre de LAPACK en ce qui concerne la précision / plage de nombres requise du compilateur / processeur au moment de l'exécution.

Déclaration en gras : si tous les calculs sont effectués à l'aide de l'arithmétique IEEE 64 bits, alors LAPACK devrait fonctionner.

LAPACK ne s'attend pas à ce que le registre 80 bits vienne aider son calcul à tout moment. Les algorithmes sont conçus avec l'arithmétique 64 bits à l'esprit. Maintenant, comme mentionné par @thijssteel , LAPACK est testé avec divers compilateurs/architectures, et ces compilateurs/architectures utilisent parfois des registres 80 bits, et nous pourrions penser que nos algorithmes n'ont besoin que de 64 bits, mais ce n'est pas le cas, et ils nécessitent en effet un 80 bits.

Nous n'avons rien fait de systématique dans notre démarche pour nous attaquer à ces problèmes. En général, nous sommes assez heureux lorsque les algorithmes passent la suite de tests, et, s'il y a de l'aide du registre 80 bits, qu'il en soit ainsi.

Tous les tests de double précision sont-ils conçus pour nécessiter au moins des registres de 64 bits ? Ou sont-ils conçus de manière à réussir pour l'ensemble des compilateurs FORTRAN populaires disponibles aujourd'hui ? (Dans le premier cas ci-dessus, le problème (et d'autres similaires) peut nécessiter votre attention. Dois-je déposer un problème pour eux ?)

Mon estimation approximative est que bien moins de 1% des tests sont affectés par ce problème ou des problèmes de débordement similaires (lors de l'utilisation de notre compilateur).

Oh mon. 1%? C'est un grand nombre effrayant.

Les tests testent beaucoup autour de la région de débordement et de débordement, on peut donc s'attendre à ce que les tests soient beaucoup plus susceptibles de déclencher ce problème que le code des utilisateurs, mais quand même.

Rendre les tests encore plus robustes contre le sous-/débordement pourrait aider à amener LAPACK sur plus de plates-formes.

La portabilité vers plus de plates-formes est en effet un intérêt. Un autre intérêt est la précision étendue avec des packages tels que GMP où, si j'ai bien compris, la précision est fixée tout au long du calcul. (Donc par exemple vous êtes pensé 256 bits, et il n'y a pas de registre 300 bits pour venir vous aider.)

Notre tentative (échoué) ci-dessus n'est qu'un exemple, qui montre clairement que nous serions à peine en mesure de trouver une solution de notre côté, cependant. Avant d'ouvrir plusieurs questions connexes, je voudrais lancer une discussion, savoir s'il y a ou non un intérêt pour un tel voyage et quelle serait une bonne approche.

Oui. Nous sommes intéressés. Cependant, nous ne pouvons pas faire grand-chose. Et nous en avons beaucoup dans nos assiettes. Alors peut-être que nous prenons cette question à la fois, et nous voyons jusqu'où nous allons.

Dans tous les cas, publier des problèmes sur GitHub est toujours une bonne idée. Cela permet de prendre conscience du problème et de recueillir de l'aide, des idées pour résoudre les problèmes.

Je suis heureux que nous suivions cette voie, mais je recommanderais d'y aller doucement.

Peut-être que pour gfortran, nous devrions compiler avec les indicateurs -mfpmath=sse -msse2 à des fins de test. Je pense que cela forcera tous les calculs à être effectués avec une arithmétique 64 bits. Je ne suis pas sûr cependant.

Compte tenu de mon expérience limitée avec le projet, j'apprécierais vos efforts et la chance de prendre votre RP comme ligne directrice pour le pot. futurs PR de notre part... (si c'est d'accord ?)

Sûr! S'il vous plaît, voir #577.

@weslleyspereira Génial ! Je suis toujours en train de vérifier, si cela s'applique à CLAHQR de la même manière. Je posterai mon résultat dès que possible (demain)

Bonjour @langou !

Déclaration en gras : si tous les calculs sont effectués à l'aide de l'arithmétique IEEE 64 bits, alors LAPACK devrait fonctionner.

Joli! Je suppose que par « travail », nous entendons : lorsqu'il est alimenté avec des données « dans une certaine plage », il ne débordera pas en raison d'une taille de registre donnée ?

LAPACK ne s'attend pas à ce que le registre 80 bits vienne aider son calcul à tout moment. Les algorithmes sont conçus avec l'arithmétique 64 bits à l'esprit. Maintenant, comme mentionné par @thijssteel , LAPACK est testé avec divers compilateurs/architectures, et ces compilateurs/architectures utilisent parfois des registres 80 bits, et nous pourrions penser que nos algorithmes n'ont besoin que de 64 bits, mais ce n'est pas le cas, et ils nécessitent en effet un 80 bits.

Nous n'avons rien fait de systématique dans notre démarche pour nous attaquer à ces problèmes. En général, nous sommes assez heureux lorsque les algorithmes passent la suite de tests, et, s'il y a de l'aide du registre 80 bits, qu'il en soit ainsi.

Cela semble très raisonnable !

Mon estimation approximative est que bien moins de 1% des tests sont affectés par ce problème ou des problèmes de débordement similaires (lors de l'utilisation de notre compilateur).

Oh mon. 1%? C'est un grand nombre effrayant.

Eh bien, c'est probablement "beaucoup moins" que cela ;)

La portabilité vers plus de plates-formes est en effet un intérêt. Un autre intérêt est la précision étendue avec des packages tels que GMP où, si j'ai bien compris, la précision est fixée tout au long du calcul. (Donc par exemple vous êtes pensé 256 bits, et il n'y a pas de registre 300 bits pour venir vous aider.)

Cela semble intéressant, mais je ne peux pas commenter cela, car je manque d'expérience avec de telles tentatives de précision fixes.

Oui. Nous sommes intéressés. Cependant, nous ne pouvons pas faire grand-chose. Et nous en avons beaucoup dans nos assiettes. Alors peut-être que nous prenons cette question à la fois, et nous voyons jusqu'où nous allons.

Je ne sais toujours pas quelle serait une bonne approche générale. Nu avec moi, si ma compréhension est trop naïve. Mais le dépassement/sous-dépassement ne dépend-il pas toujours à la fois des données d'entrée et de l'algorithme ? Ainsi, au lieu d'inonder le code de nouveaux tests conditionnels et d'un nouveau code pour les récupérer, nous pourrions plutôt réduire la « plage autorisée » pour les données d'entrée ? Je n'ai pas la perspicacité nécessaire dans l'effort requis pour l'une ou l'autre approche, cependant. Je ne peux donc pas juger ce qui serait plus faisable.

Dans tous les cas, publier des problèmes sur GitHub est toujours une bonne idée. Cela permet de prendre conscience du problème et de recueillir de l'aide, des idées pour résoudre les problèmes.

Bon. Nous allons classer les problèmes au fur et à mesure. Je comprends que ce sera un défi de trouver un correctif sans pouvoir reproduire un débordement. Alors, quelles informations pouvons-nous fournir pour rendre le problème plus clair ? Est-ce que le chemin jusqu'à la sous-verse en béton aide? C'est-à-dire : fournir le nombre d'itérations, les valeurs actuelles des locaux avec les noms de fichiers, etc. ?

Je suis heureux que nous suivions cette voie, mais je recommanderais d'y aller doucement.

Même chose ici! :)

L'un des résultats de #577 est que LAPACK s'appuie sur le compilateur FORTRAN pour implémenter une division complexe raisonnablement robuste (sous-/débordement) et ABS(). Je me demande si nous devrions commencer à maintenir un document, à collecter des exigences telles et similaires ? Ils seront tout aussi importants et utiles pour tous ceux qui souhaitent utiliser LAPACK avec d'autres / nouveaux compilateurs, pour les constructeurs de compilateurs et afin de transférer des parties ou la totalité des algorithmes LAPACK vers d'autres langages ?

Sûr! Il serait bon que ces informations soient bien documentées.

Pour commencer, j'ai passé du temps à tracer (peut-être) toutes les divisions dans les fichiers LAPACK/SRC/z*.f (algorithmes COMPLEXE*16) du formulaire

 REAL / COMPLEX   or   COMPLEX / COMPLEX

J'ai trouvé un total de 53 fichiers. Voir le fichier joint : complexDivisionFound.code-search

  • Pour cela, j'ai utilisé l'expression REGEX dans le code Visual Studio :

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

Peut-être que pour gfortran, nous devrions compiler avec les indicateurs -mfpmath=sse -msse2 à des fins de test. Je pense que cela forcera tous les calculs à être effectués avec une arithmétique 64 bits. Je ne suis pas sûr cependant.

Oui, cela devrait être le cas lors de l'utilisation de GCC, mais ce drapeau devrait également être défini par défaut sur x86-64. L'extrait de documentation ci-dessous concerne GCC 11, mais les versions beaucoup plus anciennes de GCC devraient présenter le même comportement. Utilisation de la collection de compilateurs GNU (GCC) : 3.19.59 options x86

sse

Utilisez des instructions à virgule flottante scalaires présentes dans le jeu d'instructions SSE. Ce jeu d'instructions est pris en charge par les puces Pentium III et plus récentes, et dans la gamme AMD par les puces Athlon-4, Athlon XP et Athlon MP. La version précédente du jeu d'instructions SSE ne prend en charge que l'arithmétique simple précision, donc l'arithmétique double précision et étendue est toujours effectuée à l'aide de 387. Une version ultérieure, présente uniquement dans les puces Pentium 4 et AMD x86-64, prend en charge l'arithmétique double précision. trop.

Pour le compilateur x86-32, vous devez utiliser les commutateurs -march=cpu-type , -msse ou -msse2 pour activer les extensions SSE et rendre cette option effective. Pour le compilateur x86-64, ces extensions sont activées par défaut.

Le code résultant devrait être considérablement plus rapide dans la majorité des cas et éviter les problèmes d'instabilité numérique du code 387, mais peut casser un code existant qui s'attend à ce que les temporaires soient de 80 bits.

C'est le choix par défaut pour le compilateur x86-64, les cibles Darwin x86-32 et le choix par défaut pour les cibles x86-32 avec le jeu d'instructions SSE2 lorsque -ffast-math est activé.

Exemple:
XEIGTSTZ < zec.in - échoue en raison d'un débordement dans ZLAHQR.
Etapes à reproduire : ZGET37 -> knt == 31, ZHSEQR -> ZLAHQR -> à la fin de la deuxième étape QR (ITS == 2) le code suivant provoque un débordement (sur certains registres, voir ci-dessous)

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 )

Notre compilateur cible le .NET CLR. Son JIT décide d'utiliser des registres SSE pour ABS(TEMP), ce qui conduit au dépassement dans le calcul intermédiaire de la grandeur. Ifort (comme autre exemple) utilise des registres à virgule flottante dans cette situation, donc ne déborde pas (en raison de sa plus grande longueur : 80 bits). J'essaie d'avoir une (plus) image claire de ce à quoi s'attendre de LAPACK en ce qui concerne la précision / plage de nombres requise du compilateur / processeur au moment de l'exécution.

Récapituler:

  • Vous avez transpilé un demi-million de lignes de Fortran77 en C#.
  • Le test du code transpilé échoue lors de l'utilisation du compilateur juste-à-temps .NET.
  • Le test du code LAPACK vanille réussit lors de l'utilisation du compilateur Intel Fortran (ifort).
  • La différence observée entre les deux cas est l'utilisation d'intermédiaires 80 bits par ifort qui évite un débordement.

Correct?

Par défaut, GCC ne génère que du code pour les registres flottants 64 bits sur x86-64 et sur mes machines, généralement tous les tests LAPACK réussissent, à l'exception d'un ou deux.

La suite de tests Netlib LAPACK réussit-elle lors de la compilation avec GCC ?

modifier : résolu https://github.com/Reference-LAPACK/lapack/pull/577#issuecomment -859496175

Peut-être, pour gfortran, nous devrions compiler avec les drapeaux -mfpmath=sse -msse2 à des fins de test. Je pense que cela forcera tous les calculs à être effectués avec une arithmétique 64 bits. Je ne suis pas sûr cependant.

J'ai essayé -mfpmath=sse -msse2 avec GCC 11 sur MacOS et Linux : https://github.com/weslleyspereira/lapack/actions/runs/966071530. Il n'y a eu aucune erreur supplémentaire par rapport au flux de travail sans ces indicateurs : https://github.com/Reference-LAPACK/lapack/actions/runs/945060330. Voir #591

@hokb , pourriez-vous reproduire les problèmes de débordement que vous avez mentionnés dans https://github.com/Reference-LAPACK/lapack/issues/575#issuecomment -855880000 avec GCC en utilisant les indicateurs SSE ? Pouvez-vous m'aider?

@weslleyspereira Je n'ai même pas essayé GCC. Tout ce que j'ai accès à / une configuration en cours d'exécution est ifort sur Windows. Il me faudrait quelques jours pour que GCC soit opérationnel via cygwin pour le tester (en particulier depuis ma chambre d'hôtel de vacances actuelle ... :| ) Faites-moi savoir si vous avez besoin de moi pour relever ce défi, cependant !
Au moins et selon https://godbolt.org/z/YYv5oPxe9 l' utilisation des drapeaux n'affecte pas le code généré par gfortran. Mais bien sûr, seul un test le dira avec certitude ...

Je n'utilise pas Windows, mais je l'ai ici. Je vais commencer par tester LAPACK avec ifort sur mon Ubuntu et voir ce qui se passe. Profite des vacances!

Cette page vous a été utile?
0 / 5 - 0 notes