我试图理解GNURadio中的浮点运算,并开始研究他们的测试。测试生成随机浮点输入和随机抽头,然后将所有内容传递给过滤器。后来它用一定的余量比较了预期的产出和实际产出。
关于margin:
有一个神秘的评论 // we use a sloppy error margin because on the x86 architecture,
// our reference implementation is using 80 bit floating point
// arithmetic, while the SSE version is using 32 bit float point
// arithmetic.
我在源代码中找不到80位算术。谁能帮我?或者只是解释为什么误差范围取决于抽头大小?
答案 0 :(得分:1)
在x86 + 87上,即使只使用double
,您也可以获得80位精度的中间结果,因为FPU堆栈在内部使用80位浮点数。
如果您的代码需要并依赖于64位或32位浮点数学的舍入,您可能会感到意外。
例如我被x < y
之类的东西击中了很多次但是在分配z = x
之后你可能会得到z >= y
(所有vars声明为double
) 。如果x
最终在80位FPU寄存器中分配,而z
在内存中是一个真正的64位浮点变量,则可能会发生这种情况。
g ++有一个特定的选项可以避免这些问题(-ffloat-store
)阻止使用额外的位(但是会减慢数学代码的速度)。
答案 1 :(得分:0)
注意:根据以下Marcus Müller的评论,GNURadio在一段时间内没有使用80位浮点数,因此问题中引用的评论充其量只是陈旧。所以这个答案只能说明80位和32位浮点运算之间的差异,并不适用于当前的GNURadio实现。
您尚未显示源代码,因此答案是推测性的。据推测,参考实现使用long double
,并且作者使用的C ++实现中的long double
是使用内置于Intel硬件中的80位浮点类型实现的。在看到任何显式扩展精度算术的意义上,它看起来不像80位代码;它看起来就像是带有long double
类型的C ++代码。
同时,主要实现是使用SSE代码实现的。 SSE是Intel指令子集的名称,包括SIMD(单指令多数据)指令,一次可处理四个32位浮点数。该代码在外观上会很明显;它将使用SSE指令进行汇编,在C ++中使用编译器内置函数引用SSE指令,或者可能在C ++中使用编译器扩展来支持向量类型。
当然,使用32位浮点运算时出现的浮点舍入误差与使用80位浮点运算时出现的浮点舍入误差不同,因此不会期望计算结果两种不同的方法是平等的。作者设计了测试以容忍结果中的一些差异。
应该注意的是,尽管代码当然是针对英特尔架构的,但并非所有C ++实现都使用80位浮点算法实现long double
。 C ++实现可能使用64位算术。因此,如果使用与作者不同的C ++实现来运行代码,则可能会得到不同的结果。虽然64位算法通常具有比80位算术更大的舍入误差,但是作者对32位和80位算术之间的差异设置的任何容差也可能涵盖32位和64位算术之间的差异。 ,所以不需要调整。