Lorsque ce calcul en virgule flottante est exécuté dans boost::thread
le résultat est différent de celui obtenu avec l'exécution en std::thread
ou dans le fil principal.
void print_number()
{
double a = 5.66;
double b = 0.0000001;
double c = 500.4444;
double d = 0.13423;
double v = std::sin(d) * std::exp(0.4 * a + b) / std::pow(c, 2.3);
printf("%llX\n%0.25f\n", *reinterpret_cast<unsigned long long*>(&v), v);
}
Cela semble se produire parce que boost::thread
utilise par défaut une précision interne de 53 bits pour les calculs en virgule flottante, alors que le thread principal utilise une précision de 64 bits. Si l'état de l'unité FPU est réinitialisé avec la commande _fpreset()
après le boost::thread
a été créé, le résultat est le même que dans le thread principal.
J'utilise Embarcadero C++ Builder 10.1 (compilateur bcc32c version 3.3.1) et Boost 1.55.0. Mon environnement est Windows 7, et je construis pour une cible Windows 32 bits.
Exemple de travail :
#include <tchar.h>
#include <thread>
#include <boost/thread.hpp>
#include <cstdio>
#include <cmath>
#include <cfloat>
namespace boost { void tss_cleanup_implemented() {} }
void print_number()
{
double a = 5.66;
double b = 0.0000001;
double c = 500.4444;
double d = 0.13423;
double v = std::sin(d) * std::exp(0.4 * a + b) / std::pow(c, 2.3);
// Edit:
// Avoiding the undefined behaviour by a reinterpret_cast, as
// mentioned in some answers and comments.
unsigned long long x;
memcpy(&x, &v, sizeof(x));
printf("%llX\n%0.25f\n", x, v);
}
void print_number_2()
{
// Reset FPU precision to default
_fpreset();
print_number();
}
int _tmain(int argc, _TCHAR* argv[])
{
print_number();
std::thread t1(&print_number);
t1.join();
boost::thread t2(&print_number);
t2.join();
boost::thread t3(&print_number_2);
t3.join();
getchar();
return 0;
}
Sortie :
3EAABB3194A6E99A
0.0000007966525939409087744
3EAABB3194A6E99A
0.0000007966525939409087744
3EAABB3194A6E999
0.0000007966525939409087488
3EAABB3194A6E99A
0.0000007966525939409087744
Question :
- Pourquoi cela se produit-il ? Un nouveau thread n'est-il pas censé hériter de l'environnement en virgule flottante du thread parent ?
- S'agit-il d'un bogue dans le compilateur ou dans Boost, ou mes attentes sont-elles fausses ?