在Haskell中运行跨平台,确定性模拟的最有效方法是什么?

sha*_*ang 6 floating-point performance haskell floating-accuracy

我的目标是运行一个模拟,该模拟需要跨不同机器的非整数,这些机器可能具有不同的CPU架构和操作系统.主要优先考虑的是,在相同的初始状态下,每台机器应该重现完全相同的模拟.次要的优先事项是,我希望计算的性能和精度尽可能接近双精度浮点数.

据我所知,似乎没有任何方法可以影响Haskell程序中浮点计算的确定性,类似于C中的_controlfp_FPU_SETCW宏.所以,目前我认为我的选择是

  1. 使用Data.Ratio
  2. 使用Data.Fixed
  3. 使用Data.Fixed.Binary定点
  4. _ controlfp通过FFI 编写要调用的模块(或每个平台的等效项).
  5. 可能还有其他什么?

定点算术库的一个问题是它们没有例如为它们定义的三角函数或对数(因为它们没有实现Floating类型类)所以我想我需要为所有函数提供查找表.模拟种子数据.还是有更好的方法吗?

两个固定点库也隐藏了newtype构造函数,因此任何(解)序列化都需要通过toRational/ fromRational据我所知,并且感觉它会增加不必要的开销.

我的下一步是对不同的定点解决方案进行基准测试,以了解现实世界的表现,但同时,我很乐意接受您对此主题的任何建议.

Eri*_*hil 7

IEEE 754-2008标准的第11条描述了可重现的浮点结果所需的内容.除此之外,您还需要明确的表达式评估规则.某些语言允许以额外的精度评估浮点表达式或允许对表达式进行一些更改(例如a*b+c在单个指令中进行求值而不是单独的乘法和添加指令).我不知道Haskell的语义.如果Haskell没有精确地将表达式映射到确定的浮点运算,那么它就不能支持可重现的浮点结果.

此外,由于您提到三角函数和对数函数,请注意这些函数因实现而异.我不知道任何数学库提供每个标准数学函数的正确舍入实现.(CRLibm是一个创建项目的项目.)因此每个数学库都使用自己的近似值,结果略有不同.也许您可以通过在模拟代码中包含一个数学库来解决这个问题,以便使用它来代替每个Haskell实现的默认库.

在二进制浮点数和十进制数字之间进行转换的例程也是实现之间差异的来源.这不像过去那样是一个问题,因为正确转换的算法是已知的.但是,在每个实现中可能需要检查它.