我一直在努力理解 haskell 上并行性的某些方面。我必须将并行性应用于一段代码,但我尝试过的尝试无法正常工作。
功能是这个:
fft :: [Complex Float] -> [Complex Float]
fft [a] = [a]
fft as = interleave ls rs
where
(cs,ds) = bflyS as
ls = fft cs
rs = fft ds
interleave [] bs = bs
interleave (a:as) bs = a : interleave bs as
halve as = splitAt n' as
where
n' = div (length as + 1) 2
-- twiddle factors
tw :: Int -> Int -> Complex Float
tw n k = cis (-2 * pi * fromIntegral k / fromIntegral n)
bflyS :: [Complex Float] -> ([Complex Float], [Complex Float])
bflyS as = (los,rts)
where
(ls,rs) = halve as
los = zipWith (+) ls rs
ros = zipWith (-) ls rs
rts = zipWith (*) ros [tw n i | i <- [0..n - 1]]
n = length a
我尝试使此功能任务并行的尝试如下:
bflySTask :: [Complex Float] -> ([Complex Float], [Complex Float])
bflySTask as = (los,rts) `using` if n>1000 then parTuple2 (parListChunk 500 rseq) (parListChunk 500 rseq) else r0
where
(ls,rs) = halve as
los = zipWith (+) ls rs
ros = zipWith (-) ls rs
n = length as
fx = (map (tw (n)) [0..n-1])
rts = zipWith (*) ros fx
和 Par Monad
bflySTask :: [Complex Float] -> ([Complex Float], [Complex Float])
bflySTask as = f as
where
(ls,rs) = halve as
los = zipWith (+) ls rs
ros = zipWith (-) ls rs
n = length as
fx = (map (tw (n)) [0..n-1])
f as = if n>10000 then
runPar $ do
v1<-new
v2<-new
fork $ put v1 (zipWith (*) ros fx)
fork $ put v2 (zipWith (+) ls rs)
a <- get v1
b <- get v2
return (a, b)
else
(zipWith (+) ls rs, zipWith (*) ros fx)
这两种方法的并行性都很少,例如 1.30 的并行 GC 工作平衡,并且一些火花被 GC 和失败了。有谁知道在不改变数据结构的情况下我可以做些什么来在这个函数上应用并行性?