Когда этот расчет с плавающей запятой выполняется в boost::thread
, он дает отличный результат, чем при выполнении в std::thread
или в основном потоке.Почему этот расчет дает разные результаты в boost :: thread и std :: thread?
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);
}
Это, кажется, происходит потому, что boost::thread
по умолчанию с использованием 53-битной внутренней точности с плавающей точкой математике, в то время как основной поток использует 64-битную точность. Если состояние блока FPU сбрасывается с _fpreset()
после создания boost::thread
, результат будет таким же, как в основном потоке.
Я использую Embarcadero C++ Builder 10.1 (компилятор bcc32c версии 3.3.1) и Boost 1.55.0. Моя среда - это Windows 7, и я строю для 32-битной цели Windows.
Рабочий пример:
#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;
}
Выход:
3EAABB3194A6E99A
0.0000007966525939409087744
3EAABB3194A6E99A
0.0000007966525939409087744
3EAABB3194A6E999
0.0000007966525939409087488
3EAABB3194A6E99A
0.0000007966525939409087744
Вопрос:
- Почему это происходит? Разве новый поток не должен наследовать среду с плавающей запятой из родительского потока?
- Это ошибка в компиляторе или в Boost, или мои ожидания ошибочны?
Полностью несвязанный, но я должен сказать, что ваша презентация вопроса абсолютно * звездная *. – WhozCraig
Просто из любопытства, какую операционную систему вы использовали? – PeterT
@PeterT Я использую Windows 7. –