在将应用程序从Linux x86移植到iOS ARM(iPhone 4)时,我发现了 浮点算术和小值的行为差异。
64bits floating point numbers (double)小于[+/-] 2.2250738585072014E-308在denormal/denormalized/subnormal / IEEE 754-1985标准中称为IEEE 754-2008个数字。
在iPhone 4上,这样的小数字被视为零(0),而在x86上,可以使用次正规数字进行计算。
我无法在Apple的文档Mac OS X Manual Page For float(3)上找到有关符合IEEE-754标准的任何解释。
但是由于Stack Overflow上的一些答案(flush-to-zero behavior in floating-point arithmetic,Double vs float on the iPhone),我找到了一些线索。
根据一些搜索,似乎沿着ARM内核使用的VFP(或NEON)数学协处理器正在使用Flush-To-Zero(FTZ)模式(例如,将正常值转换为0在输出处)和非正常零(DAZ)模式(例如,当用作输入参数时,将正常值转换为0)以提供快速硬件处理的IEEE 754计算。
- 符合ARM支持代码的完全IEEE754
- 符合IEEE754标准的快速运行模式(仅限硬件)
关于FTZ和DAZ的一个很好的解释可以在 x87 and SSE Floating Point Assists in IA-32: Flush-To-Zero (FTZ) and Denormals-Are-Zero (DAZ):
FTZ和DAZ模式都处理无效浮点数据发生时的情况 用下溢或非正常条件处理。 [...]。一个数字的区别 由FTZ和DAZ处理的非常微妙。 FTZ处理下溢情况 DAZ处理非正规数。当计算结果为a时,发生下溢情况 非标准。在这种情况下,FTZ模式将输出设置为零。 DAZ修复案例的时候 非正规用作输入,作为常量或通过读入无效的内存 寄存器。 DAZ模式在计算之前将计算的输入设置为零。 FTZ 然后可以说当DAZ处理[输入]时处理[输出]。
Apple开发者网站上关于FTZ的唯一内容似乎是iOS ABI Function Call Guide :
VFP状态寄存器| FPSCR | 特别| 函数调用不保留条件代码位(28-31)和饱和位(0-4)。异常控制(8-12),舍入模式(22-23)和 flush-to-zero(24)位只应由影响应用程序状态的特定例程修改(包括框架API函数) )。在函数进入和退出时,短向量长度(16-18)和步长(20-21)位必须为零。不得修改所有其他位。
根据ARM1176JZF-S Technical Reference Manual, 18.5 Modes of operation(第一个iPhone处理器),VFP可以配置为完全支持IEEE 754(子正常算术),但在这种情况下,它需要一些软件支持(陷入内核以在软件中计算) )。
注意:我还阅读了Debian的ARM Hard Float Port和VFP comparison页面。
我的问题是:
哪里可以找到关于跨iOS设备处理次正规数的明确答案?
是否可以设置iOS系统以支持次正规数而不要求编译器只生成完整的软件浮点代码?
感谢。
答案 0 :(得分:9)
是否可以设置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");
}
请提交bug report请求为iOS中的FP操作模式提供更好的文档。
答案 1 :(得分:0)
•Where can one find definitive answers regarding subnormal numbers
跨iOS设备处理?
你已经找到了答案。可以预料,ARM没有相同的浮点能力。
•可以设置iOS系统以支持次正规数 而不要求编译器只生成完整的软件浮动 点代码?
我不相信,至少我希望如此,使用相同的值来获得不同的数字。