2010-05-17 5 views
6

J'ai une petite classe de vecteurs 3D en C# 3.0 basée sur la structure qui utilise le double comme unité de base.La précision en virgule flottante peut-elle être dépendante du fil?

Un exemple: y-valeur un vecteur est

-20.0 straight 

je soustrais un vecteur avec une valeur de y

10.094999999999965 

La valeur pour y j'attendre est

-30.094999999999963   (1) 

A la place, j'obtiens

-30.094999313354492   (2) 

Lorsque je fais tout le calcul dans un seul thread, j'obtiens (1). Le débogueur et la fonction VS-watch reviennent également (1). Mais, quand je lance quelques itérations dans un thread et que j'appelle la fonction d'un thread différent, le résultat est (2). Maintenant, le débogueur renvoie aussi (2)!

Nous devons garder à l'esprit le .NET JIT pourrait écrire les valeurs en mémoire (site Web Jon Skeet) qui réduit la précision de 80 bits (FPU) à 64 bits (double). Cependant, l'exactitude de (2) est loin en dessous de cela.

La classe vecteur ressemble fondamentalement à ce

public struct Vector3d 
{ 
    private readonly double _x, _y, _z; 
    ... 
    public static Vector3d operator -(Vector3d v1, Vector3d v2) 
    { 
     return new Vector3d(v1._x - v2._x, v1._y - v2._y, v1._z - v2._z); 
    } 
} 

Le calcul est aussi facile que ce

Vector3d pos41 = pos4 - pos1; 

Répondre

5

Oui, je crois que le résultat peut dépendre du fil. J'imagine que vous utilisez DirectX à un moment donné dans votre code - et cela définit la précision pour la FPU, et je crois qu'elle le définit sur une base par thread.

Pour résoudre ce problème, utilisez le drapeau D3DCREATE_FPU_PRESERVE lorsque vous appelez CreateDevice. Notez que cela aura potentiellement un impact sur les performances. L'équivalent géré est CreateFlags.FpuPreserve.

(Voir this related question. Je ne l'ai pas laissé entendre que celui-ci soit fermé en double, comme ils au moins regard un peu différent sur la surface. Avoir les deux devraient aider la réponse à découvrable.)

+0

C'est vrai, j'utilise une bibliothèque qui crée un périphérique Direct3D. Merci! Existe-t-il un moyen de définir vous-même la précision du CLR, je veux dire en dehors de Direct3D? – msteiger

+0

@ isométrique-dieu: Je soupçonne qu'il existe, mais je ne le sais pas. Je ne pense pas que ce soit une chose CLR - je suppose que c'est une propriété générale de "précision pour ce thread" pour tout le code, géré et non géré. –

+0

Il n'y en a pas. Le CLR fait des hypothèses difficiles sur le mot de configuration FPU. Il existe un moyen de le réinitialiser, lancer et attraper une exception. Ensuite, maintenant, il est dans le mauvais état pour le code DirectX. –

Questions connexes