{- Rekursive Berechnung von Binomialkoeffizienten Parallelisiert mit par und pseq Beispiel aus Vorlesung "Parallelität in Funktionalen Sprachen" Prof. Dr. Rita Loogen, Philipps-Universitaet Marburg Sommersemester 2009 Kompilieren mit Option -threaded für paralleles RTS, Aufruf mit Option +RTS -Nn (wobei n die Anzahl der gewünschten Kerne angibt) Beispielparameter: 50 7 2 2, 30 10 2 4 (n k tiefe iterationszahl) -} module Main where import System.Environment (getArgs) import Data.Time.Clock (diffUTCTime, getCurrentTime) import Control.Parallel (par,pseq) -- einfach parallele Version binom :: Integer -> Integer -> Integer binom n k | k == 0 && n >= 0 = 1 | n < k && n >= 0 = 0 | k <= n && k >= 0 = b1 `par` b2 `pseq` b1 + b2 | otherwise = error "negative parameters" where b1 = binom (n-1) k b2 = binom (n-1) (k-1) -- sequentielle Version sbinom :: Integer -> Integer -> Integer sbinom n k | k == 0 && n >= 0 = 1 | n < k && n >= 0 = 0 | k <= n && k >= 0 = b1 + b2 | otherwise = error "negative parameters" where b1 = sbinom (n-1) k b2 = sbinom (n-1) (k-1) -- parallele Version mit Tiefenkontrolle dbinom :: Int -> Integer -> Integer -> Integer dbinom d n k | d <= 0 = sbinom n k | k == 0 && n >= 0 = 1 | n < k && n >= 0 = 0 | k <= n && k >= 0 = b1 `par` b2 `pseq` b1 + b2 | otherwise = error "negative parameters" where b1 = dbinom (d-1) (n-1) k b2 = dbinom (d-1) (n-1) (k-1) -- Hauptprogramm (Testumgebung) main :: IO () main = do args <- getArgs if length args < 4 then putStrLn "Parameters: n k depth numiter" else do let n = read (head args) let k = read (head (tail args)) let d = read (head (tail (tail args))) let nr = read (head (tail (tail (tail args)))) putStrLn $ "Parameters: n = " ++ show n ++ ", k = " ++ show k ++ ", depth = " ++ show d start <- getCurrentTime let result = my_iterate_depth nr n k d putStrLn ("Result: " ++ (show result)) end <- getCurrentTime putStrLn (show (end `diffUTCTime` start) ++ " elapsed." ) my_iterate_depth :: Int -> Integer -> Integer -> Int -> Integer my_iterate_depth nr n k d | nr == 1 = dbinom d n k | nr > 1 = dbinom d n k `pseq` my_iterate_depth (nr-1) n k d | otherwise = error "negative parameter"