3

我想知道 repa 中是否有 (//) 的类似物?

无法并行化的数组转换需要它。例如,如果函数需要整个数组来更改数组的单个条目,然后将其应用于新数组等等(并且它应该按顺序运行)。

4

2 回答 2

5

(//)可以用 Data.Array.Repa.fromFunction 来实现:

import Data.Array.Repa

(//) :: Shape sh => Array sh a -> [(sh,a)] -> Array sh a
(//) arr us = fromFunction (extent arr) (\sh -> case lookup sh us of
                                                 Just a  -> a
                                                 Nothing -> index arr sh)

fromFunction可以传递一个类型的函数,该函数Shape sh => s -> a本身可以利用整个数组。

上述实现一次执行所有更新。

于 2011-06-12T09:48:06.907 回答
4

(//) 的一个潜在问题是它需要在列表中搜索才能找到每个元素的值。如果数组或列表很大,这可能会很昂贵。

另一种选择是利用 Data.Vector 中的一个方便的函数:

modify :: Vector v a => (forall s. Mutable v s a -> ST s ()) -> v a -> v a

如果安全的话,这有可能在适当的位置进行更新。所以像

import Data.Vector.Unboxed as V
import Data.Vector.Mutable.Unboxed as M
import Data.Array.Repa as R

(///) :: Shape sh => Array sh a -> [(sh,a)] -> Array sh a
(///) arr us = R.fromVector sh . modify f $ R.toVector arr
  where
  sh = extent arr
  f mv = forM_ us $ \(k,x) -> do
    M.write mv (R.toIndex sh k) x

在我的笔记本电脑上,我测试了一个包含 100 万个元素的 DIM1 数组,更新了 100 个条目,得到了这些时间:(//): 3.598973 (///): 2.0859999999999997e-3

于 2012-02-03T04:55:15.537 回答