我使用Haskell实现了一个简单的L1距离计算器.由于我对性能感兴趣,因此我使用未装箱的矢量来存储要比较的图像.
calculateL1Distance :: LabeledImage -> LabeledImage -> Int
calculateL1Distance reference test =
let
substractPixels :: Int -> Int -> Int
substractPixels a b = abs $ a - b
diff f = Vec.sum $ Vec.zipWith substractPixels (f reference) (f test)
in
diff pixels
Run Code Online (Sandbox Code Playgroud)
据我所知(我是Haskell的新手),流融合应该使这个代码作为一个简单的循环运行.所以它应该很快.但是,编译时性能结果很低
ghc -O -fforce-recomp -rtsopts -o test .\performance.hs
Run Code Online (Sandbox Code Playgroud)
该计划耗时约60秒:
198,871,911,896 bytes allocated in the heap
1,804,017,536 bytes copied during GC
254,900,000 bytes maximum residency (14 sample(s))
9,020,888 bytes maximum slop
579 MB total memory in use (0 …Run Code Online (Sandbox Code Playgroud) optimization performance haskell nearest-neighbor stream-fusion
以下代码意外地(至少对我而言)产生了一个中间向量:
import qualified Data.Vector as Vector
main :: IO ()
main =
print (test n)
n :: Int
n = 1000000
test :: Int -> Int
test n = Vector.length (Vector.replicate n (0 :: Int))
Run Code Online (Sandbox Code Playgroud)
Core的相关部分在这里(注意newArray# 1000000电话):
Main.main4
:: forall s_a38t.
GHC.Prim.State# s_a38t
-> (# GHC.Prim.State# s_a38t, Vector.Vector Int #)
[GblId,
Arity=1,
Str=DmdType,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
WorkFree=True, Expandable=True, Guidance=IF_ARGS [0] 399 30}]
Main.main4 =
\ (@ s_a38t) (s1_a38u [OS=OneShot] :: GHC.Prim.State# s_a38t) ->
case GHC.Prim.newArray#
@ Int …Run Code Online (Sandbox Code Playgroud) 这是一个简短的Haskell程序,可产生440 Hz的声音.它使用pulseaudio作为音频后端.
import GHC.Float
import Control.Arrow
import Sound.Pulse.Simple
import qualified Data.List.Stream as S
import Data.List
type Time = Double
type Frequency = Double
type Sample = Double
type CV = Double
chunksize = 441 * 2
sampleRate :: (Fractional a) => a
sampleRate = 44100
integral :: [Double] -> [Double]
integral = scanl1 (\acc x -> acc + x / sampleRate)
chunks :: Int -> [a] -> [[a]]
chunks n = S.takeWhile (not . S.null) . S.unfoldr (Just . S.splitAt …Run Code Online (Sandbox Code Playgroud) 我有兴趣创建一个新的Haskell容器类型(严格列表),我想确保它们上的操作符合流融合的条件.如何选择ghc的流融合功能?
如果我的容器是Traversable,它会自动融合吗?如果我实现了,说mapAccumL来讲toList,将哈斯克尔足够聪明,不是容器转换到一个列表所有,而不是简单地对底层表示操作?