在将应用程序从Linux x86移植到iOS ARM (iPhone 4)时,我发现了浮点算法和小值行为上的差异。
小于+/-2.2250738585072014E-308的64位浮点数(双)在IEEE 754-1985/IEEE 754-2008标准中称为正态/非正态/次正规数字。
在iPhone 4上,这样的小数被视为零(0),而在x86上,可以使用低于正常数来计算。
在苹果的Mac浮动手册页(3)文档中,我没有找到任何关于符合IEEE-754标准的解释。
但是由于堆栈溢出( 浮点算法中的平移零行为,双vs浮动在iPhone上 )上的一些答案,我找到了一些线索。
根据一些搜索结果,沿着ARM核使用的VFP (或霓虹灯)数学协处理器使用的是刷新到零(FTZ)模式(例如,在输出时将低于正常值转换为0)和Denormals- are -Zero (DAZ)模式(例如,当用作输入参数时,低于正常值被转换为0),以提供快速硬件处理的IEEE754计算。
关于FTZ和DAZ的一个很好的解释可以在x87和SSE浮点助攻在IA-32:刷新到零(FTZ)和德诺塔尔-零(DAZ)中找到
FTZ模式和DAZ模式都可以处理无效浮点数据发生或处理时的情况。……由FTZ和DAZ处理的数字之间的差别非常微妙。FTZ处理底流条件,DAZ处理非正态。当计算结果为正态时,就会出现底流状态。在这种情况下,FTZ模式将输出设置为零。DAZ修正了当非正常值被用作输入时,或者作为常量,或者通过将无效内存读入寄存器的情况。DAZ模式在计算前将计算的输入设置为零。然后,可以说FTZ处理输出,而DAZ处理输入。
苹果开发者网站上关于FTZ的唯一内容似乎是在iOS ABI函数调用指南中
函数调用不保留VFP状态寄存器\ FPSCR /特殊条件码位(28-31)和饱和位(0-4)。异常控制(8-12)、舍入模式(22-23)和刷新到零(24)位只能通过影响应用程序状态(包括框架API函数)的特定例程来修改。短矢量长度(16-18)和步长(20-21)位在函数输入和退出时必须为零。所有其他位元都不能修改。
根据ARM1176JZF-S技术参考手册,18.5操作方式 (first iPhone processor),VFP可以配置为完全支持IEEE754(亚法线算法),但在这种情况下需要一些软件支持(陷入内核以在软件中计算)。
注意:我还读过Debian的臂式硬浮口和VFP比较页面。
我的问题是:
谢谢。
发布于 2011-09-08 11:59:13
是否可以设置iOS系统来提供对低于正常值的支持,而不要求编译器只生成完整的软件浮点代码?
是。这可以通过将FPSCR中的FZ位设置为零来实现:
static inline void DisableFZ( )
{
__asm__ volatile("vmrs r0, fpscr\n"
"bic r0, $(1 << 24)\n"
"vmsr fpscr, r0" : : : "r0");
}请注意,当遇到相当数量的异常值时,这可能会导致应用程序性能显著下降。您可以(而且应该)在调用未使ABI保证在非默认模式下正常工作的代码之前恢复默认浮点状态:
static inline void RestoreFZ( ) {
__asm__ volatile("vmrs r0, fpscr\n"
"orr r0, $(1 << 24)\n"
"vmsr fpscr, r0" : : : "r0");
}请提交一个错误报告,要求为iOS中的FP操作模式提供更好的文档。
https://stackoverflow.com/questions/7346521
复制相似问题