为什么我使用'par`的Haskell程序不会产生任何火花?

时间:2015-01-20 05:28:53

标签: haskell parallel-processing

我正在尝试使用线程编译以下程序:

import qualified Data.Vector.Unboxed as UV
passes = UV.fromList [1..1000000] :: UV.Vector Int
vector = UV.fromList [1..100] :: UV.Vector Double
vectors = x `par` y `par` z `par` w `pseq` (x,y,z,w) where
    x = UV.foldr' (const (UV.map (+1))) vector passes
    y = UV.foldr' (const (UV.map (+2))) vector passes
    z = UV.foldr' (const (UV.map (+3))) vector passes
    w = UV.foldr' (const (UV.map (+4))) vector passes
main = print vectors

但它看起来并不是并行执行,因为它与N1N4的执行时间几乎相同。

vh:haskell apple1$ ghc -fforce-recomp -threaded -O2 bench.hs -o bench; time ./bench +RTS -s -N4
[1 of 1] Compiling Main             ( bench.hs, bench.o )
Linking bench ...
(fromList [1000001.0,1000002.0,1000003.0,1000004.0,1000005.0,1000006.0,1000007.0,1000008.0,1000009.0,1000010.0,1000011.0,1000012.0,1000013.0,1000014.0,1000015.0,1000016.0,1000017.0,1000018.0,1000019.0,1000020.0,1000021.0,1000022.0,1000023.0,1000024.0,1000025.0,1000026.0,1000027.0,1000028.0,1000029.0,1000030.0,1000031.0,1000032.0,1000033.0,1000034.0,1000035.0,1000036.0,1000037.0,1000038.0,1000039.0,1000040.0,1000041.0,1000042.0,1000043.0,1000044.0,1000045.0,1000046.0,1000047.0,1000048.0,1000049.0,1000050.0,1000051.0,1000052.0,1000053.0,1000054.0,1000055.0,1000056.0,1000057.0,1000058.0,1000059.0,1000060.0,1000061.0,1000062.0,1000063.0,1000064.0,1000065.0,1000066.0,1000067.0,1000068.0,1000069.0,1000070.0,1000071.0,1000072.0,1000073.0,1000074.0,1000075.0,1000076.0,1000077.0,1000078.0,1000079.0,1000080.0,1000081.0,1000082.0,1000083.0,1000084.0,1000085.0,1000086.0,1000087.0,1000088.0,1000089.0,1000090.0,1000091.0,1000092.0,1000093.0,1000094.0,1000095.0,1000096.0,1000097.0,1000098.0,1000099.0,1000100.0],fromList [2000001.0,2000002.0,2000003.0,2000004.0,2000005.0,2000006.0,2000007.0,2000008.0,2000009.0,2000010.0,2000011.0,2000012.0,2000013.0,2000014.0,2000015.0,2000016.0,2000017.0,2000018.0,2000019.0,2000020.0,2000021.0,2000022.0,2000023.0,2000024.0,2000025.0,2000026.0,2000027.0,2000028.0,2000029.0,2000030.0,2000031.0,2000032.0,2000033.0,2000034.0,2000035.0,2000036.0,2000037.0,2000038.0,2000039.0,2000040.0,2000041.0,2000042.0,2000043.0,2000044.0,2000045.0,2000046.0,2000047.0,2000048.0,2000049.0,2000050.0,2000051.0,2000052.0,2000053.0,2000054.0,2000055.0,2000056.0,2000057.0,2000058.0,2000059.0,2000060.0,2000061.0,2000062.0,2000063.0,2000064.0,2000065.0,2000066.0,2000067.0,2000068.0,2000069.0,2000070.0,2000071.0,2000072.0,2000073.0,2000074.0,2000075.0,2000076.0,2000077.0,2000078.0,2000079.0,2000080.0,2000081.0,2000082.0,2000083.0,2000084.0,2000085.0,2000086.0,2000087.0,2000088.0,2000089.0,2000090.0,2000091.0,2000092.0,2000093.0,2000094.0,2000095.0,2000096.0,2000097.0,2000098.0,2000099.0,2000100.0],fromList [3000001.0,3000002.0,3000003.0,3000004.0,3000005.0,3000006.0,3000007.0,3000008.0,3000009.0,3000010.0,3000011.0,3000012.0,3000013.0,3000014.0,3000015.0,3000016.0,3000017.0,3000018.0,3000019.0,3000020.0,3000021.0,3000022.0,3000023.0,3000024.0,3000025.0,3000026.0,3000027.0,3000028.0,3000029.0,3000030.0,3000031.0,3000032.0,3000033.0,3000034.0,3000035.0,3000036.0,3000037.0,3000038.0,3000039.0,3000040.0,3000041.0,3000042.0,3000043.0,3000044.0,3000045.0,3000046.0,3000047.0,3000048.0,3000049.0,3000050.0,3000051.0,3000052.0,3000053.0,3000054.0,3000055.0,3000056.0,3000057.0,3000058.0,3000059.0,3000060.0,3000061.0,3000062.0,3000063.0,3000064.0,3000065.0,3000066.0,3000067.0,3000068.0,3000069.0,3000070.0,3000071.0,3000072.0,3000073.0,3000074.0,3000075.0,3000076.0,3000077.0,3000078.0,3000079.0,3000080.0,3000081.0,3000082.0,3000083.0,3000084.0,3000085.0,3000086.0,3000087.0,3000088.0,3000089.0,3000090.0,3000091.0,3000092.0,3000093.0,3000094.0,3000095.0,3000096.0,3000097.0,3000098.0,3000099.0,3000100.0],fromList [4000001.0,4000002.0,4000003.0,4000004.0,4000005.0,4000006.0,4000007.0,4000008.0,4000009.0,4000010.0,4000011.0,4000012.0,4000013.0,4000014.0,4000015.0,4000016.0,4000017.0,4000018.0,4000019.0,4000020.0,4000021.0,4000022.0,4000023.0,4000024.0,4000025.0,4000026.0,4000027.0,4000028.0,4000029.0,4000030.0,4000031.0,4000032.0,4000033.0,4000034.0,4000035.0,4000036.0,4000037.0,4000038.0,4000039.0,4000040.0,4000041.0,4000042.0,4000043.0,4000044.0,4000045.0,4000046.0,4000047.0,4000048.0,4000049.0,4000050.0,4000051.0,4000052.0,4000053.0,4000054.0,4000055.0,4000056.0,4000057.0,4000058.0,4000059.0,4000060.0,4000061.0,4000062.0,4000063.0,4000064.0,4000065.0,4000066.0,4000067.0,4000068.0,4000069.0,4000070.0,4000071.0,4000072.0,4000073.0,4000074.0,4000075.0,4000076.0,4000077.0,4000078.0,4000079.0,4000080.0,4000081.0,4000082.0,4000083.0,4000084.0,4000085.0,4000086.0,4000087.0,4000088.0,4000089.0,4000090.0,4000091.0,4000092.0,4000093.0,4000094.0,4000095.0,4000096.0,4000097.0,4000098.0,4000099.0,4000100.0])
   3,842,955,664 bytes allocated in the heap
      16,390,368 bytes copied during GC
       8,469,360 bytes maximum residency (6 sample(s))
       2,122,880 bytes maximum slop
              24 MB total memory in use (7 MB lost due to fragmentation)

                                    Tot time (elapsed)  Avg pause  Max pause
  Gen  0      7411 colls,  7411 par    0.20s    0.06s     0.0000s    0.0004s
  Gen  1         6 colls,     5 par    0.00s    0.00s     0.0002s    0.0008s

  Parallel GC work balance: 1.00% (serial 0%, perfect 100%)

  TASKS: 10 (1 bound, 9 peak workers (9 total), using -N4)

  SPARKS: 3 (0 converted, 0 overflowed, 0 dud, 3 GC'd, 0 fizzled)

  INIT    time    0.00s  (  0.00s elapsed)
  MUT     time    0.77s  (  0.69s elapsed)
  GC      time    0.20s  (  0.06s elapsed)
  EXIT    time    0.00s  (  0.00s elapsed)
  Total   time    0.97s  (  0.76s elapsed)

  Alloc rate    5,018,806,918 bytes per MUT second

  Productivity  78.9% of total user, 101.5% of total elapsed

gc_alloc_block_sync: 6988
whitehole_spin: 0
gen[0].sync: 0
gen[1].sync: 0

real    0m0.759s
user    0m0.972s
sys 0m0.158s
vh:haskell apple1$ time ./bench
(fromList [1000001.0,1000002.0,1000003.0,1000004.0,1000005.0,1000006.0,1000007.0,1000008.0,1000009.0,1000010.0,1000011.0,1000012.0,1000013.0,1000014.0,1000015.0,1000016.0,1000017.0,1000018.0,1000019.0,1000020.0,1000021.0,1000022.0,1000023.0,1000024.0,1000025.0,1000026.0,1000027.0,1000028.0,1000029.0,1000030.0,1000031.0,1000032.0,1000033.0,1000034.0,1000035.0,1000036.0,1000037.0,1000038.0,1000039.0,1000040.0,1000041.0,1000042.0,1000043.0,1000044.0,1000045.0,1000046.0,1000047.0,1000048.0,1000049.0,1000050.0,1000051.0,1000052.0,1000053.0,1000054.0,1000055.0,1000056.0,1000057.0,1000058.0,1000059.0,1000060.0,1000061.0,1000062.0,1000063.0,1000064.0,1000065.0,1000066.0,1000067.0,1000068.0,1000069.0,1000070.0,1000071.0,1000072.0,1000073.0,1000074.0,1000075.0,1000076.0,1000077.0,1000078.0,1000079.0,1000080.0,1000081.0,1000082.0,1000083.0,1000084.0,1000085.0,1000086.0,1000087.0,1000088.0,1000089.0,1000090.0,1000091.0,1000092.0,1000093.0,1000094.0,1000095.0,1000096.0,1000097.0,1000098.0,1000099.0,1000100.0],fromList [2000001.0,2000002.0,2000003.0,2000004.0,2000005.0,2000006.0,2000007.0,2000008.0,2000009.0,2000010.0,2000011.0,2000012.0,2000013.0,2000014.0,2000015.0,2000016.0,2000017.0,2000018.0,2000019.0,2000020.0,2000021.0,2000022.0,2000023.0,2000024.0,2000025.0,2000026.0,2000027.0,2000028.0,2000029.0,2000030.0,2000031.0,2000032.0,2000033.0,2000034.0,2000035.0,2000036.0,2000037.0,2000038.0,2000039.0,2000040.0,2000041.0,2000042.0,2000043.0,2000044.0,2000045.0,2000046.0,2000047.0,2000048.0,2000049.0,2000050.0,2000051.0,2000052.0,2000053.0,2000054.0,2000055.0,2000056.0,2000057.0,2000058.0,2000059.0,2000060.0,2000061.0,2000062.0,2000063.0,2000064.0,2000065.0,2000066.0,2000067.0,2000068.0,2000069.0,2000070.0,2000071.0,2000072.0,2000073.0,2000074.0,2000075.0,2000076.0,2000077.0,2000078.0,2000079.0,2000080.0,2000081.0,2000082.0,2000083.0,2000084.0,2000085.0,2000086.0,2000087.0,2000088.0,2000089.0,2000090.0,2000091.0,2000092.0,2000093.0,2000094.0,2000095.0,2000096.0,2000097.0,2000098.0,2000099.0,2000100.0],fromList [3000001.0,3000002.0,3000003.0,3000004.0,3000005.0,3000006.0,3000007.0,3000008.0,3000009.0,3000010.0,3000011.0,3000012.0,3000013.0,3000014.0,3000015.0,3000016.0,3000017.0,3000018.0,3000019.0,3000020.0,3000021.0,3000022.0,3000023.0,3000024.0,3000025.0,3000026.0,3000027.0,3000028.0,3000029.0,3000030.0,3000031.0,3000032.0,3000033.0,3000034.0,3000035.0,3000036.0,3000037.0,3000038.0,3000039.0,3000040.0,3000041.0,3000042.0,3000043.0,3000044.0,3000045.0,3000046.0,3000047.0,3000048.0,3000049.0,3000050.0,3000051.0,3000052.0,3000053.0,3000054.0,3000055.0,3000056.0,3000057.0,3000058.0,3000059.0,3000060.0,3000061.0,3000062.0,3000063.0,3000064.0,3000065.0,3000066.0,3000067.0,3000068.0,3000069.0,3000070.0,3000071.0,3000072.0,3000073.0,3000074.0,3000075.0,3000076.0,3000077.0,3000078.0,3000079.0,3000080.0,3000081.0,3000082.0,3000083.0,3000084.0,3000085.0,3000086.0,3000087.0,3000088.0,3000089.0,3000090.0,3000091.0,3000092.0,3000093.0,3000094.0,3000095.0,3000096.0,3000097.0,3000098.0,3000099.0,3000100.0],fromList [4000001.0,4000002.0,4000003.0,4000004.0,4000005.0,4000006.0,4000007.0,4000008.0,4000009.0,4000010.0,4000011.0,4000012.0,4000013.0,4000014.0,4000015.0,4000016.0,4000017.0,4000018.0,4000019.0,4000020.0,4000021.0,4000022.0,4000023.0,4000024.0,4000025.0,4000026.0,4000027.0,4000028.0,4000029.0,4000030.0,4000031.0,4000032.0,4000033.0,4000034.0,4000035.0,4000036.0,4000037.0,4000038.0,4000039.0,4000040.0,4000041.0,4000042.0,4000043.0,4000044.0,4000045.0,4000046.0,4000047.0,4000048.0,4000049.0,4000050.0,4000051.0,4000052.0,4000053.0,4000054.0,4000055.0,4000056.0,4000057.0,4000058.0,4000059.0,4000060.0,4000061.0,4000062.0,4000063.0,4000064.0,4000065.0,4000066.0,4000067.0,4000068.0,4000069.0,4000070.0,4000071.0,4000072.0,4000073.0,4000074.0,4000075.0,4000076.0,4000077.0,4000078.0,4000079.0,4000080.0,4000081.0,4000082.0,4000083.0,4000084.0,4000085.0,4000086.0,4000087.0,4000088.0,4000089.0,4000090.0,4000091.0,4000092.0,4000093.0,4000094.0,4000095.0,4000096.0,4000097.0,4000098.0,4000099.0,4000100.0])

real    0m0.717s
user    0m0.694s
sys 0m0.021s

为什么它没有并行运行,我该如何解决?

2 个答案:

答案 0 :(得分:3)

我认为火花在创建后需要一段时间才能得到处理,所以如果你没有很多工作要做,那么它们很可能会被GC发现或失败。

考虑这个程序:

import Control.Parallel.Strategies
import System.Environment

fib :: Int -> Int
fib n
  | n <= 2 = n
  | otherwise = fib (n-2) + fib (n-1)

test4 n = runEval $ do
  a <- rpar (fib n)
  b <- rpar (fib (n+1))
  c <- rpar (fib (n+2))
  d <- rpar (fib (n+3))
  return (a,b,c,d)

main = do
  n <- fmap (read.head) getArgs
  print $ test4 n

以下是我通常在n的各种值中看到的内容摘要:

n           sparks
----------  ------------------------
up to 25    either 4 GC or 4 fizzled
26          1 converted, 3 fizzled
28          2 converted, 2 fizzled
30          3 converted, 1 fizzled

在每种情况下都会创建4个火花,但对于较小的n值,火花管理器没有时间评估它们中的任何一个,它们都会被主线程评估。

答案 1 :(得分:1)

肯定有一个技巧可以让火花运转起来。以下是使用parMap的另一种方法:

import Control.Monad.Par

import qualified Data.Vector.Unboxed as UV

passes = UV.fromList [1..1000000] :: UV.Vector Int
vector = UV.fromList [1..100] :: UV.Vector Double

test = runPar $ parMap go [1..4]
  where go k = UV.foldr' (const (UV.map (+k))) vector passes

main = print test

这不会产生任何火花,但代码并行运行。分析统计显示总时间为1.63秒(经过0.93秒)。

Threadscope非常便于观察HEC活动。编译:

ghc -O2 -threaded -eventlog -rtsopts ...

并运行:

./prog +RTS -N... -l

生成用于Threadscope的事件日志文件。