微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

对于密集访问,先冻结数组是好是坏?

如何解决对于密集访问,先冻结数组是好是坏?

假设我有一个 Data.Array.IO.IOArray i e(来自 array 包),我想从中读取元素,根据一些索引顺序在 IO 中一个一个地处理每个元素:

arr :: IOArray I E
ordering :: [I]
processElement :: I -> E -> IO ()

(如我们所见,一切都是单态的)。

有两种明显的方法可以做到这一点:

  1. freeze首先将数组转化为不可变数组,然后使用 ! 运算符:

    do
        arr' <- freeze arr
        forM_ ordering $ \i -> processElement i (arr' ! i)
    
  2. readArray 对原始可变数组中的每个元素进行处理:

    forM_ ordering $ \i -> do
        e <- readArray arr i
        processElement i e
    

ordering 中的索引是“密集”的,因为 arr 的大多数索引都出现在 ordering 中。

哪个更有效?此外,答案是否取决于以下因素:

  • 索引 ordering 是否有重复索引?
  • 索引 ordering 是否单调递增?
  • 索引 ordering 是完全随机还是有很大的连续延伸?

解决方法

没关系。从可变数组读取与从不可变数组读取相同,除非实现中存在明显问题,例如其中一个版本会内联/解包,而另一个版本则不会。

如果您希望写入数组,则无需为了索引而冻结。如果您不希望写入数组,冻结可能是有益的,因为它会将数组从 mutable list 中移除,从而降低 GC 开销。然而,由于竞技场的大小和可变数组的数量很少, 即使这也没有那么重要。

对于读取访问模式,适用一般的局部性考虑。越密集越好,此外,如果可能,我们应该避免以 2 的更大幂的步长进行迭代,以减少缓存冲突。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。