计算机无法精确地表示任意实数,这是由于以下两个难以理解的实数事实:
由于计算机使用有限数量的位,因此计算机架构师必须致力于以有限的精度捕获有限数量的实数,这是通过固定位模式与实数之间的映射(称为表示)来实现的。在可表示数字的数量和精度水平之间。
浮点表示法是使用最广泛的表示形式,数字形式为$$(-1 ^ s)* 1.m * 2 ^ e $$
数量和精度之间的设计折衷通过尾数和指数专用的位数来捕获。
但是,实际上,IEEE 754浮点标准对此方案进行了少许修改,以解决两个可感知的限制:
Small Number Gap:最大负数和最小正数之间存在较大的差距。为了解决这个问题,指数最小的数字将被归一化。归一化的值线性分布,而不是呈指数分布。对于浮点数,归一化发生在最大负数和最小正数之间,升至第二大指数。
虚假结果:溢出结果(例如,除以很小的数字)或应用于其域外元素的部分函数的结果(例如,除以零)没有结果。溢出的情况由正无穷大和负无穷大捕获,每个无穷大由对应于全1指数和全零尾数的位模式表示,并通过符号位进行微分。
部分结果不成立的情况由NaN值(即“非数字”)捕获,该值由具有全指数和非零尾数的各种位模式表示。
posit表示应该是使用最广泛的表示。posits表示的数字类似于浮点,但由于引入了所谓的制度术语而有所不同,如下所示:
规范位可能看起来像是一种怪异的人工构造,但实际上它们来自二进制整数到圆上的投影实数的自然而优雅的几何映射。
在圆圆的北部,象征着我们的父神阿尔法和欧米茄,我们庄严地祈祷着它,光荣的正负无限;在圆圆的对面,邪恶,不道德的南面不存在任何有价值的东西$ 0 $。与此同时,在尘世间,上帝的孩子们享有自由意志,他们在东方的积极人与西方的消极人之间做出选择。
然后,由这些点引起的象限由其余的点对称地填充。 $ useed $确定这些象限的“中心”位于以下位置:
就像亚当和夏娃一样,$ useed $决定了圆中象限的填充方式。正值位于圆的右侧,负值位于圆的左侧,倒数在整个赤道上反映。
悲惨的是,我们生活在一个堕落的世界中,充满了非信徒和对托马斯的怀疑。
尽管有两个零的浮点表示形式(正数和负数),但是只有一个这样的正数表示形式:全零位模式。
正负无穷表示为浮点数,而正则将这些值组合成一个表示形式:全零的位模式保存在第一位。
浮点数会被NaN值污染,而正数会被清除掉这些不干净的特殊值。
在其他时候,需要一种更定量的方法;为此,古斯塔夫森提出了多种基于度量的数字表示比较。首先,他问道:我们如何评估给定表示形式中数字的精确度?回答这个问题,他提出了十进制精度度量:对数刻度上实数的有效位数,如分贝系统中那样。
实数系统中介于10和10之间的十个数字的“完美间隔”不是计数数字1到10的均匀间隔,而是指数间隔的$ 1,10 ^ {\ frac {1} {10}},10 ^ {\ frac {2} {10}},...,10 ^ {\ frac {9} {10}},10 $。
因此,(正,非零)实数$ n $的“规范位置”由$ p $给出,其中$ n = 10 ^ {\ frac {p} {10}} $,因此遵循实数$ n $与其表示$ n'$之间的距离或表示误差由$ |给出\ log_ {10}(\ frac {n} {n'})| $。直接调整也使该方案也适用于负数,由于正数表示正负号,因此我们忽略了零。此误差的倒数产生准确度的完美度量标准。配备此度量标准后,我们收集了有效位数以十进制为底的对数表示十进制精度。
我们从该图中得出两个观察结果:首先,posits在表示形式之间对称地分配小数精度,而浮点数不能在较大的数字处传递,而对于NaN则被忽略了;此外,posites赞成数字线处的小数精度最后,位置代表更多的数字:位置代表更大范围的显示。换句话说,位置的动态范围(另一个度量标准)超过了浮点数的范围。
除了原始表示错误外,还有可能因原始运算而产生错误。Gustafson通过“闭合图”解决了基本算术运算的问题。这种图直观地描述了输入的每种组合的准确性。例如,乘法闭合下图以十进制精度表示,将输入域更暗,可获得更准确的结果:
通过绘制排序误差比较表示形式之间单参数运算的精度,例如,古斯塔夫森(Gustafson)在以下图中比较平方根的精度:
作为信使工作的一部分,我们通过比较各种基准下的32位浮点数和posit表示的精度来比较其准确性。在每个基准中,我们都以64位双精度以上的运算表示实数计算。换句话说,双精度类型用作计算精度的“ oracle”基准。然后,将每个双精度基准编译为LLVM IR,然后分别应用正向LLVM遍历和浮点LLVM遍历以生成关联的基准。
最后,我们通过将浮动基准和基准基准结果与双基准基准进行比较来计算误差百分比,我们认为基准误差是由特定32位表示形式所特有的不准确性所引起的,再加上连续的运算。我们向古斯塔夫森深表歉意,我们以线性标尺(而不是对数标尺)计算这些误差,并将它们用作度量标准以比较两种表示法的准确性。
我们的目标是通过float和posit传递将尽可能多的特定于表示的功能插入我们的基准测试.float的情况允许完整转换,因为每个双精度操作都可以转换为float操作。 ,但是:我们没有为所有现有的LLVM double操作提供实现。
为了在一次通过实现中适应两种情况,我们设计了一次通过,以使其首先降低每个受支持的double运算并将操作数降低到目标表示,然后将结果提升为double。
由于每次重写都具有纯粹的局部效果,因此我们可以避免对复杂的分配和类型转换场景进行推理,尽管计算效率低下,但这种方法可立即支持所有程序并且易于扩展。
在pseduo-LLVM中,类型为typ的传递的一般结构转换任意双精度运算op,其操作数如下所示:
x:double = ..y:double = ..result:double = op double x y
x:double = ..y:double = ..x_typ:typ =将double x转换为typ; y_typ:typ =将double y转换为typ; result_typ:typ = typ_op x_typ y_typ;结果double =将result_typ类型转换为double
类型参数设置为float的LLVM浮点运算(例如fadd float x y)
posit传递从Cerlane Leong的SoftPosit存储库中实现的外部C函数提取这些组件,尤其是,我们借用32位posits的基本算术运算(+,-,*和/)。
对于每个输入,我们都将浮动基准和基准基准结果的误差百分比计算为正确的“随机”值,并将相应的双重基准结果作为基准。我们大约使用启发式$ 20 ^ {vars} $为每个基准选择计算上可行的样本大小,其中$ vars $表示基准的输入变量数量,反映出在较大的输入空间上需要更多样本。这个有效的输入范围是为每个基准测试指定的。这种简单的策略可以确保测试用例也包括可以精确表示的整数的情况,其中所有误差均源于运算误差。我们报告了所有误差百分比的平均值和标准偏差检查的输入:
根据古斯塔夫森(Gustafson)的预言,假定位置始终优于浮点数个数量级,但是我们的LLVM确定位置效率极低:它引入了负载并存储了操作,以便为每个重复操作在double和posit之间进行转换。无知的,非确定性的体系结构,这首先需要通过这样的测试。
位置处理单元比IEEE浮动FPU占用更少的电路。利用更低的功耗和更小的硅片占位面积,芯片所支持的每秒posit操作数(POPS)可能明显高于使用类似硬件资源的FLOPS。尤其是GPU加速器和深度学习处理器,每瓦特和每美元可以带来更多收益,同时提供卓越的答案质量
的确,我们可以用POPS代替FLOPS进行交谈。
我们的方法依赖于将double类型视为基准的“基本事实”表示。尽管这是一个近似值,但由于没有有限的表示形式具有完美的准确性,因此我们假设与不太精确的32位表示形式进行比较时,双基准中的累积误差将被截断或四舍五入。浮点数或32位正数的两倍可以在不损失信息的情况下完成。尽管这种假设并不总是成立,但我们发现它足以进行实际测试,并证明了LLVM传递的精简设计是合理的。
[posits]提供了优于float的引人注目的优势,包括更大的动态范围,更高的精度,更好的闭包,系统中按位相同的结果,更简单的硬件以及更简单的异常处理。
承认您使用浮点,pent悔并加以清洗。请与作者联系以归纳为“教派”。
这是CS 6120的课程博客,这是康奈尔大学计算机科学系的博士学位级编译器课程。您可以使用RSS订阅博客上的帖子。