加速Data.Array行提取和过滤

时间:2011-11-21 21:39:34

标签: arrays haskell

我的应用程序中有一个非常简单的功能,可以完成大量工作并占用最多的计算时间:

f :: Int -> Array (Int,Int) Int -> [Int]
f x arr = [v | v <- range (l,u), vv <- [g!(x,v)], vv /= 0]
          where ((_,l), (_,u)) = bounds arr

这样做是:从数组x中提取索引arr的行,并返回包含元素\= 0的所有列索引。因此,例如,给定以下具有边界((0,0),(2,2))的矩阵:

arr =  [[0, 0, 5], 
        [4, 0, 3],
        [0, 3, 1]]   -- for simplicity in [[a]] notation

预期输出

f 0 arr == [2] 
f 1 arr == [0,2]
f 2 arr == [1,2]

如何加快f并更详细地了解f(列表构造,数组访问等)中实际占用大部分计算时间的详细信息?

谢谢!

2 个答案:

答案 0 :(得分:2)

f x arr = [v | v <- range (l,u), vv <- [g!(x,v)], vv /= 0]

我认为g是拼写错误,应该是arr 编译器可能能够优化前者和后者,而不是range (l,u)使用[l .. u],但[l .. u]更具惯用性(并且编译器可能无法优化前者为好)。
不要创建无意义的单元素列表,可以使用直接测试,

f x arr = [v | v <- [l .. u], arr!(x,v) /= 0]

编译器可能再次能够将前者重写为后者,但是a)后者更清晰,并且b)不会冒编译器不能的风险。

要了解花费的时间,您可以插入成本中心注释

f x arr = [v | v <- {-# SCC "Range" #-} [l .. u], {-# SCC "ZeroTest" #-} (arr!(x,v) /= 0)]

但是这样的注释会禁用许多优化(编译总是会进行性能分析),因此从性能分析中获得的图片可能会有所偏差,并且与优化程序中的实际情况不同。

答案 1 :(得分:2)

以下是有关分析的文档:

http://www.haskell.org/ghc/docs/latest/html/users_guide/profiling.html

还有一章书:

http://book.realworldhaskell.org/read/profiling-and-optimization.html

如果您的代码由于数组更新而变慢,请使用vector包中的Data.Vector.*