Floating point x87中的扩展(80位)双浮点,而不是SSE2-我们没有';你不会错过的吧?

Floating point x87中的扩展(80位)双浮点,而不是SSE2-我们没有';你不会错过的吧?,floating-point,sse2,x87,Floating Point,Sse2,X87,我今天读了一篇关于。显然,这对于速度超过精度的并行数据集来说是次优的。然而,文章作者继续引用: 英特尔在2000年底推出了P4,开始阻止x87的使用。AMD自2003年推出K8以来就不推荐使用x87,因为x86-64定义了SSE2支持;VIA的C7自2005年以来一直支持SSE2。在64位版本的Windows中,用户模式不推荐使用x87,内核模式完全禁止使用x87。自2005年以来,几乎所有业内人士都推荐SSE而不是x87,并且没有理由使用x87,除非软件必须运行在嵌入式奔腾或486上 我想知道

我今天读了一篇关于。显然,这对于速度超过精度的并行数据集来说是次优的。然而,文章作者继续引用:

英特尔在2000年底推出了P4,开始阻止x87的使用。AMD自2003年推出K8以来就不推荐使用x87,因为x86-64定义了SSE2支持;VIA的C7自2005年以来一直支持SSE2。在64位版本的Windows中,用户模式不推荐使用x87,内核模式完全禁止使用x87。自2005年以来,几乎所有业内人士都推荐SSE而不是x87,并且没有理由使用x87,除非软件必须运行在嵌入式奔腾或486上

我想知道这件事。我知道x87在内部使用80位扩展双精度来计算值,而SSE2没有。这对任何人都不重要吗?这对我来说似乎很奇怪。我知道,当我对平面中的点、线和多边形进行计算时,在进行减法运算时,值可能会出人意料地错误,并且由于精度的不足,区域可能会塌陷,线彼此重叠。我想,使用80位值和64位值可能会有所帮助


这是不对的吗?如果没有,如果x87被淘汰,我们可以用什么来执行扩展双浮点操作?

x87的最大问题基本上是所有寄存器操作都是在80位中完成的,而大多数时候人们只使用64位浮点(即双精度浮点)。发生的情况是,将64位浮点加载到x87堆栈中,并将其转换为80位。在80位中对其执行一些操作,然后将其存储回内存,并将其转换为64位。与仅使用64位执行所有操作相比,您将得到不同的结果,并且使用优化编译器,一个值可能会经过多少次转换是非常不可预测的,因此在进行回归测试时,很难验证您是否得到了“正确”的答案

另一个问题,仅从编写程序集(或间接编写程序集,在为编译器编写代码生成器的情况下)的角度来看,是x87使用寄存器堆栈,而SSE使用可单独访问的寄存器。有了x87,你就有了一堆额外的指令来操作堆栈,我想Intel和AMD更愿意用SSE代码让处理器运行得更快,而不是试图让那些额外的堆栈操作x87指令运行得更快


顺便说一句,如果你有不准确的问题,你会想看一看文章“”,然后可能使用任意精度的数学库(例如GMP)。

另一个答案似乎表明使用80位精度是个坏主意,但事实并非如此。它有时在防止不精确方面起着至关重要的作用,参见W.Kahan的著作


如果你能在速度方面解决问题,请始终使用80位中间算法。如果这意味着您必须使用x87数学,那么就这样做。对它的支持无处不在,只要人们继续做正确的事情,它就会无处不在。

为了正确使用扩展精度数学,语言必须支持一种类型,这种类型可以用来存储中间计算的结果,并且可以替换产生这些结果的表达式。因此,鉴于:

无效打印距离平方(双x1、双y1、双x2、双y2)
{
printf(“%12.6f”,(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
应该有一些类型可用于捕获和替换公共子表达式
x2-x1
y2-y1
,允许将代码重写为:

无效打印距离平方(双x1、双y1、双x2、双y2)
{
某些_型dx=x2-x1;
某些_型dy=y2-y1;
printf(“%12.6f”,dx*dx+dy*dy);
}
不改变程序的语义。不幸的是,ANSI C未能指定任何可用于执行扩展精度计算的平台上的
some_type
的类型,因此将扩展精度类型的存在归咎于英特尔比归咎于ANSI拙劣的支持要常见得多

事实上,扩展精度类型在没有浮点单元的平台上的价值与在x87处理器上的价值一样,因为在这种处理器上,像x+y+z这样的计算需要以下步骤:

  • 将x的尾数、指数和可能的符号解压到单独的寄存器中(指数和符号通常可以“双下铺”)
  • 同样地打开包装
  • 将值的尾数与较低的指数(如果有)右移,然后加上或减去这些值
  • 如果x和y有不同的符号,则向左移动尾数,直到最左边的位为1,并适当调整指数
  • 将指数和尾数重新打包为双精度格式
  • 打开临时结果的包装
  • 打开z
  • 将值的尾数与较低的指数(如果有)右移,然后加上或减去这些值
  • 如果前面的结果和z有不同的符号,左移尾数直到最左边的位为1,并适当调整指数
  • 将指数和尾数重新打包为双精度格式

  • 使用扩展精度类型可以消除步骤4、5和6。由于53位尾数太大,无法容纳少于四个16位寄存器或两个32位寄存器,因此使用64位尾数执行加法并不比使用53位尾数慢,因此使用扩展精度数学可以提供更快的计算速度,而且在支持适当类型以保存临时结果的语言中没有任何缺点。英特尔提供的FPU可以以非FPU芯片上最有效的方式执行浮点运算,这一点没有理由指责英特尔。

    对于许多应用程序(mo),双精度比f80低11位(约2.5个半字节/位)