【问题标题】:Haskell computation performanceHaskell 计算性能
【发布时间】:2021-03-28 13:54:12
【问题描述】:

我有几个相同功能的不同实现。不同之处在于爆炸模式的使用。问题是,为什么 perimeterNaiveFast 和 perimeterStrictFast 一样?

基准测试结果:

功能实现:

> data Point = Point { x :: Int, y :: Int }
> 
> distance :: Point -> Point -> Double  
> distance (Point x1 y1) (Point x2 y2) =    
>   sqrt $ fromIntegral $ (x1 - x2) ^ (2 :: Int) + (y1 - y2) ^ (2 :: Int)
> 
> perimeterNaive :: [Point] -> Double 
> perimeterNaive [] = 0.0
> perimeterNaive points = foldPoints points 0.0   
>   where
>     firstPoint = head points
>     foldPoints []              _   =  0.0
>     foldPoints [lst]           acc = acc + distance firstPoint lst
>     foldPoints (prev:next:rst) acc = foldPoints (next:rst) (acc + distance prev next)
> 
> perimeterStrict :: [Point] -> Double perimeterStrict [] = 0.0
> perimeterStrict points = foldPoints points 0.0   
>   where
>     firstPoint = head points
>     foldPoints []              _    =  0.0
>     foldPoints [lst]           acc  = acc + distance firstPoint lst
>     foldPoints (prev:next:rst) !acc = foldPoints (next:rst) (acc + distance prev next)
> 
> perimeterNaiveFast :: [Point] -> Double perimeterNaiveFast [] = 0.0
> perimeterNaiveFast (first:rest) = foldPoints rest first 0.0   
>   where
>     foldPoints []         lst  acc = acc + distance first lst
>     foldPoints (next:rst) prev acc = foldPoints rst next (acc + distance next prev)
> 
> perimeterStrictFast :: [Point] -> Double perimeterStrictFast [] = 0.0
> perimeterStrictFast (first:rest) = foldPoints rest first 0.0   
>   where
>     foldPoints []         lst  acc = acc + distance first lst
>     foldPoints (next:rst) prev !acc = foldPoints rst next (acc + distance next prev)
> 
> main :: IO () 
> main = defaultMain [ perimeterBench $ 10 ^ (6 :: Int) ]
> 
> perimeterBench :: Int -> Benchmark perimeterBench n = bgroup "Perimiter"   
>   [ bench "Naive"  $ nf perimeterNaive points   
>   , bench "Strict" $ nf perimeterStrict points 
>   , bench "Naive fast" $ nf perimeterNaiveFast points 
>   , bench "Strict fast" $ nf perimeterStrictFast points   
>   ]   
>     where
>       points = map (\i -> Point i i) [1..n]

【问题讨论】:

    标签: performance haskell benchmarking strictness


    【解决方案1】:

    GHC 的strictness analysis 通行证注意到Float 累加器不会(也不能)被懒惰消耗,并代表您将您的幼稚版本转换为严格版本。

    它还没有为你的另一个天真/快速对这样做的原因是这个子句:

    foldPoints []              _   =  0.0
    

    在这里你忽略了累加器,因此编译器认为在某些情况下不强制计算可能会更好。将其更改为

    foldPoints []            acc   =  acc
    

    足以让 GHC 让您的其他天真/严格对在我的机器上具有相同的性能。

    【讨论】:

      猜你喜欢
      • 2014-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      • 2011-03-08
      • 2012-03-09
      • 2010-09-15
      • 1970-01-01
      相关资源
      最近更新 更多