cod*_*zen 35 floating-point sse2 x87
我今天正在阅读研究人员发现NVidia的Phys-X库使用x87 FP与SSE2.显然,对于速度超过精度的并行数据集来说,这将是次优的.然而,文章作者继续引用:
英特尔在2000年末引入P4后开始不鼓励使用x87.AMD自2003年K8以来已弃用x87,因为x86-64定义为SSE2支持; VIA的C7自2005年以来一直支持SSE2.在64位版本的Windows中,x87不适用于用户模式,完全禁止在内核模式下使用.自2005年以来,业内所有人都推荐SSE超过x87,除非软件必须在嵌入式Pentium或486上运行,否则没有理由使用x87.
我想知道这件事.我知道x87内部使用80位扩展双精度值来计算值,而SSE2则不然.这对任何人都没关系吗?这对我来说似乎很惊讶.我知道当我对平面中的点,线和多边形进行计算时,在进行减法时,值可能出乎意料地错误,并且由于缺乏精度,区域可能会折叠并且线条会相互别名.我想,使用80位值与64位值可能会有所帮助.
这是不正确的?如果没有,如果x87被淘汰,我们可以用什么来执行扩展的双FP操作?
小智 25
x87的最大问题基本上是所有寄存器操作都是以80位完成的,而大多数时候人们只使用64位浮点数(即双精度浮点数).发生的是,您将64位浮点数加载到x87堆栈中,并将其转换为80位.您以80位对其执行某些操作,然后将其存储回内存,将其转换为64位.你得到的结果与你用64位完成所有操作的结果不同,并且使用优化编译器,一个值可能会经历多少次转换是非常难以预测的,因此很难验证你是否得到了"在做回归测试时纠正"回答".
另一个问题,只有从编写汇编的人的角度来看(或者在为编译器编写代码生成器的情况下间接编写汇编),x87使用寄存器堆栈,而SSE使用单独访问寄存器.使用x87,你有一堆额外的指令来操纵堆栈,我想英特尔和AMD宁愿让他们的处理器使用SSE代码快速运行,而不是试图使那些额外的堆栈操作x87指令快速运行.
顺便说一句,如果你遇到不准确的问题,你会想看看文章" 每个程序员应该知道浮点算术的内容 ",然后可以使用任意精度数学库(例如GMP).
为了正确使用扩展精度数学,语言必须支持可用于存储中间计算结果的类型,并且可以替换产生这些结果的表达式.因此,给出:
void print_dist_squared(double x1, double y1, double x2, double y2)
{
printf("%12.6f", (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
Run Code Online (Sandbox Code Playgroud)
应该有一些类型可以用来捕获和替换公共子表达式,x2-x1并y2-y1允许将代码重写为:
void print_dist_squared(double x1, double y1, double x2, double y2)
{
some_type dx = x2-x1;
some_type dy = y2-y1;
printf("%12.6f", dx*dx + dy*dy);
}
Run Code Online (Sandbox Code Playgroud)
不改变程序的语义.遗憾的是,ANSI C未能指定可用于some_type执行扩展精度计算的平台的任何类型,并且指责英特尔存在扩展精度类型而不是归咎于ANSI的拙劣支持变得更为常见.
实际上,扩展精度类型在没有浮点单元的平台上具有与在x87处理器上一样多的价值,因为在这样的处理器上,像x + y + z这样的计算将需要以下步骤:
使用扩展精度类型将允许消除步骤4,5和6.由于53位尾数太大而不适合少于4个16位寄存器或2个32位寄存器,因此使用64位尾数执行加法并不比使用53位尾数慢,所以使用扩展精度数学提供更快的计算,在支持适当类型以保存临时结果的语言中没有缺点.没有理由指责英特尔提供可能在当时是时尚执行浮点运算的FPU 也非FPU芯片的最有效的方法.