Links und Funktionen
Sprachumschaltung

Navigationspfad
Sie sind hier: Startseite / Lehre / SS 2015 / Programmierung und Modellierung / ProMo Material / Code Vorlesung 25.06.


Inhaltsbereich

Code Vorlesung 25.06.

Beispiel zur Anwendung der Par-Monade. Vier aufwendige Aufgaben in exakt gleicher Größe werden zur Beschleunigung der gesamten Berechnung auf 4 Prozessorkerne verteilt.

Haskell source code icon parHanoi.hs — Haskell source code, 4 KB (5089 bytes)

Dateiinhalt

-------------------------------------------------------------
-- Code aus der Vorlesung "Programmierung und Modellierung"
-- am 25.06.2015 an der LMU München
-- verfasst von Steffen Jost
--
-- Simples Beispiel zur Anwendung der Par-Monade

import Control.Monad
import Control.Monad.Par
-- import Control.Applicative


main :: IO ()
main = do -- gewünschte Version durch auskommentieren wählen
  -- mainSequentiell  -- original, alles der Reihe nach
  -- mainParMonade1   -- live codiert, parallel
  mainParMonade2   -- nachträglich aufgehübscht

difficulty  = 25 -- ändern, falls Laufzeit zu lang oder zu kurz ist

{----------------------------------------------------------------------------
---- MESSUNGEN MIT DIFFICULTY 25 AUF 4-Kern Maschine ----

-- 1) SEQUENTIELLE VERSION:
> ghc parHanoi.hs -O2

> time ./parHanoi
real    0m17.089s
user    0m16.993s
sys     0m0.114s


-- 2) VERSION: mainParMonade1
> ghc parHanoi.hs -O2 -threaded -rtsopts

-- Mit 1 aktiven Kern durch Par-Monade etwas langsamer:
> time ./parHanoi +RTS -N1
real    0m18.269s
user    0m18.152s
sys     0m0.155s

-- Mit 2 aktiven Kernen Speedup Faktor 1.66, ganz ok!
> time ./parHanoi +RTS -N2
real    0m10.179s  -- tatsächlich verstrichene Zeit
user    0m18.871s  -- Summe der Rechenzeit aller Kerne
sys     0m1.508s

-- Mit 4 aktiven Kernen Speedup Faktor 3, ganz ok!
> time ./parHanoi +RTS -N4
real    0m5.416s   -- tatsächlich verstrichene Zeit
user    0m18.776s  -- Summe der Rechenzeit aller Kerne
sys     0m2.753s

-- Mit 6 aktiven Kernen Speedup Faktor nur noch 2.48, bringt also nix mehr!
> time ./parHanoi +RTS -N6
real    0m6.879s
user    0m24.705s -- Verwaltung steigt
sys     0m9.951s


-- 2) VERSION: mainParMonade2

-- Vergleichbar mit der ersten Version.
> time ./parHanoi +RTS -N4
real    0m5.344s
user    0m18.573s
sys     0m2.702s

----------------------------------------------------------------------------}

mainSequentiell :: IO ()
mainSequentiell = do
  putStrLn "SEQUENTIELLE VERSION"
  putStrLn "Wusstest Du schon:"
  let t1 = length $ hanoi difficulty 1 2
  let t2 = length $ hanoi difficulty 1 3
  let t3 = length $ hanoi difficulty 2 3
  let t4 = length $ hanoi difficulty 3 1
  putStrLn $ "Man braucht " ++ (show t1) ++ " Schritte um einen Hanoi-Turm der Größe "
    ++ (show difficulty) ++ " von Platz 1 auf Platz 2 zu versetzen."
  putStrLn $ "Man braucht " ++ (show t2) ++ " Schritte um einen Hanoi-Turm der Größe "
    ++ (show difficulty) ++ " von Platz 1 auf Platz 3 zu versetzen."
  putStrLn $ "Man braucht " ++ (show t3) ++ " Schritte um einen Hanoi-Turm der Größe "
    ++ (show difficulty) ++ " von Platz 2 auf Platz 3 zu versetzen."
  putStrLn $ "Man braucht " ++ (show t4) ++ " Schritte um einen Hanoi-Turm der Größe "
    ++ (show difficulty) ++ " von Platz 3 auf Platz 1 zu versetzen."
  putStrLn "Gut zu wissen, oder?"
-- Hilfsfunktionen, zur Erzeugung von Rechnenlast:


mainParMonade1 :: IO ()
mainParMonade1 = do
  putStrLn "VERSION: mainParMonade1"
  putStrLn "Wusstest Du schon:"
  let t1 = length $ hanoi difficulty 1 2
  let t2 = length $ hanoi difficulty 1 3
  let t3 = length $ hanoi difficulty 2 3
  let t4 = length $ hanoi difficulty 3 1
  (t1,t2,t3,t4) <- runParIO $ do
        v1 <- new
        v2 <- new
        v3 <- new
        v4 <- new
        fork $ put v1 t1
        fork $ put v2 t2
        fork $ put v3 t3
        fork $ put v4 t4
        r1 <- get v1
        r2 <- get v2
        r3 <- get v3 
        r4 <- get v4
        return (r1,r2,r3,r4)
  putStrLn $ "Man braucht " ++ (show t1) ++ " Schritte um einen Hanoi-Turm der Größe "
    ++ (show difficulty) ++ " von Platz 1 auf Platz 2 zu versetzen."
  putStrLn $ "Man braucht " ++ (show t2) ++ " Schritte um einen Hanoi-Turm der Größe "
    ++ (show difficulty) ++ " von Platz 1 auf Platz 3 zu versetzen."
  putStrLn $ "Man braucht " ++ (show t3) ++ " Schritte um einen Hanoi-Turm der Größe "
    ++ (show difficulty) ++ " von Platz 2 auf Platz 3 zu versetzen."
  putStrLn $ "Man braucht " ++ (show t4) ++ " Schritte um einen Hanoi-Turm der Größe "
    ++ (show difficulty) ++ " von Platz 3 auf Platz 1 zu versetzen."
  putStrLn "Gut zu wissen, oder?"


mainParMonade2 :: IO ()
mainParMonade2 = do
  putStrLn "VERSION: mainParMonade2"
  putStrLn "Wusstest Du schon:"
  let tasks = take 4 [htask x y | x <- [1..3], y <-[1..3], x/=y ]
  outputs <- runParIO $ do
                pcs <- mapM spawnP tasks
                mapM get pcs
  mapM_ putStrLn outputs
  putStrLn "Gut zu wissen, oder?"
  where
    htask start end =
      "Man braucht " ++ (show $ length $ hanoi difficulty start end)
      ++ " Schritte um einen Hanoi-Turm der Größe "++ (show difficulty)
      ++ " von Platz " ++ show start
      ++ " auf Platz " ++ show end ++ " zu versetzen."


----------------------------------------------------
-- Hilfsfunktionen, zur Erzeugung von etwas Rechnenlast:

hanoi :: Int -> Int -> Int -> [(Int,Int)]
hanoi 1 i j = [(i,j)]
hanoi n i j =
       hanoi n' i otherTower
    ++ [(i,j)]
    ++ hanoi n' otherTower j
  where
    n'         = n-1
    otherTower = 1+2+3-i-j

Artikelaktionen


Funktionsleiste