Performance isoprolog中非规范浮点的正确处理

Performance isoprolog中非规范浮点的正确处理,performance,floating-point,prolog,iso-prolog,denormal-numbers,Performance,Floating Point,Prolog,Iso Prolog,Denormal Numbers,非规范浮点是一种特殊的类型: ISO Prolog标准如何处理这些问题 我很清楚,每当这些非规范化发生时,提出一个评估\u错误(下溢)异常是处理它们的正确方法,但这会产生额外的成本,必须检查产生的每个浮动 但是许多处理器提供的“将非规范化刷新为零”(FTZ)和“将非规范化视为零”(DAZ)操作模式又如何呢?Prolog实现可以使用这些吗?如果可以,它们是如何正确使用的 (1)记录这些操作模式的使用,(2)确保非规范化被刷新到同一符号的零(FTZ)和(3)确保非规范化被视为同一符号的零(DAZ)

非规范浮点是一种特殊的类型:

ISO Prolog标准如何处理这些问题

我很清楚,每当这些非规范化发生时,提出一个
评估\u错误(下溢)
异常是处理它们的正确方法,但这会产生额外的成本,必须检查产生的每个浮动

但是许多处理器提供的“将非规范化刷新为零”(FTZ)和“将非规范化视为零”(DAZ)操作模式又如何呢?Prolog实现可以使用这些吗?如果可以,它们是如何正确使用的


(1)记录这些操作模式的使用,(2)确保非规范化被刷新到同一符号的零(FTZ)和(3)确保非规范化被视为同一符号的零(DAZ)就足够了吗?救命啊

不要跳过它们。然而,ISO/IEC 13211-1:1995 9.1.4.2浮点结果函数的简短回答:

当0<| x |是选择圆形(x)还是下溢,应由实现定义

但首先,让我们称之为次正常。过时的(至少根据)非规范化概念(回顾过去)并没有多大帮助,因为它暗示了一些积极的、解构的特性。不,它们并不像你说的那么特别。要看到这个,考虑实数的数字行。可以精确表示的数字被标记,当接近零时(从两侧)彼此越来越接近。低于正常值是指最接近于零的值。它们与零之间的距离与最小正常数之间的距离相同。这就是他们的异常(或者说非规范化)。如果你现在移除这些次正常值,你会得到一个巨大的缺口,它会导致更多的数值异常。这就像你在尺子上划掉零旁边的标记,然后用这把断了的尺子测量1。因此,在没有低于正常值的情况下,剩余的数字可能不像人们所认为的那样正常,而是异常的,容易出现更多的错误

如果你不喜欢读卡汉关于我建议的主题的书,我可以让你参考古斯塔夫森的《错误的终结》,它比我更好地解释了次正常现象

在13211-1中,可以排除次正常值,但这只是为了与非常危险、过时的体系结构兼容

正式的一致性就到此为止。从长远来看,一些联合国大学风格的、CLP(BNR)式的、Prolog IV ish方法可能是有希望的



1)也就是说,如果四舍五入为零。如果生成异常/连续值,只要不发生此类异常,更好的数值属性将保持不变。

在第7.1.3节中,ISO Prolog标准将集合F定义为所选浮点格式可以表示的数字集合。此集合可能包括也可能不包括非规范化值,这两种选择都是允许的

当计算结果(绝对)大于零且小于最小规范化值时,您可以选择

  • 四舍五入到用F表示的值
  • 引发下溢异常

根据第9.1.4.2节,此选项是由实现定义的,即您必须对其进行记录。

这是一个小测试用例,以查看您的Prolog系统是否可以返回低于正常值的算术结果(无刷新到零,~FTZ):

这是API中的一个新添加,在Prolog系统中不一样,显示了次规范的参数传递(没有非规范为零,~DAZ):


结果来自MacBook Air 2019。

我想说,试图从一个20多年前的标准中引出关于浮点的智慧,对于这个标准来说,浮点不是核心问题,甚至遵守它都是徒劳的,但我脾气暴躁,这就是我自己。甚至Java标准也没有得到以下方面的认可:。IEEE标准754建议使用超精确的longdouble,95%以上的台式机在其硬件中内置了longdouble。您为此付费,但Java否认了它的好处。特别是上面的PDF:“无效操作、溢出、零除、下溢、不精确结果”。。。除非处理不当,否则这些事件不是错误。它们被称为“例外”,因为根据计算机系统预先强加给所有程序员的任何处理它们的策略,一些程序员有充分的理由采取例外。@David Tonhofer。对我来说,一致性很重要,因为我也是一个实现者。旁白:根据IEEE,+/-0.0不是一个次正常值(非正常值),因此我不希望FTZ、DAZ引起下溢。@chux。我不是有意暗示的。自贸区和DAZ是提高底流的替代方案。我只是不确定保留这个标志是否重要。
/* SWI-Prolog */
?- X is 2.2250738585072011e-308 - 2.2250738585072012e-308.
X = -5.0e-324.
/* Jekejeke Prolog */
?- X is 2.2250738585072011e-308 - 2.2250738585072012e-308.
X = -4.9E-324
/* SWI-Prolog */
?- X is 2.2250738585072011e-308 - 2.2250738585072012e-308, 
float_parts(X,M,B,E).
X = -5.0e-324,
M = -0.5,
B = 2,
E = -1073.
/* Jekejeke Prolog */
?- X is 2.2250738585072011e-308 - 2.2250738585072012e-308, 
sys_float_mantissa(X,M), sys_float_exponent(X,E), sys_float_radix(X,R).
X = -4.9E-324,
M = -1,
E = -1074,
R = 2