适用于大型,频繁变化的浮子序列的Haskell类型

时间:2014-04-23 01:32:14

标签: haskell

我必须选择一个带有16K元素的浮点序列的类型。这些值会经常更新,可能每秒更新一次。

我已阅读wiki page on arrays。以下是我迄今为止得出的结论。 (如果有任何错误,请纠正我。)

  1. 在这种情况下,IArrays会慢得令人无法接受,因为它们会在每次更改时被复制。阵列中有16K浮点数,每次都会复制64KB内存。

  2. IOArrays可以解决这个问题,因为它们可以在不复制所有数据的情况下进行修改。在我的特定用例中,在IO monad中进行所有更新根本不是问题。但是它们被装箱了,这意味着额外的开销,这可能会增加16K元素。

  3. IOUArrays看起来非常合适。与IOArrays一样,他们在每次更改时都不需要完整的副本。但是与IOArrays不同,它们是未拆箱的,这意味着它们基本上是Haskell等效的C浮点数组。我意识到他们很严格。但我不认为这是一个问题,因为我的应用程序永远不需要访问任何少于整个阵列的东西。

  4. 我是否正确地寻求IOUArrays?

    另外,假设我后来想要从多个线程读取或写入数组。我会用IOUArrays支持自己吗?或者IOUArrays的选择与并发问题完全正交? (我还不熟悉Haskell中的并发原语以及它们如何与IO monad交互。)

2 个答案:

答案 0 :(得分:5)

一个好的经验法则是你应该几乎总是使用the vector library而不是数组。在这种情况下,您可以使用the Data.Vector.Mutable module中的可变向量。

您需要的关键操作是readwrite,它们允许您可变地读取和写入可变向量。

答案 1 :(得分:3)

您当然想要基准测试(使用criterion),或者您可能有兴趣浏览我所做的一些基准测试,例如here(如果该链接适合您;请为我破解)。

vector库是GHC更原始的数组类型的一个很好的接口(疯狂的低估),你可以在primitive package更直接地获得它。与标准array包中的内容一样;例如,IOUArray基本上是MutableByteArray#

未装箱的可变数组通常是最快的,但您应该在应用程序中将它们与IOArray或等效的矢量进行比较。

我的建议是:

  • 如果您可能不需要并发,请首先尝试一个可变的未装箱的Vector,如Gabriel建议的那样

  • 如果您知道自己需要并发更新(并且感觉有点勇敢),那么首先尝试MutableArray,然后使用atomic-primops库中的these functions进行原子更新。如果您想要细粒度锁定,这是您的最佳选择。当然,并发读取对于您选择的任何数组都可以正常工作。

理论上也可以对MutableByteArray(相当于IOUArray)同时更新这些atomic-primops函数,因为Float应始终适合一句话(我想),但是你必须做一些研究(或者说是Ryan)。

在使用atomic-primops内容进行并发时,还要注意潜在的内存重新排序问题,并帮助说服自己进行大量测试;这是一个有点未知的领域。