git.iko.soy/distributed-process
on master help sign in
Clean up the code
commitbd36d06aa66b4578398b29713cf4ce07981f457c authorEdsko de Vries <edsko@edsko.net> dateThu 27 Sep 2012, 16:44 (14 years ago) parent5ad2786
7 files changed+48−62
distributed-process-demos/distributed-process-demos.cabal+1−1 distributed-process-demos/src/MapReduce/CountWords.hs+1−1 distributed-process-demos/src/MapReduce/KMeans.hs+3−3 distributed-process-demos/src/MapReduce/MapReduce.hs+26−34 distributed-process-demos/src/MasterSlave/MasterSlave.hs+1−1 distributed-process-demos/src/WorkPushing/WorkPushing.hs+7−8 distributed-process-demos/src/WorkStealing/WorkStealing.hs+9−14
distributed-process-demos/distributed-process-demos.cabal+1−1
@@ -93,7 +93,7 @@ executable distributed-process-simplelocalnet-mapreduce
9393 hs-source-dirs: src/MapReduce
9494 build-depends: base ==4.5.*,
9595 distributed-process >= 0.3.2,
96− distributed-static >= 0.2 && < 0.3,
96+ distributed-static >= 0.2.0 && < 0.3,
9797 containers >= 0.4 && < 0.6,
9898 bytestring >= 0.9 && < 0.11,
9999 binary >= 0.5 && < 0.6,
distributed-process-demos/src/MapReduce/CountWords.hs+1−1
@@ -23,7 +23,7 @@ countWords = MapReduce {
2323localCountWords :: Map FilePath Document -> Map Word Frequency
2424localCountWords = localMapReduce countWords
2525
26−dictIn :: SerializableDict (ProcessId, FilePath, Document)
26+dictIn :: SerializableDict (FilePath, Document)
2727dictIn = SerializableDict
2828
2929dictOut :: SerializableDict [(Word, Frequency)]
distributed-process-demos/src/MapReduce/KMeans.hs+3−3
@@ -59,7 +59,7 @@ localKMeans points cs iterations = go (iterations - 1)
5959 trivialSegmentation :: [Cluster] -> Map (Int, Int) [Cluster]
6060 trivialSegmentation cs' = Map.fromList [(bounds points, cs')]
6161
62−dictIn :: SerializableDict (ProcessId, (Int, Int), [Cluster])
62+dictIn :: SerializableDict ((Int, Int), [Cluster])
6363dictIn = SerializableDict
6464
6565dictOut :: SerializableDict [(Cluster, Point)]
@@ -82,7 +82,7 @@ distrKMeans points cs mappers iterations =
8282 go :: Int
8383 -> (Map (Int, Int) [Cluster] -> Process (Map Cluster ([Point], Point)))
8484 -> Process (Map Cluster ([Point], Point))
85− go 0 iteration = do
85+ go 0 iteration =
8686 iteration (Map.fromList $ map (, cs) segments)
8787 go n iteration = do
8888 clusters <- go (n - 1) iteration
@@ -120,7 +120,7 @@ createGnuPlot clusters h =
120120
121121 flatten :: [(Float, (KMeans.Cluster, ([KMeans.Point], KMeans.Point)))]
122122 -> [(Double, Double, Float)]
123− flatten = concat . map (\(color, (_, (points, _))) -> map (\(x, y) -> (x, y, color)) points)
123+ flatten = concatMap (\(color, (_, (points, _))) -> map (\(x, y) -> (x, y, color)) points)
124124
125125 colors :: [Float]
126126 colors = [0, 1 / fromIntegral (Map.size clusters) .. 1]
distributed-process-demos/src/MapReduce/MapReduce.hs+26−34
@@ -15,14 +15,13 @@ import Data.ByteString.Lazy (ByteString)
1515import Data.Map (Map)
1616import qualified Data.Map as Map (mapWithKey, fromListWith, toList, size)
1717import Control.Arrow (second)
18−import Control.Monad (forM_, forever, replicateM)
18+import Control.Monad (forM_, replicateM, replicateM_)
1919import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
2020import qualified Control.Concurrent.Chan as Chan
2121import Control.Distributed.Process
2222import Control.Distributed.Process.Serializable (Serializable)
2323import Control.Distributed.Process.Closure
2424import Control.Distributed.Static (closureApply, staticCompose, staticApply)
25−import Control.Concurrent (threadDelay)
2625
2726--------------------------------------------------------------------------------
2827-- Definition of a MapReduce skeleton and a local implementation --
@@ -64,59 +63,52 @@ matchDict SerializableDict = match
6463sendDict :: forall a. SerializableDict a -> ProcessId -> a -> Process ()
6564sendDict SerializableDict = send
6665
66+sdictProcessIdPair :: SerializableDict (ProcessId, ProcessId)
67+sdictProcessIdPair = SerializableDict
68+
6769mapperProcess :: forall k1 v1 k2 v2 v3.
68− SerializableDict (ProcessId, k1, v1)
70+ SerializableDict (k1, v1)
6971 -> SerializableDict [(k2, v2)]
70− -> ProcessId
72+ -> (ProcessId, ProcessId)
7173 -> MapReduce k1 v1 k2 v2 v3
7274 -> Process ()
73−mapperProcess dictIn dictOut workQueue mr = do
74− us <- getSelfPid
75− liftIO . putStrLn $ "Mapper " ++ show us ++ " started"
76− go us
75+mapperProcess dictIn dictOut (master, workQueue) mr = getSelfPid >>= go
7776 where
7877 go us = do
7978 -- Ask the queue for work
8079 send workQueue us
8180
82− liftIO . putStrLn $ "Mapper " ++ show us ++ " waiting for work"
83− -- Wait for a reply
84− mWork <- receiveWait
85− [ matchDict dictIn $ \(pid, key, val) -> return $ Just (pid, key, val)
86− , match $ \() -> return Nothing
81+ -- Wait for a reply; if there is work, do it and repeat; otherwise, exit
82+ receiveWait
83+ [ matchDict dictIn $ \(key, val) -> do
84+ sendDict dictOut master (mrMap mr key val)
85+ go us
86+ , match $ \() ->
87+ return ()
8788 ]
8889
89− -- If there is work, do it and repeat; otherwise, exit
90− case mWork of
91− Just (pid, key, val) -> do
92− sendDict dictOut pid (mrMap mr key val)
93− go us
94−
95− Nothing -> do
96− liftIO $ putStrLn "Slave exiting"
97− return ()
98−
99−remotable ['mapperProcess]
90+remotable ['mapperProcess, 'sdictProcessIdPair]
10091
10192mapperProcessClosure :: forall k1 v1 k2 v2 v3.
10293 (Typeable k1, Typeable v1, Typeable k2, Typeable v2, Typeable v3)
103− => Static (SerializableDict (ProcessId, k1, v1))
94+ => Static (SerializableDict (k1, v1))
10495 -> Static (SerializableDict [(k2, v2)])
10596 -> Closure (MapReduce k1 v1 k2 v2 v3)
10697 -> ProcessId
98+ -> ProcessId
10799 -> Closure (Process ())
108−mapperProcessClosure dictIn dictOut mr pid =
109− closure decoder (encode pid) `closureApply` mr
100+mapperProcessClosure dictIn dictOut mr master workQueue =
101+ closure decoder (encode (master, workQueue)) `closureApply` mr
110102 where
111103 decoder :: Static (ByteString -> MapReduce k1 v1 k2 v2 v3 -> Process ())
112104 decoder =
113105 ($(mkStatic 'mapperProcess) `staticApply` dictIn `staticApply` dictOut)
114106 `staticCompose`
115− staticDecode sdictProcessId
107+ staticDecode $(mkStatic 'sdictProcessIdPair)
116108
117109distrMapReduce :: forall k1 k2 v1 v2 v3 a.
118110 (Serializable k1, Serializable v1, Serializable k2, Serializable v2, Serializable v3, Ord k2)
119− => Static (SerializableDict (ProcessId, k1, v1))
111+ => Static (SerializableDict (k1, v1))
120112 -> Static (SerializableDict [(k2, v2)])
121113 -> Closure (MapReduce k1 v1 k2 v2 v3)
122114 -> [NodeId]
@@ -125,8 +117,8 @@ distrMapReduce :: forall k1 k2 v1 v2 v3 a.
125117distrMapReduce dictIn dictOut mr mappers p = do
126118 mr' <- unClosure mr
127119 us <- getSelfPid
128− queue <- liftIO $ Chan.newChan
129− slavesTerminated <- liftIO $ newEmptyMVar
120+ queue <- liftIO Chan.newChan
121+ slavesTerminated <- liftIO newEmptyMVar
130122
131123 workQueue <- spawnLocal $ do
132124 let go :: Process ()
@@ -136,18 +128,18 @@ distrMapReduce dictIn dictOut mr mappers p = do
136128 Just (key, val) -> do
137129 -- As long there is work, make it available to the mappers
138130 them <- expect
139− send them (us, key, val)
131+ send them (key, val)
140132 go
141133 Nothing -> do
142134 -- Tell the mappers to terminate
143− replicateM (length mappers) $ do
135+ replicateM_ (length mappers) $ do
144136 them <- expect
145137 send them ()
146138 liftIO $ putMVar slavesTerminated ()
147139 go
148140
149141 -- Start the mappers
150− forM_ mappers $ flip spawn (mapperProcessClosure dictIn dictOut mr workQueue)
142+ forM_ mappers $ \nid -> spawn nid (mapperProcessClosure dictIn dictOut mr us workQueue)
151143
152144 let iteration :: Map k1 v1 -> Process (Map k2 v3)
153145 iteration input = do
distributed-process-demos/src/MasterSlave/MasterSlave.hs+1−1
@@ -24,7 +24,7 @@ master n slaves = do
2424 spawn them ($(mkClosure 'slave) (us, m))
2525
2626 -- Wait for the result
27− partials <- replicateM (fromInteger n) (expect :: Process Integer)
27+ partials <- replicateM (fromIntegral n) (expect :: Process Integer)
2828
2929 -- And return the sum
3030 return (sum partials)
distributed-process-demos/src/WorkPushing/WorkPushing.hs+7−8
@@ -10,10 +10,10 @@ fib = go (0, 1)
1010 go (!a, !b) !n | n == 0 = a
1111 | otherwise = go (b, a + b) (n - 1)
1212
13−slave :: () -> Process ()
14−slave () = forever $ do
15− (pid, n) <- expect
16− send pid (fib n)
13+slave :: ProcessId -> Process ()
14+slave them = forever $ do
15+ n <- expect
16+ send them (fib n)
1717
1818remotable ['slave]
1919
@@ -22,14 +22,13 @@ master n slaves = do
2222 us <- getSelfPid
2323
2424 -- Start processes on the slaves that compute Fibonacci numbers
25− slaveProcesses <- forM slaves $ flip spawn ($(mkClosure 'slave) ())
25+ slaveProcesses <- forM slaves $ \nid -> spawn nid ($(mkClosure 'slave) us)
2626
2727 -- Distribute 1 .. n amongst the slave processes
28− forM_ (zip [1 .. n] (cycle slaveProcesses)) $ \(m, them) ->
29− send them (us, m)
28+ forM_ (zip [1 .. n] (cycle slaveProcesses)) $ \(m, them) -> send them m
3029
3130 -- Wait for the result
32− partials <- replicateM (fromInteger n) (expect :: Process Integer)
31+ partials <- replicateM (fromIntegral n) (expect :: Process Integer)
3332
3433 -- And return the sum
3534 return (sum partials)
distributed-process-demos/src/WorkStealing/WorkStealing.hs+9−14
@@ -10,8 +10,8 @@ fib = go (0, 1)
1010 go (!a, !b) !n | n == 0 = a
1111 | otherwise = go (b, a + b) (n - 1)
1212
13−slave :: ProcessId -> Process ()
14−slave workQueue = do
13+slave :: (ProcessId, ProcessId) -> Process ()
14+slave (master, workQueue) = do
1515 us <- getSelfPid
1616 go us
1717 where
@@ -19,17 +19,12 @@ slave workQueue = do
1919 -- Ask the queue for work
2020 send workQueue us
2121
22− -- Wait for a reply
23− mWork <- receiveWait
24− [ match $ \(pid, n) -> return $ Just (pid, n)
25− , match $ \() -> return Nothing
22+ -- If there is work, do it, otherwise terminate
23+ receiveWait
24+ [ match $ \n -> send master (fib n) >> go us
25+ , match $ \() -> return ()
2626 ]
2727
28− -- If there is work, do it and repeat; otherwise, exit
29− case mWork of
30− Just (pid, n) -> send pid (fib n) >> go us
31− Nothing -> return ()
32−
3328remotable ['slave]
3429
3530master :: Integer -> [NodeId] -> Process Integer
@@ -40,7 +35,7 @@ master n slaves = do
4035 -- As long as there is work, return the next Fib to compute
4136 forM_ [1 .. n] $ \m -> do
4237 them <- expect
43− send them (us, m)
38+ send them m
4439
4540 -- After that, just report that the work is done
4641 forever $ do
@@ -48,10 +43,10 @@ master n slaves = do
4843 send pid ()
4944
5045 -- Start processes on the slaves that compute Fibonacci numbers
51− forM_ slaves $ flip spawn ($(mkClosure 'slave) workQueue)
46+ forM_ slaves $ \nid -> spawn nid ($(mkClosure 'slave) (us, workQueue))
5247
5348 -- Wait for the result
54− partials <- replicateM (fromInteger n) (expect :: Process Integer)
49+ partials <- replicateM (fromIntegral n) (expect :: Process Integer)
5550
5651 -- And return the sum
5752 return (sum partials)