与Scala相比,Haskell Vector性能
发布时间:2020-12-16 18:25:33 所属栏目:安全 来源:网络整理
导读:我在 Haskell和 Scala中有一段非常简单的代码.此代码旨在以非常紧凑的循环运行,因此性能很重要.问题是Haskell比Scala慢大约10倍.这是Haskell代码. {-# LANGUAGE BangPatterns #-}import qualified Data.Vector.Unboxed as VUnewtype AffineTransform = Affin
我在
Haskell和
Scala中有一段非常简单的代码.此代码旨在以非常紧凑的循环运行,因此性能很重要.问题是Haskell比Scala慢大约10倍.这是Haskell代码.
{-# LANGUAGE BangPatterns #-} import qualified Data.Vector.Unboxed as VU newtype AffineTransform = AffineTransform {get :: (VU.Vector Double)} deriving (Show) {-# INLINE runAffineTransform #-} runAffineTransform :: AffineTransform -> (Double,Double) -> (Double,Double) runAffineTransform affTr (!x,!y) = (get affTr `VU.unsafeIndex` 0 * x + get affTr `VU.unsafeIndex` 1 * y + get affTr `VU.unsafeIndex` 2,get affTr `VU.unsafeIndex` 3 * x + get affTr `VU.unsafeIndex` 4 * y + get affTr `VU.unsafeIndex` 5) testAffineTransformSpeed :: AffineTransform -> Int -> (Double,Double) testAffineTransformSpeed affTr count = go count (0.5,0.5) where go :: Int -> (Double,Double) go 0 res = res go !n !res = go (n-1) (runAffineTransform affTr res) 还有什么可以改进这个代码? 解决方法
主要问题是
runAffineTransform affTr (!x,!y) = (get affTr `VU.unsafeIndex` 0 * x + get affTr `VU.unsafeIndex` 1 * y + get affTr `VU.unsafeIndex` 2,get affTr `VU.unsafeIndex` 3 * x + get affTr `VU.unsafeIndex` 4 * y + get affTr `VU.unsafeIndex` 5) 产生一对thunk.调用runAffineTransform时不会评估组件,它们会保持不变,直到某些消费者要求对它们进行评估. testAffineTransformSpeed affTr count = go count (0.5,Double) go 0 res = res go !n !res = go (n-1) (runAffineTransform affTr res) 不是那个消费者,关于res的爆炸只会将它评估到最外层的构造函数(,),并且你得到的结果是 runAffineTransform affTr (runAffineTrasform affTr (runAffineTransform affTr (...))) 当最终需要正常形式时,仅在最后评估. 如果强制立即评估结果的组件, runAffineTransform affTr (!x,!y) = case ( get affTr `U.unsafeIndex` 0 * x + get affTr `U.unsafeIndex` 1 * y + get affTr `U.unsafeIndex` 2,get affTr `U.unsafeIndex` 3 * x + get affTr `U.unsafeIndex` 4 * y + get affTr `U.unsafeIndex` 5 ) of (!a,!b) -> (a,b) 使用自定义严格的一对未装箱的Double#s对jtobin版本的主要区别在于,对于testAffineTransformSpeed中的循环,您使用盒装双打作为参数进行一次初始迭代,最后是组件结果是盒装的,这会增加一些不变的开销(我的盒子上每个循环大约5纳秒).循环的主要部分在两种情况下都采用Int#和两个Double#参数,并且当达到n = 0时,除了装箱之外,循环体是相同的. 当然,通过使用未装箱的严格对类型强制立即评估组件是更好的. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |