我的目标是在可能具有不同 CPU 架构和操作系统的不同机器上运行需要非整数的模拟。主要优先级是给定相同的初始状态,每台机器都应该完全相同地再现模拟。次要优先级是我希望计算的性能和精度尽可能接近 double 浮点数。
据我所知,似乎没有任何方法可以影响 float 的确定性
Haskell 程序中的点计算,类似于 _controlfp
和 _FPU_SETCW
C中的宏。所以,目前我认为我的选择是
_ controlfp
(或每个平台的等效项)通过 FFI。 定点算术库的一个问题是它们没有例如为它们定义的三角函数或对数(因为它们没有实现
Floating
类型类)所以我想我需要为模拟种子数据中的所有函数提供查找表。或者有什么更好的方法吗?两个定点库也隐藏了
newtype
构造函数,因此任何(反)序列化都需要通过 toRational
完成/fromRational
据我所知,这感觉会增加不必要的开销。我的下一步是对不同的定点解决方案进行基准测试,以了解真实世界的性能,但与此同时,我很乐意听取您对此主题的任何建议。
最佳答案
IEEE 754-2008 标准的第 11 条描述了可重现的浮点结果所需的内容。除其他外,您需要明确的表达式评估规则。某些语言允许以额外的精度计算浮点表达式或允许对表达式进行某些更改(例如在单个指令中计算 a*b+c
,而不是单独的乘法和加法指令)。我不知道 Haskell 的语义。如果 Haskell 没有将表达式精确地映射到明确的浮点运算,那么它就不能支持可重现的浮点结果。
此外,由于您提到三角函数和对数函数,请注意这些函数因实现而异。我不知道有任何数学库提供每个标准数学函数的正确舍入实现。 (CRLibm 是一个创建项目。)所以每个数学库都使用自己的近似值,它们的结果略有不同。也许你可以通过在你的模拟代码中包含一个数学库来解决这个问题,以便使用它来代替每个 Haskell 实现的默认库。
在二进制浮点数和十进制数字之间转换的例程也是实现之间差异的一个来源。这不像过去那样成为问题,因为正确转换的算法是已知的。但是,这可能需要在每个实现中进行检查。
关于performance - 在 Haskell 中运行跨平台、确定性模拟的最有效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16538065/