Tho*_*est 2 c++ floating-point x86 long-double quadruple-precision
我在 Unix 上编程,使用 g++ 4.8.2 编译器。我目前需要将此时使用的 C++ 程序long double(在我的情况下为 64 位有效位)转换为使用该__float128类型(有效位为 113 位)的程序。我使用了libquadmath0包和 boost 库来做到这一点,但生成的程序比使用long double.
这令人困惑,因为有效数的大小并没有大多少,而且从 切换double到时我没有观察到这种差异long double。这种时间差异是否正常,如果不正常,我该如何解决?
编码:
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include <complex.h>
extern "C" {
#include <quadmath.h>
}
#include <gmp.h>
#include <iomanip>
#include <cfloat>
#include <boost/multiprecision/float128.hpp>
using namespace boost::multiprecision;
using namespace std;
typedef __float128 long_double_t;
void main()
{
...
}
Run Code Online (Sandbox Code Playgroud)
编译说明:
g++ --std=c++11 main.cc -o main -lgmp -lquadmath -Ofast -m64
Run Code Online (Sandbox Code Playgroud)
这是令人困惑的,因为有效数的大小并没有高很多,而且在从 切换
double到时我没有观察到这种差异long double
举个简单的例子:用一个 12 位的袖珍计算器将两个 8 位数字相加,然后将两个 11 位数字相加。你看得到差别吗?现在用那个计算器把两个 23 位数字相加,你认为哪个会更慢?显然最后一个需要更多的操作(还有空间,因为你需要将中间结果写到纸上)
在 x86 中,您有对 IEEE-754 单、双和80 位扩展精度的硬件支持,因此对这些类型的操作完全在硬件中完成,通常只是一条指令。没有来自不同,这是相同的中的x87指令。如果你使用 SSE 那么会比由于使用新的 SIMD 寄存器和指令快一点 long doubledouble + doublelong double + long doubleFADDdoublelong double
__float128但是,当您使用时,编译器需要使用慢得多的软件仿真。您不能long double用 2 条指令添加 2 个值。您需要手动完成所有操作:
这些步骤包括几个分支(可能导致分支预测错误)、内存加载/存储(因为 x86 没有很多寄存器)以及更多最终加起来至少有几十条指令的事情。将这些复杂任务的速度降低 10 倍已经是一项了不起的成就。而且我们还没有进行乘法,当有效位宽度加倍时,乘法难度增加了 4 倍。除法、平方根、求幂、三角……要复杂得多,而且速度会慢很多