提问人:noureddine-as 提问时间:1/7/2020 最后编辑:S.S. Annenoureddine-as 更新时间:1/27/2020 访问量:240
如何比较两个数学库实现?
How to compare two Math library implementations?
问:
如您所知,C 标准库定义了几个标准函数调用,这些调用应该由任何兼容的实现实现,例如 Newlib、MUSL、GLIBC ...
例如,如果我的目标是Linux,我必须在glibc和MUSL之间进行选择,而我的标准是 数学库的准确性 。例如,如何比较两种可能的实现?libm
sin()
cos()
一种幼稚的方法是使用参考输入(例如来自 Matlab)在一组随机生成的输入上测试两种实现结果的输出质量,但有没有其他更可靠/正式/结构化/指导的方法来比较/建模两者?我试图看看是否有这方面的任何研究,但我找到了,所以任何指示都是值得赞赏的。
答:
1赞
Eric Postpischil
1/10/2020
#1
一些想法:
- 您可以使用 GNU 多精度算术库 (GnuMP) 生成良好的参考结果。
- 可以详尽地测试大多数(如果不是全部)单参数单精度 (IEEE-754 binary32) 例程。(对于某些 macOS 三角例程,例如 ,我们详尽地测试了一个实现,验证它是否返回了忠实的舍入结果,这意味着结果是数学值 [如果可表示] 或两个相邻值之一 [如果不是]。然后,在更改实现时,我们将一个与另一个进行比较。如果新实现结果与旧实现结果相同,则通过。否则,将使用 GnuMP 对其进行测试。由于新实现与旧实现基本一致,这导致很少调用 GnuMP,因此如果我没记错的话,我们能够在大约三分钟内详尽地测试一个新的例程实现。
sinf
- 详尽地测试多参数或双精度例程是不可行的。
- 在比较实现时,您必须选择一个或多个指标。具有良好最坏情况错误的库适用于证明;它的边界可以被断言为对任何参数都成立,并且可用于在后续计算中推导出进一步的边界。但是,对于使用大型数据数组的物理模拟,具有良好平均误差的库可能倾向于产生更好的结果。对于某些应用,只有“正常”域中的误差可能是相关的(角度约为 −2π 至 +2π),因此减少大型参数(最多约 10308)的误差可能无关紧要,因为这些参数从未使用过。
- 有一些共同点应该测试各种例程。例如,对于三角函数例程,在π的不同分数下进行测试。除了在数学上很有趣之外,这些往往是实现在内部近似值之间切换的地方。还要测试可表示但恰好非常接近简单分数π倍数的大数。这些是参数减少的最坏情况,如果操作不当,可能会产生巨大的相对误差。他们需要数论才能找到。以任何一种散射方法进行测试,甚至是没有考虑这个约简问题的有序方法,都无法找到这些麻烦的论点,因此很容易将存在巨大错误的例程报告为准确。
- 另一方面,有一些重要的测试点,如果没有对实现的内部了解,就无法知道。例如,在设计正弦例程时,我会使用 Remez 算法来找到一个最小最大多项式,目标是从 –π/2 到 +π/2 (对于这种事情来说相当大,但只是举例)。然后,我会查看在参数缩减过程中可能发生的算术和舍入错误。有时,它们会在该间隔之外产生一个结果。因此,我会回到最小最大多项式生成,并推动稍大的区间。我也会寻求减少参数的改进。最后,我最终会得到一个保证在特定区间内产生结果的约简,以及一个已知在该区间内达到一定精度的多项式。为了测试我的例程,你需要知道该区间的端点,并且你必须能够找到一些参数,这些参数的参数缩减会在这些端点附近产生点,这意味着你必须对我的参数缩减是如何实现的有所了解——它使用了多少位,等等。就像上面提到的麻烦的论点一样,这些观点无法用散射的方法找到。但与上述不同的是,它们不能从纯数学中找到;您需要有关实现的信息。这使得你几乎不可能知道你已经比较了实现的最坏的潜在参数。
评论
0赞
noureddine-as
1/27/2020
非常感谢埃里克的详细回答!
评论
dlopen()
dlsym()