Numpy: Avertissement par np.float32 .__ mul__ compilé par clang

Créé le 27 avr. 2017  ·  53Commentaires  ·  Source: numpy/numpy

À Sagemath, nous rencontrons dans notre ticket # 22799

RuntimeWarning: invalid value encountered in multiply

en multipliant un nombre numpy.float32 avec une donnée non numpy; c'est-à-dire que numpy ne devrait pas faire cette multiplication en silence, et en effet il le fait si on construit avec gcc, ou si au lieu de np.float32 c'est np.float ou np.float128 .

Plus précisément, on obtient l'avertissement de l'appel Python

type(numpy.float32('1.5')).__mul__(numpy.float32('1.5'), x)

x est un polynôme univarié de Sagemath avec des coefficients de type RealField Sagemath. (et seul ce type particulier de données déclenche cela).
Autrement dit, potentiellement, de tels avertissements sans signification peuvent être émis en dehors de Sagemath; nous pouvons le reproduire sur OSX 11.12 avec son stock cc (un dérivé de clang 3.8), ainsi que sur Linux avec clang 4.0 et sur FreeBSD 11.0 avec clang 4.0 ou clang 3.7.

Potentiellement, nous devrions être en mesure de produire un moyen de reproduire cela en dehors de Sagemath, bien que nous aurions besoin de quelques conseils où dans le code numpy ce __mul__ est réellement implémenté, pour voir quelles fonctions sont appliquées à x ...

Nous voyons cela sur numpy 1.11 et sur 1.12, aussi.

Tous les 53 commentaires

même image avec numpy.float32('1.5').__mul__(x) ainsi que __add__ et __sub__ .

Ce type d'erreur est typique des tableaux contenant nan ou infinity . Que retourne np.array(x) ?

@ eric-wieser: il renvoie array(x, dtype=object) , aucun avertissement.

Est-ce que np.multiply(np.float32('1.5'), x) donne le même avertissement?

numpy.multiply(numpy.float32('1.5'), x) donne le même avertissement.

Et pour type(x).__rmul__(numpy.float32('1.5'), x) ?

De plus, si vous pouviez exécuter warnings.filterwarnings('error') , vous obtiendriez une trace complète de la pile

type(x).__rmul__(numpy.float32('1.5'), x)

TypeError: descriptor '__rmul__' requires a 'sage.structure.element.Element' object but received a 'numpy.float32'

x.__rmul__(numpy.float32('1.5')) se passe très bien.

Il semble que j'ai oublié comment fonctionne rmul . Je voulais dire type(x).__rmul__(x, numpy.float32('1.5')) , mais j'imagine que cela fait la même chose que x.__rmul__ , à moins que x soit vraiment bizarre

Cela échoue-t-il également? np.multiply(np.array(1.5, dtype=object), x) (cette fois avec filterwarnings , s'il vous plaît)

type(x).__rmul__(x,numpy.float32('1.5')) passe sans avertissement.

Et, au fait, définir warnings.filterwarnings('error') ne me donne rien d'intéressant,

---------------------------------------------------------------------------
RuntimeWarning                            Traceback (most recent call last)
<ipython-input-50-b3ece847d318> in <module>()
sage: np.multiply(np.array(1.5, dtype=object), x)
---------------------------------------------------------------------------
RuntimeWarning                            Traceback (most recent call last)
<ipython-input-52-706823a0b5a2> in <module>()
----> 1  np.multiply(np.array(RealNumber('1.5'), dtype=object), x)

RuntimeWarning: invalid value encountered in multiply

Hmm, sage a fait quelque chose auquel je ne m'attendais pas. Même comportement avec float('1.5') , je suppose?

Ok, alors voici ce que je pense qu'il se passe:

  • numpy utilise correctement la boucle d'objet dans ufunc, qui finit par appeler PyNumber_Multiply
  • Dans sage , quelque chose est en train de définir le drapeau d'erreur dans le FPU (bogue dans sage?)
  • numpy fait sa vérification normale du drapeau fpu à la sortie de ufunc (bogue dans les boucles d'objets?), Et trouve l'erreur laissée par sage
sage: float(1.5).__mul__(x)
NotImplemented
sage: np.float(1.5).__mul__(x)
NotImplemented
sage: np.float32(1.5).__mul__(x)
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x
sage: np.float64(1.5).__mul__(x)
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x

A noter que np.float is float pour des raisons de compatibilité

pourquoi np.float32(1.5).__mul__(x) retourne pas NotImplemented ?

Parce qu'il sait qu'il peut le gérer comme np.multiply avec une boucle d'objet, puis réessayer avec float * x intérieur de cette boucle. Malheureusement, le wrapper autour de cette boucle récupère les indicateurs FPU définis par sage.

Si vous regardez de plus près, vous constaterez que x.__rmul__ est toujours appelé plus profondément dans la pile

sage: np.float32(1.5)*x
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x
sage: np.float128(1.5)*x
1.50000000000000*x
sage: np.float64(1.5)*x
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x

il semble donc que np.float128 est OK, mais

sage: np.float128(1.5).__mul__(x)
/usr/home/dima/Sage/sage/src/bin/sage-ipython:1: RuntimeWarning: invalid value encountered in multiply
  #!/usr/bin/env python
1.50000000000000*x

C'est bizarre. Un bogue du compilateur, peut-être (comme on ne le voit jamais sur gcc), mais à quel endroit?

L'indicateur FPU est pour une raison quelconque défini sur clang mais pas gcc dans le code sage, semble-t-il. Numpy est à blâmer pour avoir fait du bruit à ce sujet, mais je doute fortement que ce soit à blâmer pour l'avoir créé en premier lieu.

Malheureusement, numpy n'expose aucun moyen de demander explicitement les drapeaux FPU - ce serait très utile pour couper en deux le problème dans sage.

Je suppose que cela provoque le même avertissement (nécessite numpy 1.12 pour le faire, je pense)

mul = np.vectorize(x.__rmul__)
mul(float('1.5'))

pas tout à fait pareil, mais proche:

/usr/home/dima/Sage/sage/local/lib/python2.7/site-packages/numpy/lib/function_base.py:2652: RuntimeWarning: invalid value encountered in __rmul__ (vectorized)
  outputs = ufunc(*inputs)
array(1.50000000000000*x, dtype=object)

OK, bien, cela semble indiquer qu'il n'y a rien de spécifique avec np.float32 ou np.float64 , c'est un mécanisme numpy plus générique pour générer des avertissements.

Je ne sais pas si les auteurs du compilateur le considéreraient comme un bogue. Le fonctionnement de l'avertissement est qu'il existe des indicateurs d'état magiques dont le processeur garde la trace, qui sont automatiquement définis chaque fois que l'événement correspondant se produit. Numpy les efface avant de commencer le calcul, puis les vérifie à nouveau à la fin. Donc, quelque part entre ces points, l'assemblage généré par clang fait un calcul qui implique un NaN. Mais il est difficile de le localiser (puisque le paramétrage du drapeau réel est entièrement effectué dans le matériel), et la plupart du temps, les gens ne s'inquiètent pas de la façon dont leur code affecte les indicateurs fpu. (Les implémentations de Libm sont également notoirement incohérentes quant à savoir si elles définissent ces indicateurs.) Et les résultats exacts dépendent beaucoup de l'asm exact généré, il n'est donc pas surprenant que vous ne le voyiez que dans des configurations spécifiques et pas dans d'autres.

Oui, cela confirme mes soupçons et vous fournit un moyen de déboguer. Ce code

def check_fpu(f):
    @functools.wraps(f)
    def wrapped(*args, **kwargs):
        excluded = list(range(len(args))) + list(kwargs.keys())
        fvec = np.vectorize(f, excluded=excluded)
        return fvec(*args, **kwargs)
    return wrapped

Appliqué à une fonction python, vous permet d'isoler les avertissements dans ce morceau de code.

Je veux dire, c'est assez étrange que cela se passe du tout; les compilateurs n'inventent généralement pas puis ne jettent pas les NaN sans raison.

Si vous essayez de le localiser, alors vous devriez probablement regarder le code dans sage qui implémente la multiplication pour ces polynômes - il est probable que le paramètre de drapeau étrange se produise probablement tout le temps, et la seule implication de numpy est de rendre cela visible .

Il y a aussi un assez bon argument selon lequel numpy ne devrait même pas essayer de vérifier ces indicateurs sur les boucles d'objets. (Ou des boucles entières d'ailleurs, mais c'est délicat parce que la façon dont nous signalons le dépassement d'entiers est un peu grossière et utilise les drapeaux fpu.) C'est la seule chose que je peux penser que numpy pourrait faire ici.

check_fpu() a une faute de frappe, il devrait y avoir fvec = np.vectorize(f, excluded=exclude) .
Et nous sommes sur python2: import functools32 as functools .

functools.wraps n'a pas besoin de python 3, n'est-ce pas?

J'obtiens une erreur si j'utilise les functools de python2, dans setattr() call

AttributeError: 'method-wrapper' object has no attribute '__module__'

Oui, je suppose que c'est n'importe quelle bibliothèque multi-précision implémentant l'arithmétique pour les coefficients dans RealField qui définit le drapeau FPU. Les bibliothèques sous-jacentes sont-elles compilées avec le même compilateur que numpy dans chacune des différentes circonstances? Ou est seulement numpy en cours de reconstruction avec les différents compilateurs?

Ouais, je suppose que c'est n'importe quelle bibliothèque multi-précision implémentant l'arithmétique pour les coefficients dans RealField

C'est MPFR pour mémoire.

Nous essayons de porter Sagemath sur clang + gfortran (principalement sur OSX et FreeBSD, plates-formes où clang est le compilateur principal), de sorte que le construire et l'exécuter sur OSX soit plus facile et plus rapide (FreeBSD est plus un outil pour obtenir un environnement similaire sans les tracas du matériel OSX et Apple).

Toutes les comparaisons que je rapporte ici concernent des constructions complètes avec clang / clang +++ gfortran par opposition à gcc / g +++ gfortran.

le wrapper semble nous dire que x.__rmul__ configure le drapeau FPU

check_fpu(x.__rmul__)(np.float32('1.5'))

affiche l'avertissement, contrairement à x.__rmul__(np.float32('1.5')) .

En effet - mon hypothèse était que x.__rmul__ été écrit en python, et que son code source peut être coupé en deux pour trouver quel bit définit spécifiquement le drapeau

x.__rmul__ est en Cython, mais c'est quand même un petit morceau de code à étudier.

S'il y avait un moyen simple de changer l'avertissement en erreur, vous obtiendrez un suivi (Cython génère des retraits pour les erreurs mais pas pour les avertissements).

@jdemeyer IMHO numpy warning est émis beaucoup plus tard dans le chemin du code, c'est-à-dire qu'il résulte d'une vérification explicite des drapeaux FPU, pas d'un jeu d'interruptions.

numpy fournit une interface pour changer cet avertissement en erreur, mais tout ce que vous obtenez est que vous revenez à la boucle principale de l'interpréteur iPython, sans aucune trace.

@jdemeyer est- ce que le code Cython entre sig_on() / sig_off() de cysignals lèvera une exception si un drapeau FPU est levé? Ou cela dépend du drapeau?

cysignals lèverait une exception si SIGFPE est levé, ce qui peut se produire si un drapeau FPU est levé, en fonction de la configuration du FPU. Mais par défaut, ce n'est pas le cas.

Un avertissement similaire: RuntimeWarning: invalid value encountered in greater est
provenant de np.float64(5)>e . Ici e est la constante de Sagemath spécifiant la base du logarithme naturel 2,71828 ..., et ainsi de suite pour évaluer cela en True il doit être "converti" (certainement, e "sait "son approximation numérique, c'est e.n() ) à un nombre.
Cette approximation est du type RealField déjà mentionné ci-dessus (donc peut-être que cet avertissement est étroitement lié).

Encore une fois, la question est: que fait numpy pour évaluer np.float64(5)>e ?
Ou de manière équivalente, le même avertissement apparaît à partir de np.float64(5).__gt__(e) , donc on peut tout aussi bien commencer à partir de là.

Notez que type(e) est sage.symbolic.constants_c.E ; c'est fondamentalement une classe (presque) factice
enveloppant les expressions symboliques de Sagemath ( SR ).

Il n'y a aucun avertissement de np.float64(5).__gt__(e.n()) ou np.float64(5)>e.n() .
Essentiellement le même (même modèle d'avertissement / pas d'avertissement) se produit si vous remplacez e par pi (avec pi.n()==3.1.415... évident).
pi a le type SR , soit sage.symbolic.expression.Expression .

La réponse est la même ici - numpy appelle np.greater avec une boucle d'objet. Au niveau inférieur, cela appelle e.__lt__(5.0) . Mais encore une fois, il vérifie les drapeaux FPU avant et après, et remarque que quelque chose ne va pas.

La plupart des opérateurs arithmétiques / logiques ndarray (à l'exception de - et divmod ) sont délégués à ufuncs. Lorsqu'il est appelé avec des objets sage, cela appellera les boucles O (objet) pour ces ufuncs. Ces boucles d'objet boucleront sur le tableau (qui dans ce cas est 0d), exécutent l'opérateur python normal sur les éléments, _ mais vérifiez les indicateurs FPU quand il le fait_.

Donc, encore une fois, sage définit ces drapeaux. C'est peut-être le signe d'un bug, peut-être que ce n'est pas le cas.

Je pense qu'il y a un bon argument ici que numpy ne devrait pas vérifier les drapeaux fpu pour ces cas. @njsmith , pensez-vous que nous devrions continuer à supprimer la vérification des types d'objets?

En fait, e.__lt__(5.0) est une expression symbolique:

sage: type(e.__lt__(np.float32(5.0)))
<type 'sage.symbolic.expression.Expression'>
sage: e.__lt__(np.float32(5.0))
e < 5.0
sage: bool(e.__lt__(np.float32(5.0)))  # this is how it's evaluated
True

et donc je doute vraiment qu'il soit appelé au final, car on obtient True . De plus, votre wrapper check_fpu ci-dessus ne le fait pas afficher d'avertissements, c'est-à-dire que ce qui suit fonctionne.

sage: check_fpu(e.__lt__)(np.float32(5.0))
e < 5.0

J'ai pu épingler notre problème dans Sagemath à une extension C particulière en utilisant le module fpectl Python (qui est un peu, mais pas totalement, cassé sur FreeBSD). C'était en fait très rapide une fois que j'ai réussi à l'installer.

IMHO fpectl est si utile qu'il devrait être corrigé ; peut-être même utilisé dans numpy à la place ou en plus de np.seterr() , car il offre une meilleure granularité sur les composants compilés.

La différence entre l'approche de fpectl et np.seterr est:

np.seterr exécute la boucle ufunc, puis vérifie si des indicateurs sont définis.

fpectl fait de la magie pour faire en sorte que chaque fois qu'une opération se produit et entraîne la définition de l'un des indicateurs, le matériel déclenche une interruption, le noyau le convertit en un SIGFPE livré au processus et installe un Gestionnaire SIGFPE que longjmp s directement hors du gestionnaire de signal dans le code de gestion des erreurs.

Certains inconvénients de l'approche fpectl sont les suivants: (a) cela ne fonctionne pas du tout sous Windows, (b) il se casse pour le code qui provoque en interne un de ces indicateurs à être temporairement défini puis l'efface (ceci est légal et je pense qu'il existe des libm qui le font), (c) longjmp est incroyablement fragile; en gros, vous risquez un segfault chaque fois que vous le faites. Cela ne peut certainement pas être une solution générale pour les ufuncs arbitraires définis par l'utilisateur.

Compte tenu de tout cela, je ne pense pas que numpy va changer.

Dans tous les cas, il semble que le problème d'origine soit résolu, alors fermez-le - n'hésitez pas à ouvrir un nouveau problème si vous souhaitez faire valoir des modifications dans seterr .

Dans tous les cas, il semble que le problème d'origine soit résolu

Sommes-nous sûrs de ne pas vouloir désactiver la vérification des indicateurs FPU pour les boucles d'objets? Cela semblerait être un changement assez judicieux de numpy.

@ eric-wieser: oh, c'est une idée intéressante, oui. ça vaut peut-être la peine d'ouvrir un numéro pour ça :-). La "bonne chose" est cependant assez compliquée - idéalement, nous ne devrions pas encapsuler spécialement l'objet dtype (pensez aux dtypes utilisateur), et les boucles entières ne devraient pas non plus l'utiliser (cela peut être une véritable optimisation sur certaines architectures où vérifier / effacer les drapeaux FPU est extrêmement lent), mais les boucles entières ont besoin d'un moyen de signaler explicitement les erreurs entières, ce qu'elles font actuellement en définissant explicitement les drapeaux FPU, ... Je ne suis pas sûr que ce soit un cas où il y a un faible faible -rendre des fruits?

Ou ai-je mal compris, et sage a seulement identifié le problème, et ils ont encore besoin d'un changement numpy pour le résoudre?

@njsmith : Je ne comprends pas pourquoi vous dites que cela ne fonctionnera pas sous Windows. (Ce serait correct dans l'ère pré-C99, cependant). Les fonctions modernes de gestion des FPU (fenv) sont disponibles dès que votre compilateur C est conforme à la norme C99. En dehors de fenv, tout ce dont il a besoin est setjmp / longjmp (encore une fois, la fonction C standard).

Je suis également curieux d'entendre parler d'une libm qui provoque l'une des exceptions FE au cours d'une opération normale.
(À moins qu'il ne soit classé comme un bogue).

@dimpase : Vous avez également besoin du support SIGFPE, qui n'est pas spécifié dans C99. (Eh bien, C99 dit qu'il devrait y avoir un SIGFPE, mais c'est pour la division par zéro - il ne spécifie aucun moyen de le connecter à des exceptions en virgule flottante.) Cela dit, il semble que je me suis mal souvenu, et bien que Windows ne prend pas en charge les signaux, MSVCRT émule SIGFPE en utilisant la gestion structurée des exceptions et fournit la fonction non standard _control_fp pour l'activer pour des exceptions fp particulières, de sorte que la prise en charge de Windows n'est pas réellement une barrière. OTOH cela n'a pas tellement d'importance puisque longjmp ne se produit certainement pas sans une très bonne raison :-)

Et FWIW, si une libm provoquait une exception FE puis l'effaçait à nouveau, je ne vois pas pourquoi ils considéreraient cela comme un bogue. Je ne suis pas sûr que de telles implémentations existent, mais c'est plausible, et si elles le font, la façon dont nous le découvririons est que quelqu'un nous dit que numpy est cassé sur la plate-forme X et que la seule solution serait d'annuler le changement vous avez suggéré.

Pouvez-vous répondre à la question que j'ai posée à la fin de mon commentaire précédent?

@njsmith : si une libm (ou tout autre code utilisateur) doit provoquer une exception FE et la traiter, elle mettra en place son propre gestionnaire d'exceptions FE, sauvegardant le précédent et restaurant le précédent en quittant.
Ce n'est donc pas un problème si le code sous-jacent respecte les règles.

En ce qui concerne la prise en charge de MS pour cela, ils livrent fenv.h depuis Visual C (++) 2013 environ .
Il est spécifiquement destiné à être utile avec setjmp / longjmp (comment exactement cela se fait sous le capot ne devrait pas trop inquiéter, j'espère).

Concernant le Runtime de numpy

  • si vous pensez que le code utilisateur peut jouer rapidement et librement avec les drapeaux FP, alors ces avertissements devraient être tout au plus facultatifs.
  • sinon, ils peuvent rester standard, mais au moins un moyen d'aller au fond de l'endroit d'où ils viennent est crucial pour leur utilité; (amélioré) fpectl est un moyen rapide d'atteindre ce dernier. L'utilisation d'outils externes (tels que les débogueurs vous permettant d'instrumenter le code pour vérifier quelque chose après chaque instruction) est plus difficile, plus lent et plus sujet aux erreurs --- par exemple, il n'est pas inhabituel que le bogue n'apparaisse que sur un binaire optimisé, et disparaît dès que vous essayez de le trouver sur un binaire bien débuggable.
  • dans tous les cas, la chose RuntimeWarning devrait pouvoir s'éteindre.

Concernant ce problème dans Sage - toujours en cours de résolution (j'espère qu'il est limité à certains problèmes dans MPFR uniquement).

Désolé, cela tourne en rond et je dois passer à autre chose, donc à moins que quelque chose de nouveau ne survienne sur le problème fenv / sigfpe, ce sera mon dernier message sur le sujet. (Je suis toujours intéressé à savoir s'il y a quelque chose de numpy à faire pour le bogue sage).

si une libm (ou tout autre code utilisateur) a besoin de provoquer une exception FE et de la traiter, elle mettra en place son propre gestionnaire d'exceptions FE, en sauvegardant le précédent,

Ce que vous proposez, c'est de prendre une opération qui normalement ne provoque pas le déclenchement d'un gestionnaire de signaux, et de configurer le processeur dans un mode non standard où il provoque le déclenchement d'un gestionnaire de signaux. Il est tout à fait raisonnable que le code effectue cette opération et s'attende à ce qu'il ne déclenche pas du tout un gestionnaire de signal.

En ce qui concerne la prise en charge de MS pour cela, ils livrent fenv.h depuis Visual C (++) 2013 environ.
Il est spécifiquement destiné à être utile avec setjmp / longjmp

Je ne sais pas de quoi vous parlez ici. AFAICT, la fonctionnalité standard dans fenv.h est utile pour la mise en œuvre des fonctionnalités de style numpy et des bâtons MS à la norme. Je ne vois aucune fonction qui pourrait être utilisée avec setjmp / longjmp du tout.

le code utilisateur peut jouer rapidement et librement avec les drapeaux FP, alors ces avertissements devraient être au maximum facultatifs.

Effacer soigneusement un drapeau fixé par un calcul intermédiaire est l'exact opposé de jouer vite et lâche avec eux. De plus, les avertissements sont facultatifs.

un moyen d'aller au fond de l'endroit d'où ils viennent est crucial pour leur utilité; (amélioré) fpectl est un moyen rapide d'atteindre ce dernier.

Vous êtes littéralement la première personne en quelque chose comme une décennie à avoir besoin de SIGFPE pour déboguer ce genre de problème, et en regardant à nouveau les commentaires de bogue sage, il semble que vous n'ayez pas fait fonctionner fpectl? Il n'est pas censé provoquer un vidage de mémoire. (Il semble que cysignals écrase le code fpectl donc il ne s'exécute même pas.)

Si cela se reproduit, vous devez effectuer un appel C pour activer SIGFPE, puis utiliser un débogueur pour obtenir une trace de la pile. Vous n'avez pas besoin d'une version de débogage pour obtenir une trace de pile; tout ce que vous avez à faire est de ne pas dépouiller les symboles. Et bon, maintenant nous savons au cas où cela se reproduirait.

Je comprends que cela a été vraiment frustrant à déboguer, mais il n'est pas utile d'insister sur le fait que d'autres projets doivent changer ou maintenir l'infrastructure de base alors que vous ne pouvez même pas expliquer clairement ce que cela va accomplir. (En fait, je n'ai aucune idée de comment vous pensez que changer quelque chose ici vous aiderait même à trouver ce type de bogue plus rapidement - l'idée même de longjmp est de détruire les informations plus précises que vous dites que vous voulez.)

Enfin, il s'avère que cela se résume à un bogue de longue date dans le compilateur clang C. Fondamentalement, dans une certaine plage de double une affectation comme dans

unsigned long a;
double b;
...
a = b;

lève FE_INVALID (et parfois FE_INEXACT ); btw cela affecte également d'autres types de données flottantes. Un excellent MPFR (MPFR doit copier des doubles dans leurs flotteurs de précision arbitraires, certainement), les gens ont fourni une solution de contournement, corrigeant cela pour sage.

Incidemment, un bug clang fenv.h de Clang pour faire fonctionner correctement fpectl pour le moment. . Clang n'est pas entièrement conforme à C99 à cet égard, et il est vraiment timide à ce sujet.

Je ne sais pas si numpy veut faire quelque chose à ce sujet; peut-être qu'une remarque selon laquelle RuntimeWarning pourrait être simplement due à un bogue du compilateur (citant "clang bug 8100", c'est un exemple assez important) pourrait être utile.

le bogue 8100 n'est pas pertinent; c'est aux pragmas C99 de désactiver les optimisations en virgule flottante, et aucun compilateur grand public ne les prend en charge. numpy semble fonctionner (principalement) de toute façon :-)

L'esprit du bogue 8100 est que clang ne se soucie pas que les opérations FP soient correctement compilées; bien qu'un avocat puisse ne pas être d'accord. :-)

OK, le bogue 17686 déjà mentionné est

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