@@ -15,14 +15,13 @@ import Data.ByteString.Lazy (ByteString)
15import Data.Map (Map)
15import Data.Map (Map)
16import qualified Data.Map as Map (mapWithKey, fromListWith, toList, size)
16import qualified Data.Map as Map (mapWithKey, fromListWith, toList, size)
17import Control.Arrow (second)
17import Control.Arrow (second)
18−import Control.Monad (forM_, forever, replicateM)
18+import Control.Monad (forM_, replicateM, replicateM_)
19import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
19import Control.Concurrent.MVar (newEmptyMVar, takeMVar, putMVar)
20import qualified Control.Concurrent.Chan as Chan
20import qualified Control.Concurrent.Chan as Chan
21import Control.Distributed.Process
21import Control.Distributed.Process
22import Control.Distributed.Process.Serializable (Serializable)
22import Control.Distributed.Process.Serializable (Serializable)
23import Control.Distributed.Process.Closure
23import Control.Distributed.Process.Closure
24import Control.Distributed.Static (closureApply, staticCompose, staticApply)
24import Control.Distributed.Static (closureApply, staticCompose, staticApply)
25−import Control.Concurrent (threadDelay)
27--------------------------------------------------------------------------------
26--------------------------------------------------------------------------------
28-- Definition of a MapReduce skeleton and a local implementation --
27-- Definition of a MapReduce skeleton and a local implementation --
@@ -64,59 +63,52 @@ matchDict SerializableDict = match
64sendDict :: forall a. SerializableDict a -> ProcessId -> a -> Process ()
63sendDict :: forall a. SerializableDict a -> ProcessId -> a -> Process ()
65sendDict SerializableDict = send
64sendDict SerializableDict = send
66+sdictProcessIdPair :: SerializableDict (ProcessId, ProcessId)
67+sdictProcessIdPair = SerializableDict
67mapperProcess :: forall k1 v1 k2 v2 v3.
69mapperProcess :: forall k1 v1 k2 v2 v3.
68− SerializableDict (ProcessId, k1, v1)
70+ SerializableDict (k1, v1)
69 -> SerializableDict [(k2, v2)]
71 -> SerializableDict [(k2, v2)]
70− -> ProcessId
72+ -> (ProcessId, ProcessId)
71 -> MapReduce k1 v1 k2 v2 v3
73 -> MapReduce k1 v1 k2 v2 v3
72 -> Process ()
74 -> Process ()
73−mapperProcess dictIn dictOut workQueue mr = do
75+mapperProcess dictIn dictOut (master, workQueue) mr = getSelfPid >>= go
75− liftIO . putStrLn $ "Mapper " ++ show us ++ " started"
78 go us = do
77 go us = do
79 -- Ask the queue for work
78 -- Ask the queue for work
80 send workQueue us
79 send workQueue us
82− liftIO . putStrLn $ "Mapper " ++ show us ++ " waiting for work"
83− -- Wait for a reply
81+ -- Wait for a reply; if there is work, do it and repeat; otherwise, exit
84− mWork <- receiveWait
82+ receiveWait
85− [ matchDict dictIn $ \(pid, key, val) -> return $ Just (pid, key, val)
83+ [ matchDict dictIn $ \(key, val) -> do
84+ sendDict dictOut master (mrMap mr key val)
86− , match $ \() -> return Nothing
87+ return ()
89− -- If there is work, do it and repeat; otherwise, exit
91− Just (pid, key, val) -> do
92− sendDict dictOut pid (mrMap mr key val)
96− liftIO $ putStrLn "Slave exiting"
99−remotable ['mapperProcess]
90+remotable ['mapperProcess, 'sdictProcessIdPair]
101mapperProcessClosure :: forall k1 v1 k2 v2 v3.
92mapperProcessClosure :: forall k1 v1 k2 v2 v3.
102 (Typeable k1, Typeable v1, Typeable k2, Typeable v2, Typeable v3)
93 (Typeable k1, Typeable v1, Typeable k2, Typeable v2, Typeable v3)
103− => Static (SerializableDict (ProcessId, k1, v1))
94+ => Static (SerializableDict (k1, v1))
104 -> Static (SerializableDict [(k2, v2)])
95 -> Static (SerializableDict [(k2, v2)])
105 -> Closure (MapReduce k1 v1 k2 v2 v3)
96 -> Closure (MapReduce k1 v1 k2 v2 v3)
106 -> ProcessId
97 -> ProcessId
107 -> Closure (Process ())
99 -> Closure (Process ())
108−mapperProcessClosure dictIn dictOut mr pid =
100+mapperProcessClosure dictIn dictOut mr master workQueue =
109− closure decoder (encode pid) `closureApply` mr
101+ closure decoder (encode (master, workQueue)) `closureApply` mr
111 decoder :: Static (ByteString -> MapReduce k1 v1 k2 v2 v3 -> Process ())
103 decoder :: Static (ByteString -> MapReduce k1 v1 k2 v2 v3 -> Process ())
112 decoder =
104 decoder =
113 ($(mkStatic 'mapperProcess) `staticApply` dictIn `staticApply` dictOut)
105 ($(mkStatic 'mapperProcess) `staticApply` dictIn `staticApply` dictOut)
114 `staticCompose`
106 `staticCompose`
115− staticDecode sdictProcessId
107+ staticDecode $(mkStatic 'sdictProcessIdPair)
117distrMapReduce :: forall k1 k2 v1 v2 v3 a.
109distrMapReduce :: forall k1 k2 v1 v2 v3 a.
118 (Serializable k1, Serializable v1, Serializable k2, Serializable v2, Serializable v3, Ord k2)
110 (Serializable k1, Serializable v1, Serializable k2, Serializable v2, Serializable v3, Ord k2)
119− => Static (SerializableDict (ProcessId, k1, v1))
111+ => Static (SerializableDict (k1, v1))
120 -> Static (SerializableDict [(k2, v2)])
112 -> Static (SerializableDict [(k2, v2)])
121 -> Closure (MapReduce k1 v1 k2 v2 v3)
113 -> Closure (MapReduce k1 v1 k2 v2 v3)
122 -> [NodeId]
114 -> [NodeId]
@@ -125,8 +117,8 @@ distrMapReduce :: forall k1 k2 v1 v2 v3 a.
125distrMapReduce dictIn dictOut mr mappers p = do
117distrMapReduce dictIn dictOut mr mappers p = do
126 mr' <- unClosure mr
118 mr' <- unClosure mr
127 us <- getSelfPid
119 us <- getSelfPid
128− queue <- liftIO $ Chan.newChan
120+ queue <- liftIO Chan.newChan
129− slavesTerminated <- liftIO $ newEmptyMVar
121+ slavesTerminated <- liftIO newEmptyMVar
131 workQueue <- spawnLocal $ do
123 workQueue <- spawnLocal $ do
132 let go :: Process ()
124 let go :: Process ()
@@ -136,18 +128,18 @@ distrMapReduce dictIn dictOut mr mappers p = do
136 Just (key, val) -> do
128 Just (key, val) -> do
137 -- As long there is work, make it available to the mappers
129 -- As long there is work, make it available to the mappers
138 them <- expect
130 them <- expect
139− send them (us, key, val)
131+ send them (key, val)
141 Nothing -> do
133 Nothing -> do
142 -- Tell the mappers to terminate
134 -- Tell the mappers to terminate
143− replicateM (length mappers) $ do
135+ replicateM_ (length mappers) $ do
144 them <- expect
136 them <- expect
145 send them ()
137 send them ()
146 liftIO $ putMVar slavesTerminated ()
138 liftIO $ putMVar slavesTerminated ()
149 -- Start the mappers
141 -- 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)
152 let iteration :: Map k1 v1 -> Process (Map k2 v3)
144 let iteration :: Map k1 v1 -> Process (Map k2 v3)
153 iteration input = do
145 iteration input = do