[Haskell-beginners] parallel quicksort
Ovidiu Deac
ovidiudeac at gmail.com
Wed Aug 3 00:44:03 CEST 2011
I'm trying to write a parallel quicksort algorithm for lists.
This is my original implementation:
quickSort [] = []
quickSort (x:xs) = (quickSort small) ⊕ [x] ⊕ (quickSort big)
where
small = [p | p ← xs, p ≤ x]
big = [p | p ← xs, p > x]
and the output is:
$ ghc -threaded -rtsopts -o quicksort quicksort.hs && ./quicksort +RTS -N2 -RTS
[1 of 1] Compiling Main ( quicksort.hs, quicksort.o )
Linking quicksort ...
Sorting 1000000 elements...
CPU Time: 13290000000000
Time elapsed: 8.929503s
ovidiu at asus:~/work/haskell$ ghc -threaded -rtsopts -o quicksort
quicksort.hs && ./quicksort +RTS -N2 -RTS
Sorting 1000000 elements...
CPU Time: 11240000000000
Time elapsed: 7.785293s
ovidiu at asus:~/work/haskell$ ghc -threaded -rtsopts -o quicksort
quicksort.hs && ./quicksort +RTS -N1 -RTS
Sorting 1000000 elements...
CPU Time: 6790000000000
Time elapsed: 6.817648s
ovidiu at asus:~/work/haskell$ ghc -threaded -rtsopts -o quicksort
quicksort.hs && ./quicksort +RTS -N1 -RTS
Sorting 1000000 elements...
CPU Time: 6980000000000
Time elapsed: 7.006658s
ovidiu at asus:~/work/haskell$ ghc -threaded -rtsopts -o quicksort
quicksort.hs && ./quicksort +RTS -N1 -RTS
Sorting 1000000 elements...
CPU Time: 5900000000000
Time elapsed: 5.932236s
...so the conclusion is that using option N1 is faster the N2. This makes sense.
Then I tried to parallelize it:
First try:
-----------------
quickSort [] = []
quickSort (x:xs) = small `pseq` ((quickSort small) ⊕ [x] ⊕ (quickSort big))
where
small = [p | p ← xs, p ≤ x]
big = [p | p ← xs, p > x]
$ ghc -threaded -rtsopts -o quicksort quicksort.hs && ./quicksort +RTS -N2 -RTS
[1 of 1] Compiling Main ( quicksort.hs, quicksort.o )
Linking quicksort ...
Sorting 1000000 elements...
CPU Time: 12020000000000
Time elapsed: 8.29653s
This is slower then the non-parallel version
Second try:
---------------
quickSort [] = []
quickSort (x:xs) = small `par` ((quickSort small) ⊕ [x] ⊕ (quickSort big))
where
small = [p | p ← xs, p ≤ x]
big = [p | p ← xs, p > x]
$ ghc -threaded -rtsopts -o quicksort quicksort.hs && ./quicksort +RTS -N2 -RTS
Sorting 1000000 elements...
CPU Time: 14750000000000
Time elapsed: 10.772271s
Even slower
Third try:
-------------
quickSort [] = []
quickSort (x:xs) = small `par` (big `par` ((quickSort small) ⊕ [x] ⊕
(quickSort big)))
where
small = [p | p ← xs, p ≤ x]
big = [p | p ← xs, p > x]
$ ghc -threaded -rtsopts -o quicksort quicksort.hs && ./quicksort +RTS -N2 -RTS
[1 of 1] Compiling Main ( quicksort.hs, quicksort.o )
Linking quicksort ...
Sorting 1000000 elements...
CPU Time: 134490000000000
Time elapsed: 122.917093s
Fourth try:
------------------------
quickSort [] = []
quickSort (x:xs) = small `par` (big `pseq` ((quickSort small) ⊕ [x] ⊕
(quickSort big)))
where
small = [p | p ← xs, p ≤ x]
big = [p | p ← xs, p > x]
$ ghc -threaded -rtsopts -o quicksort quicksort.hs && ./quicksort +RTS -N2 -RTS
[1 of 1] Compiling Main ( quicksort.hs, quicksort.o )
Linking quicksort ...
Sorting 1000000 elements...
CPU Time: 12770000000000
Time elapsed: 8.844304s
-----------------------------
It seems that I'm unable to make it parallel. What am I doing wrong?
Thanks,
ovidiu
See the full code below:
--------------------------------------------------
module Main where
import Prelude
import Data.List
import Data.Time.Clock
import System.CPUTime
import System.Random
import Control.Parallel
import Control.Exception (evaluate)
import Control.DeepSeq (rnf)
import Text.Printf
quickSort [] = []
quickSort (x:xs) = small `par` (big `par` ((quickSort small) ⊕ [x] ⊕
(quickSort big)))
where
small = [p | p ← xs, p ≤ x]
big = [p | p ← xs, p > x]
randomlist :: Int → StdGen → [Int]
randomlist n = take n∘unfoldr (Just∘random)
len = 10 ↑ 6
time = do
t ← getCurrentTime
c ← getCPUTime
return (t,c)
measure f p = do
(t1, c1) ← time
evaluate $ rnf $ f p
(t2, c2) ← time
return (diffUTCTime t2 t1, c2 - c1)
main = do
seed ← newStdGen
let rs = randomlist len seed
printf "Sorting %d elements...\n" len
(t, cpu) ← measure quickSort rs
printf "CPU Time: %dλnTime elapsed: %sλn" cpu (show t)
More information about the Beginners
mailing list