【发布时间】:2016-09-11 23:38:12
【问题描述】:
据我所知,!(称为 bangs)用于表示应严格评估表达式。但对我来说,将它们放在哪里或根本就不是那么明显。
import qualified Data.Vector.Unboxed as V
main :: IO ()
main = print $ mean (V.enumFromTo 1 (10^9))
mean :: V.Vector Double -> Double
mean 的不同版本:
-- compiled with O2 ~ 1.14s
mean xs = acc / fromIntegral len
where !(len, acc) = V.foldl' f (0,0) xs :: (Int, Double)
f (len, acc) x = (len+1, acc+x)
-- compiled with O2 ~ 1.18s
mean xs = acc / fromIntegral len
where (!len, !acc) = V.foldl' f (0,0) xs :: (Int, Double)
f (len, acc) x = (len+1, acc+x)
-- compiled with O2 ~ 1.75s
mean xs = acc / fromIntegral len
where (len, acc) = V.foldl' f (0,0) xs :: (Int, Double)
f !(len, acc) x = (len+1, acc+x)
-- compiled with O2 ~ 1.75s
mean xs = acc / fromIntegral len
where (len, acc) = V.foldl' f (0,0) xs :: (Int, Double)
f (len, acc) x = (len+1, acc+x)
-- compiled without options ~ 6s
mean xs = acc / fromIntegral len
where (len, acc) = V.foldl' f (0,0) xs :: (Int, Double)
f (len, acc) x = (len+1, acc+x)
-- compiled without options ~ 12s
mean xs = acc / fromIntegral len
where !(len, acc) = V.foldl' f (0,0) xs :: (Int, Double)
f (len, acc) x = (len+1, acc+x)
其中一些在直觉上是有意义的,但我希望它不是一种反复试验的方法。
是否有某种方法可以检测延迟评估何时会影响性能?除了严格测试之外。
它是否只对像
mean这样的简单函数有意义,因为它应该一次性评估所有内容?
【问题讨论】:
-
如果你使用
-O2并且根本没有爆炸模式怎么办? -
@dfeuer 刚刚添加了它。就像 1.75 秒的那个位置不好的爆炸
-
你是如何调用这个函数的,用什么参数?我发现结果有点令人惊讶。我猜 GHC 的严格性分析在这里不是很好用!
-
@dfeuer 我用
stack build --ghc-options -O2 && time stack exec <project>在shell中构建并运行它 -
我最惊讶的是第一个,敲打最终结果对,会做任何有用的事情;最终的结果显然是严格的!
标签: performance haskell optimization lazy-evaluation