C ++ / Haskell中精确的实数算术和惰性列表性能

时间:2011-06-04 12:49:45

标签: c++ math haskell lazy-evaluation arbitrary-precision

我最近在阅读this paperthis paper后遇到了精确实数算术的主题。

我找到了许多论文,讨论使用有符号数字流实现精确算术的实现。使用无限流来获得任意精度可以在函数式语言(如Haskell)中使用惰性列表实现良好的实际实现。然而,在功能语言中讨论这种实现的论文似乎得出结论,表现很差。

现在,我很欣赏与标准浮点表示相比,精确的非硬件实现通常具有相对较差的性能,但我有兴趣以命令式语言(特别是C ++)提供更高效的实现。操作/函数的集合(算术运算,三角函数,exp,log等)。

我的问题:对于导致性能不佳的签名数字/懒惰流表示,是否存在某些内在缓慢的问题,还是Haskell?是什么让它变慢?是否有可能使用C ++中的延迟流实现带符号的数字流表示,实现(显着)比其Haskell对应物更好的性能,或者这是徒劳的练习?也许重建为迭代?

我知道有两个C ++库,RealLib和iRRAM,可以实现高效的实数计算。然而,这些似乎使用区间运算,将实数表示为缩小的嵌套区间,这似乎不像无限流那样“纯粹”(如果您不同意,请纠正我!)。但也许这些是实现高效率的唯一方法?

感谢任何输入!

2 个答案:

答案 0 :(得分:8)

  

是否存在导致性能不佳的签名数字/惰性流表示的内在缓慢,或者是Haskell?是什么让它变慢?是否有可能使用C ++中的延迟流实现带符号的数字流表示,实现(显着)比其Haskell对应物更好的性能,或者这是徒劳的练习?也许重建为迭代?

延迟流最有效地表示为具有延迟功能组件的数据。这是GHC中使用的相当高效的Haskell实现的表示,无论如何你需要在C ++中使用它。你可以用C ++编写没有特殊的“快速”懒惰版本,这在20年的Haskell编译器研究中还没有尝试过,而且更多的是回到Algol。

有关如何最有效地实施延迟数据结构的研究的更多详细信息,请参阅Good introductory text about GHC implementation?

现在,由于缺乏有关基准的信息,有几个可能的答案:

  • 代码写得不好(更好的实现可能不会很慢)
  • 将大数字表示为标记的延迟位,空间效率低,导致各种硬件瓶颈
  • 数字的惰性流表示仅允许某些线性算法。更密集的表示可以允许算法具有更好的复杂性或绝对性能。

我的猜测是后两点。懒惰的C ++版本只是努力达到GHC已经存在的相同点,所以为什么不使用文章中的代码,看看你是否可以加快它。

答案 1 :(得分:5)

我担心“数字是懒惰的数字流”方法注定效率低于更直接的方法,即使数字位于较大的基数(表示2 ^ 64或更多):

  • 延迟评估意味着最后,您所考虑的数字实际上是代表导致它的计算的DAG。要求再多一个数字可以在该DAG的每个节点中重新触发计算。在一天结束时,你花在家里的时间远远多于计算时间。

  • 您可能无法使用更复杂的算法进行基本计算。例如,用于乘法的FFT方法显然是不可能的。

  • 这并不意味着算法会很简单。想想如何处理当前的99999结果。你需要做好准备,为所有这些人做好准备。现在试着考虑如何进行乘法运算。一个懒惰表达的语言可能有助于表达它,但是你会因第一个问题而变得更难;我很高兴得知编译器能够对其进行优化,但我担心它们不是。