繁体   English   中英

Haskell中具有高性能的可变随机访问数组/向量

[英]Mutable, random-access array/vector with high performance in haskell

这个关于Haskell的主题讨论了很多(例如可变数组实现 ),但我仍然不确定需要频繁修改和随机访问数组/向量的情况的最佳实践是什么。

说一个长度为1,000,000的向量。 对它的操作涉及根据输入访问其(较小的,例如1000个)子集,并根据输入修改值。 此外,这种操作重复2,000,000次。 任务本身可以在纯数据结构中实现,例如列表,如下所示,尽管效率很低:

type Vect = [Int]

f :: Vect -> [[Int]] -> Vect
f x indsList = foldl g x indsList

-- g is just an example of random-access and modifications on the values.
g :: Vect -> [Int] -> Vect
g x inds = map h $ zip x [0..]
    where h (x, i) = if i `elem` inds then x !! i + 1 else x !! i

散列/映射数据结构(例如IntMap)可以用于有效的大量随机访问,但是数组/向量也应该这样做。 更重要的是,仍需要通过可变结构来解决大量修改以避免存储器复制。 Haskell中是否存在可变的随机访问数组/向量? 如果使用ST / IO Monads,这些控件会影响我的设置吗?

Haskell确实具有有效的可变数组。

  • STUArray ,它具有相当复杂但通常只是不必要的Ix索引方法,具有许多边界检查和很少的特殊优化,这使其比理论上的速度慢一些。

  • 所有Data.Vector开销都很少,大量使用了流融合优化,更喜欢简单的“类似于列表”的界面。 这意味着您实际上可以非常轻松地将示例直接轻松地转换为不可变向量,并且可能仍会获得比预期更好的性能:

     import Data.Vector.Unboxed as VU type Vect = VU.Vector Int f :: Vect -> [[Int]] -> Vect fx indsList = VU.foldl gx indsList g :: Vect -> [Int] -> Vect gx inds = VU.zipWith hx [0..] -- h is just an example of modifications on the values. where hxi | i`elem`inds = x VU.! i + 1 | otherwise = x VU.! i 

是的,您可能想在ST monad中进行可变更新。 不知道您所说的“这样的控件会影响性能”是什么意思:一旦编译器优化了行之有效的类型安全性,命令语言就不会真正没有任何“控件”。 哪个GHC可以做得很好; 使用Data.Vector.Unboxed可以非常接近C的性能。 总会有一些不可避免的开销,但这主要与垃圾回收等问题有关,您在Java中也会遇到这种问题。

由于STIO是monad,因此编译器实际上可以进行一些更高级的优化,这在命令式语言中是不可能的,尽管编译器的作用还不是很远。

在许多地方都讨论了性能,尤其是阵列操作的性能,例如在RWH中

来自Yarr的外来UArrays是可变的,随机访问和最大快速。 它们也是“快速和脏”的,即不对每次突变操作施加冷冻/解冻样板。

缺点:几乎所有“低级”操作都在IO之下。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM