我遇到了問題,使我的代碼並行運行。這是一個3D Delaunay生成器,使用分割&征服算法,命名爲DeWall。分而治之算法的並行性
主要功能是:
deWall::[SimplexPointer] -> SetSimplexFace -> Box -> StateT DeWallSets IO ([Simplex], [Edge])
deWall p afl box = do
...
...
get >>= recursion box1 box2 p1 p2 sigma edges
...
...
它調用可以稱之爲dewall功能背面的「遞歸」功能。在這裏,平滑機會出現在這裏。以下代碼顯示了順序解決方案。
recursion::Box -> Box -> [SimplexPointer] -> [SimplexPointer] -> [Simplex] -> [Edge] -> DeWallSets -> StateT DeWallSets IO ([Simplex], [Edge])
recursion box1 box2 p1 p2 sigma edges deWallSet
| null afl1 && null afl2 = return (sigma, edges)
| (null) afl1 = do
(s, e) <- deWall p2 afl2 box2
return (s ++ sigma, e ++ edges)
| (null) afl2 = do
(s,e) <- deWall p1 afl1 box1
return (s ++ sigma, e ++ edges)
| otherwise = do
x <- get
liftIO $ do
(s1, e1) <- evalStateT (deWall p1 afl1 box1) x
(s2, e2) <- evalStateT (deWall p2 afl2 box2) x
return (s1 ++ s2 ++ sigma, e1 ++ e2 ++ edges)
where afl1 = aflBox1 deWallSet
afl2 = aflBox2 deWallSet
狀態和IO monads用於管道狀態併爲使用MVar發現的每個四面體生成UID。我的第一次嘗試是添加一個forkIO,但它不起作用。由於合併過程中缺乏控制,不會等待兩個線程完成,因此它會給出錯誤的輸出。我不知道如何讓它等待它們。
liftIO $ do
let
s1 = evalStateT (deWall p1 afl1 box1) x
s2 = evalStateT (deWall p2 afl2 box2) x
concatThread var (a1, b1) = takeMVar var >>= \(a2, b2) -> putMVar var (a1 ++ a2, b1 ++ b2)
mv <- newMVar ([],[])
forkIO (s1 >>= concatThread mv)
forkIO (s2 >>= concatThread mv)
takeMVar mv >>= \(s, e) -> return (s ++ sigma, e ++ edges)
所以,我的下一個嘗試是使用一個更好的並行策略「相提並論」和「PSEQ」這給正確的結果,但根據threadScope沒有並行執行。
liftIO $ do
let
s1 = evalStateT (deWall p1 afl1 box1) x
s2 = evalStateT (deWall p2 afl2 box2) x
conc = liftM2 (\(a1, b1) (a2, b2) -> (a1 ++ a2, b1 ++ b2))
(stotal, etotal) = s1 `par` (s2 `pseq` (s1 `conc` s2))
return (stotal ++ sigma, etotal ++ edges)
我在做什麼錯?
UPDATE:不知何故,這個問題似乎與IO單子的存在有關。在沒有IO monad的其他(舊)版本中,只有狀態monad,並行執行以'par'
和'pseq'
運行。 GHC -sstderr給出SPARKS: 1160 (69 converted, 1069 pruned)
。
recursion::Box -> Box -> [SimplexPointer] -> [SimplexPointer] -> [Simplex] -> [Edge] -> DeWallSets -> State DeWallSets ([Simplex], [Edge])
recursion p1 p2 sigma deWallSet
| null afl1 && null afl2 = return sigma
| (null) afl1 = do
s <- deWall p2 afl2 box2
return (s ++ sigma)
| (null) afl2 = do
s <- deWall p1 afl1 box1
return (s ++ sigma)
| otherwise = do
x <- get
let s1 = evalState (deWall p1 afl1 box1) x
let s2 = evalState (deWall p2 afl2 box2) x
return $ s1 `par` (s2 `pseq` (s1 ++ s2 ++ sigma))
where afl1 = aflBox1 deWallSet
afl2 = aflBox2 deWallSet
雲有人解釋說?
假設您使用GHC,您應該在使用`!`使字段嚴格之前添加`{ - #LANGUAGE BangPatterns# - }`編譯指示。 – dvitek 2011-02-07 13:08:58
@drvitek:不,「BangPatterns」僅用於嚴格模式匹配,不適用於嚴格的數據類型註釋。 – nominolo 2011-02-07 13:24:21
感謝球員的評論。我試圖給我的代碼添加嚴格性,但沒有結果(GHC -sstderr給出'SPARKS:1080(0轉換,0修剪)')。這似乎與IO monad存在有關。查看我的問題中的更新。 – LambdaStaal 2011-02-09 15:55:52