initial exercise
This commit is contained in:
commit
e74be4aaff
20
.gitignore
vendored
Normal file
20
.gitignore
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
dist
|
||||||
|
dist-*
|
||||||
|
cabal-dev
|
||||||
|
*.o
|
||||||
|
*.hi
|
||||||
|
*.chi
|
||||||
|
*.chs.h
|
||||||
|
*.dyn_o
|
||||||
|
*.dyn_hi
|
||||||
|
.hpc
|
||||||
|
.hsenv
|
||||||
|
.cabal-sandbox/
|
||||||
|
cabal.sandbox.config
|
||||||
|
*.prof
|
||||||
|
*.aux
|
||||||
|
*.hp
|
||||||
|
*.eventlog
|
||||||
|
.stack-work/
|
||||||
|
cabal.project.local
|
||||||
|
*~
|
41
.travis.yml
Normal file
41
.travis.yml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# This is the simple Travis configuration, which is intended for use
|
||||||
|
# on applications which do not require cross-platform and
|
||||||
|
# multiple-GHC-version support. For more information and other
|
||||||
|
# options, see:
|
||||||
|
#
|
||||||
|
# https://docs.haskellstack.org/en/stable/travis_ci/
|
||||||
|
#
|
||||||
|
# Copy these contents into the root directory of your Github project in a file
|
||||||
|
# named .travis.yml
|
||||||
|
|
||||||
|
# Use new container infrastructure to enable caching
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
# Do not choose a language; we provide our own build tools.
|
||||||
|
language: generic
|
||||||
|
|
||||||
|
# Caching so the next build will be fast too.
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.stack
|
||||||
|
|
||||||
|
# Ensure necessary system libraries are present
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- libgmp-dev
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
# Download and unpack the stack executable
|
||||||
|
- mkdir -p ~/.local/bin
|
||||||
|
- export PATH=$HOME/.local/bin:$PATH
|
||||||
|
- travis_retry curl -L https://www.stackage.org/stack/linux-x86_64 | tar xz --wildcards --strip-components=1 -C ~/.local/bin '*/stack'
|
||||||
|
|
||||||
|
install:
|
||||||
|
# Build dependencies
|
||||||
|
- stack --no-terminal --install-ghc test --only-dependencies
|
||||||
|
|
||||||
|
script:
|
||||||
|
# Build the package, its tests, and its docs and run the tests
|
||||||
|
- stack --no-terminal test --haddock --no-haddock-deps
|
||||||
|
|
30
LICENSE
Normal file
30
LICENSE
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
Copyright Author name here (c) 2017
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of Author name here nor the names of other
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
83
README.md
Normal file
83
README.md
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
Übungszettel 10
|
||||||
|
==============
|
||||||
|
|
||||||
|
Parallelismus & Nebenläufigkeit
|
||||||
|
|
||||||
|
Issue 1
|
||||||
|
-------
|
||||||
|
|
||||||
|
Im Modul `Parallel` finden Sie eine Funktion, die Sie noch von Zettel 3 kennen.
|
||||||
|
Zur Erinnerung: Die Funktion `nBesteEingaben` gibt Ihnen mit beliebiger numerischer Genauigkeit
|
||||||
|
diejenigen Eingaben (4-Tupel, jeweils mit Werten aus [-10,10]) zurück, für die eine
|
||||||
|
`komlizierteFunktion` maximal wird. Hierfür wird der komplizierten Funktion mithilfe von
|
||||||
|
List-Applicative (kartesisches Produkt) eine lange, beliebig dichte Liste möglicher Eingabewerte
|
||||||
|
zwischen `(-10,-10,-10,-10)` und `(10,10,10,10)` übergeben. Bei einem Abstand von 0.5 ergeben sich
|
||||||
|
damit 41^4 = 2 825 761 Berechnungen. Diese lohnt es sich zu parallelisieren.
|
||||||
|
|
||||||
|
Parallelisieren Sie die Funktion `nBesteEingaben`, mit mindestens drei verschiedenen Strategien für Listen aus
|
||||||
|
[`Control.Parallel.Strategies`](https://hackage.haskell.org/package/parallel-3.2.1.1/docs/Control-Parallel-Strategies.html#v:evalList).
|
||||||
|
|
||||||
|
Um ihre Parallelisierung zu testen, verwenden Sie die folgenden Terminalbefehle:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
stack exec -- MainParallel1 +RTS -N1 -s
|
||||||
|
stack exec -- MainParallel1 +RTS -N2 -s
|
||||||
|
stack exec -- MainParallel1 +RTS -N4 -s
|
||||||
|
stack exec -- MainParallel1 +RTS -N8 -s
|
||||||
|
```
|
||||||
|
`-Nx` steht hierbei für die Verwendung von x Kernen.
|
||||||
|
|
||||||
|
Eine sinnvolle Parallelisierung erkennen Sie daran, dass die Berechnung schneller wird,
|
||||||
|
je mehr echte Kerne Sie für zur Verfügung stellen.
|
||||||
|
|
||||||
|
Notieren sie die Laufzeiten ihrer Versuche in einer Tabelle und geben sie den Speedup (`-N1`-Zeit/`-Nx`Zeit) an.
|
||||||
|
|
||||||
|
Issue 2
|
||||||
|
-------
|
||||||
|
|
||||||
|
Sie werden bemerkt haben, dass der Speedup sich nicht linear mit der Anzahl der Kerne steigern lässt.
|
||||||
|
Nach [Amdahls Gesetz](https://de.wikipedia.org/wiki/Amdahlsches_Gesetz) ist bei vielen Kernen der nicht-parallelisierte Part
|
||||||
|
(in unserem Fall das sortieren) für die schlechte Performance verantwortlich.
|
||||||
|
|
||||||
|
Da wir uns nur für die Top `n` eingaben interessieren, schreiben sie eine Funktion
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
topn :: Int -> [a] -> [a]
|
||||||
|
```
|
||||||
|
|
||||||
|
welche nach `n` Einsortierungsversuchen das zu sortierende Element verwirft (z.B. als Liste oder Array) und somit die Sortierung
|
||||||
|
frühestmöglich abbricht.
|
||||||
|
|
||||||
|
Füllen sie die Speedup-Tabelle erneut aus. Was ändert sich?
|
||||||
|
|
||||||
|
Issue 3
|
||||||
|
-------
|
||||||
|
|
||||||
|
Sie besitzen eine Bank und sollen Überweisungen programmieren. Sie finden in `Banking.hs` alles fertig. Nur noch die `debit`-Funktion muss geschrieben werden,
|
||||||
|
die von dem ersten auf das Zweite Konto überweist.
|
||||||
|
|
||||||
|
Im Szenario der Main-Funktionen hat die Bank 10 verschiedene Server, die gleichzeitig dieselbe Transaktion auf der Datenbank ausführen wollen
|
||||||
|
(also haben sie mehrere "Banken" in der Main, die auch alle etwas ausgeben, aber alle zeigen denselben Kontostand, da die Konten selbst nur 1x existieren).
|
||||||
|
|
||||||
|
Führen sie anschließend MainBanking1 und MainBanking2 aus. Was können sie beobachten? Wie kommt es zu den Ergebnissen?
|
||||||
|
|
||||||
|
Hint (optional!): Mittels `stack exec -- MainBanking1 +RTS -ls` können sie ein eventlog ausgeben lassen, welches sie mittels `threadscope` (`stack install threadscope`) ansehen können.
|
||||||
|
|
||||||
|
Was passiert, wenn sie dies mit `-N1` ausführen? Wieso?
|
||||||
|
|
||||||
|
Issue 4
|
||||||
|
-------
|
||||||
|
|
||||||
|
Da sie in Aufgabe 3 in Probleme gelaufen sind (sind sie doch, oder? ;) ), benutzen sie hier statt `MVar`s die STM-eigenen `TMVar`s.
|
||||||
|
|
||||||
|
In `STMBanking.hs` finden sie die gleiche Situation vor - nur müssen sie hier mit `STM` statt mit `MVar` arbeiten.
|
||||||
|
|
||||||
|
Führen sie anschließend MainSTMBanking1 und MainSTMBanking2 aus. Was können sie beobachten? Inwiefern unterscheiden sich die Ergebnisse zu den `MVar`s?
|
||||||
|
|
||||||
|
Hint (optional!): Mittels `stack exec -- MainBanking1 +RTS -ls` können sie ein eventlog ausgeben lassen, welches sie mittels `threadscope` (`stack install threadscope`) ansehen können.
|
||||||
|
|
||||||
|
Was passiert, wenn sie dies mit `-N1` ausführen? Wieso?
|
||||||
|
|
||||||
|
Wo sind die Unterschiede zu `MVar`s (Performance, Einfachheit der Programmierung, Resistenz gegen Programmierfehler, ..)? Beschreiben sie kurz wie sich ihre Probleme mit
|
||||||
|
der jeweiligen Implementation anfühlten und wieso sie welche Lösung selbst bevorzugen würden.
|
||||||
|
|
24
app/MainBanking1.hs
Normal file
24
app/MainBanking1.hs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import qualified Control.Concurrent.Thread as Thread ( forkIO, result )
|
||||||
|
import Control.Concurrent.MVar
|
||||||
|
import Control.Monad
|
||||||
|
import Data.Time.Clock
|
||||||
|
|
||||||
|
import Banking
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
start <- getCurrentTime
|
||||||
|
bank <- setup
|
||||||
|
-- start 10 threads doing 10000 treansactions each
|
||||||
|
threads <- sequence $ Thread.forkIO <$> replicate 10 (foldr1 (>=>) (replicate 10000 testTransaction1) bank)
|
||||||
|
banks <- sequence $ (\(_,w) -> w >>= Thread.result) <$> threads
|
||||||
|
stop <- getCurrentTime
|
||||||
|
printBanks banks
|
||||||
|
print $ "Time taken: " ++ (show $ diffUTCTime stop start)
|
||||||
|
printBanks :: [Bank] -> IO ()
|
||||||
|
printBanks (a:as) = do
|
||||||
|
sequence_ $ (readMVar >=> print) <$> a
|
||||||
|
printBanks [] = return ()
|
||||||
|
|
26
app/MainBanking2.hs
Normal file
26
app/MainBanking2.hs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import qualified Control.Concurrent.Thread as Thread ( forkIO, result )
|
||||||
|
import Control.Concurrent.MVar
|
||||||
|
import Control.Monad
|
||||||
|
import Data.Time.Clock
|
||||||
|
|
||||||
|
import Banking
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
start <- getCurrentTime
|
||||||
|
bank <- setup
|
||||||
|
bank' <- newMVar bank
|
||||||
|
-- start 10 threads doing 10000 treansactions each
|
||||||
|
threads <- sequence $ Thread.forkIO <$> replicate 10 (foldr1 (>=>) (replicate 10000 testTransaction2) bank')
|
||||||
|
banks <- sequence $ (\(_,w) -> w >>= Thread.result) <$> threads
|
||||||
|
stop <- getCurrentTime
|
||||||
|
printMBanks banks
|
||||||
|
print $ "Time taken: " ++ (show $ diffUTCTime stop start)
|
||||||
|
|
||||||
|
printMBanks :: [MVar Bank] -> IO ()
|
||||||
|
printMBanks (a:as) = do
|
||||||
|
a' <- readMVar a
|
||||||
|
sequence_ $ (readMVar >=> print) <$> a'
|
||||||
|
printMBanks [] = return ()
|
6
app/MainParallel1.hs
Normal file
6
app/MainParallel1.hs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import Parallel
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = putStr strategy1
|
6
app/MainParallel2.hs
Normal file
6
app/MainParallel2.hs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import Parallel
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = putStr strategy2
|
6
app/MainParallel3.hs
Normal file
6
app/MainParallel3.hs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import Parallel
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = putStr strategy3
|
24
app/MainSTMBanking1.hs
Normal file
24
app/MainSTMBanking1.hs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import qualified Control.Concurrent.Thread as Thread ( forkIO, result )
|
||||||
|
import Control.Concurrent.STM
|
||||||
|
import Control.Monad
|
||||||
|
import Data.Time.Clock
|
||||||
|
|
||||||
|
import STMBanking
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
start <- getCurrentTime
|
||||||
|
bank <- setup
|
||||||
|
-- start 10 threads doing 10000 treansactions each
|
||||||
|
threads <- sequence $ Thread.forkIO <$> replicate 10 (foldr1 (>=>) (replicate 10000 testTransaction1) bank)
|
||||||
|
banks <- sequence $ (\(_,w) -> w >>= Thread.result) <$> threads
|
||||||
|
stop <- getCurrentTime
|
||||||
|
printBanks banks
|
||||||
|
print $ "Time taken: " ++ (show $ diffUTCTime stop start)
|
||||||
|
|
||||||
|
printBanks :: [Bank] -> IO ()
|
||||||
|
printBanks (a:as) = do
|
||||||
|
sequence_ $ ((atomically . readTMVar) >=> print) <$> a
|
||||||
|
printBanks [] = return ()
|
28
app/MainSTMBanking2.hs
Normal file
28
app/MainSTMBanking2.hs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
module Main where
|
||||||
|
|
||||||
|
import qualified Control.Concurrent.Thread as Thread ( forkIO, result )
|
||||||
|
import Control.Concurrent.STM
|
||||||
|
import Control.Monad
|
||||||
|
import Data.Time.Clock
|
||||||
|
|
||||||
|
import STMBanking
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = do
|
||||||
|
start <- getCurrentTime
|
||||||
|
bank <- setup
|
||||||
|
bank' <- newTMVarIO bank
|
||||||
|
-- start 10 threads doing 10000 treansactions each
|
||||||
|
threads <- sequence $ Thread.forkIO <$> replicate 10 (foldr1 (>=>) (replicate 10000 testTransaction2) bank')
|
||||||
|
banks <- sequence $ (\(_,w) -> w >>= Thread.result) <$> threads
|
||||||
|
stop <- getCurrentTime
|
||||||
|
printMBanks banks
|
||||||
|
print $ "Time taken: " ++ (show $ diffUTCTime stop start)
|
||||||
|
|
||||||
|
printMBanks :: [TMVar Bank] -> IO ()
|
||||||
|
printMBanks (a:as) = do
|
||||||
|
vals <- atomically $ do
|
||||||
|
a' <- readTMVar a
|
||||||
|
sequence $ readTMVar <$> a'
|
||||||
|
sequence_ $ print <$> vals
|
||||||
|
printMBanks [] = return ()
|
44
src/Banking.hs
Normal file
44
src/Banking.hs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
module Banking where
|
||||||
|
|
||||||
|
import Control.Concurrent.MVar
|
||||||
|
|
||||||
|
data Konto = Konto
|
||||||
|
{ cents :: Integer
|
||||||
|
, nummer :: Integer
|
||||||
|
}
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
type Bank = [MVar Konto]
|
||||||
|
|
||||||
|
kontoA :: Konto
|
||||||
|
kontoA = Konto 1000 1
|
||||||
|
kontoB :: Konto
|
||||||
|
kontoB = Konto 0 2
|
||||||
|
kontoC :: Konto
|
||||||
|
kontoC = Konto 2000 3
|
||||||
|
|
||||||
|
-- IMPLEMENTIEREN
|
||||||
|
debit :: Bank -> MVar Konto -> MVar Konto -> Integer -> IO Bank
|
||||||
|
debit b _ _ _ = return b
|
||||||
|
|
||||||
|
-- diese Transaktion überweist 1000 cent einmal reihum.
|
||||||
|
-- Danach hat jeder dasselbe Geld wie vorher - theoretisch!
|
||||||
|
testTransaction1 :: Bank -> IO Bank
|
||||||
|
testTransaction1 bank = do
|
||||||
|
bank <- debit bank (bank!!0) (bank!!1) 1000
|
||||||
|
bank <- debit bank (bank!!1) (bank!!2) 1000
|
||||||
|
debit bank (bank!!2) (bank!!0) 1000
|
||||||
|
|
||||||
|
-- Dieselbe Transaktion. Diesmal mit gelockter Bank.
|
||||||
|
testTransaction2 :: MVar Bank -> IO (MVar Bank)
|
||||||
|
testTransaction2 mb = do
|
||||||
|
bank <- takeMVar mb
|
||||||
|
bank <- debit bank (bank!!0) (bank!!1) 1000
|
||||||
|
bank <- debit bank (bank!!1) (bank!!2) 1000
|
||||||
|
bank <- debit bank (bank!!2) (bank!!0) 1000
|
||||||
|
putMVar mb bank
|
||||||
|
return mb
|
||||||
|
|
||||||
|
|
||||||
|
setup :: IO Bank
|
||||||
|
setup = sequence $ newMVar <$> [kontoA, kontoB, kontoC]
|
7
src/KomplizierteFunktion.hs
Normal file
7
src/KomplizierteFunktion.hs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module KomplizierteFunktion
|
||||||
|
( komplizierteFunktion
|
||||||
|
) where
|
||||||
|
|
||||||
|
{-# INLINE komplizierteFunktion #-}
|
||||||
|
|
||||||
|
komplizierteFunktion x y z w = 1/exp (abs (x- 2.3))^2 * sin( (y- 2.9))^2+cos( (0.4*z- 2.6))^5 *(2*z)^2-(2*z- 2.6)^2+ (25-log(abs (w- 0.6)+1))
|
44
src/Parallel.hs
Normal file
44
src/Parallel.hs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
module Parallel where
|
||||||
|
|
||||||
|
import Data.List
|
||||||
|
import Data.Array
|
||||||
|
import Data.Ord
|
||||||
|
import Control.Parallel.Strategies
|
||||||
|
import Control.DeepSeq
|
||||||
|
import KomplizierteFunktion
|
||||||
|
|
||||||
|
-- Sie sollen Minima einer komplizierten Funktion finden. Die Funktion erlaubt keine analytische Berechnung
|
||||||
|
-- der Maxima. Daher sollen Sie im Intervall [-10,10] für alle Parameter x y z w approximativ Maxima suchen.
|
||||||
|
|
||||||
|
-- komplizierteFunktion :: Double -> Double -> Double -> Double -> Double
|
||||||
|
|
||||||
|
berechnungMitEingabe :: Double -> Double -> Double -> Double -> ((Double,Double,Double,Double),Double)
|
||||||
|
berechnungMitEingabe x y z w = ((x,y,z,w),komplizierteFunktion x y z w)
|
||||||
|
|
||||||
|
nBesteEingaben :: Int -> Double -> [((Double,Double,Double,Double),Double)]
|
||||||
|
nBesteEingaben n d = take n $ sortOn (negate.snd) $ berechnungMitEingabe <$> range <*> range <*> range <*> range
|
||||||
|
where range = [(-10),(-(10-d))..10]
|
||||||
|
|
||||||
|
-- 3 x dieselbe implementation -> versuchen sie 3 verschiedene Strategien der Parallelisierung
|
||||||
|
nBesteEingabenPar1 :: Int -> Double -> [((Double,Double,Double,Double),Double)]
|
||||||
|
nBesteEingabenPar1 n d = take n $ sortOn (negate.snd) berechnungen
|
||||||
|
where
|
||||||
|
berechnungen = berechnungMitEingabe <$> range <*> range <*> range <*> range
|
||||||
|
range = [(-10),(-(10-d))..10]
|
||||||
|
|
||||||
|
nBesteEingabenPar2 :: Int -> Double -> [((Double,Double,Double,Double),Double)]
|
||||||
|
nBesteEingabenPar2 n d = take n $ sortOn (negate.snd) berechnungen
|
||||||
|
where
|
||||||
|
berechnungen = berechnungMitEingabe <$> range <*> range <*> range <*> range
|
||||||
|
range = [(-10),(-(10-d))..10]
|
||||||
|
|
||||||
|
nBesteEingabenPar3 :: Int -> Double -> [((Double,Double,Double,Double),Double)]
|
||||||
|
nBesteEingabenPar3 n d = take n $ sortOn (negate.snd) berechnungen
|
||||||
|
where
|
||||||
|
berechnungen = berechnungMitEingabe <$> range <*> range <*> range <*> range
|
||||||
|
range = [(-10),(-(10-d))..10]
|
||||||
|
|
||||||
|
strategy1 = show $ nBesteEingabenPar1 10 0.5
|
||||||
|
strategy2 = show $ nBesteEingabenPar2 10 0.5
|
||||||
|
strategy3 = show $ nBesteEingabenPar3 10 0.5
|
||||||
|
|
44
src/STMBanking.hs
Normal file
44
src/STMBanking.hs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
module STMBanking where
|
||||||
|
|
||||||
|
import Control.Concurrent.STM
|
||||||
|
|
||||||
|
data Konto = Konto
|
||||||
|
{ cents :: Integer
|
||||||
|
, nummer :: Integer
|
||||||
|
}
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
type Bank = [TMVar Konto]
|
||||||
|
|
||||||
|
kontoA :: Konto
|
||||||
|
kontoA = Konto 1000 1
|
||||||
|
kontoB :: Konto
|
||||||
|
kontoB = Konto 0 2
|
||||||
|
kontoC :: Konto
|
||||||
|
kontoC = Konto 2000 3
|
||||||
|
|
||||||
|
-- IMPLEMENTIEREN
|
||||||
|
debit :: Bank -> TMVar Konto -> TMVar Konto -> Integer -> STM Bank
|
||||||
|
debit b _ _ _ = return b
|
||||||
|
|
||||||
|
-- diese Transaktion überweist 1000 cent einmal reihum.
|
||||||
|
-- Danach hat jeder dasselbe Geld wie vorher - theoretisch!
|
||||||
|
testTransaction1 :: Bank -> IO Bank
|
||||||
|
testTransaction1 bank = atomically $ do
|
||||||
|
bank <- debit bank (bank!!0) (bank!!1) 1000
|
||||||
|
bank <- debit bank (bank!!1) (bank!!2) 1000
|
||||||
|
debit bank (bank!!2) (bank!!0) 1000
|
||||||
|
|
||||||
|
-- Dieselbe Transaktion. Diesmal mit gelockter Bank.
|
||||||
|
testTransaction2 :: TMVar Bank -> IO (TMVar Bank)
|
||||||
|
testTransaction2 mb = atomically $ do
|
||||||
|
bank <- takeTMVar mb
|
||||||
|
bank <- debit bank (bank!!0) (bank!!1) 1000
|
||||||
|
bank <- debit bank (bank!!1) (bank!!2) 1000
|
||||||
|
bank <- debit bank (bank!!2) (bank!!0) 1000
|
||||||
|
putTMVar mb bank
|
||||||
|
return mb
|
||||||
|
|
||||||
|
|
||||||
|
setup :: IO Bank
|
||||||
|
setup = sequence $ newTMVarIO <$> [kontoA, kontoB, kontoC]
|
6
stack.yaml
Normal file
6
stack.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
flags: {}
|
||||||
|
extra-package-dbs: []
|
||||||
|
packages:
|
||||||
|
- '.'
|
||||||
|
extra-deps: []
|
||||||
|
resolver: lts-8.12
|
100
zettel10.cabal
Normal file
100
zettel10.cabal
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
name: zettel10
|
||||||
|
version: 0.1.0.0
|
||||||
|
synopsis: First Assignment of FFPiHaskell 2017
|
||||||
|
-- description:
|
||||||
|
homepage: https://github.com/FFPiHaskell/zettel10#readme
|
||||||
|
license: BSD3
|
||||||
|
license-file: LICENSE
|
||||||
|
author: FFPiHaskell Tutors
|
||||||
|
maintainer: sdressel@techfak.uni-bielefeld.de
|
||||||
|
copyright: 2017 FFPiHaskell Tutors
|
||||||
|
category: cli
|
||||||
|
build-type: Simple
|
||||||
|
extra-source-files: README.md
|
||||||
|
cabal-version: >=1.10
|
||||||
|
|
||||||
|
|
||||||
|
-- library for all things common in all exercises/not neccessary for students
|
||||||
|
-- to solve assignments
|
||||||
|
library
|
||||||
|
hs-source-dirs: src
|
||||||
|
exposed-modules: Parallel
|
||||||
|
, KomplizierteFunktion
|
||||||
|
, Banking
|
||||||
|
, STMBanking
|
||||||
|
build-depends: base >= 4.7 && < 5
|
||||||
|
, parallel
|
||||||
|
, array
|
||||||
|
, deepseq
|
||||||
|
, stm
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable MainParallel1
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: MainParallel1.hs
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, zettel10
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable MainParallel2
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: MainParallel2.hs
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, zettel10
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable MainParallel3
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: MainParallel3.hs
|
||||||
|
ghc-options: -threaded -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, zettel10
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable MainBanking1
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: MainBanking1.hs
|
||||||
|
ghc-options: -threaded -eventlog -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, zettel10
|
||||||
|
, threads
|
||||||
|
, time
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable MainBanking2
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: MainBanking2.hs
|
||||||
|
ghc-options: -threaded -eventlog -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, zettel10
|
||||||
|
, threads
|
||||||
|
, time
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable MainSTMBanking1
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: MainSTMBanking1.hs
|
||||||
|
ghc-options: -threaded -eventlog -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, zettel10
|
||||||
|
, threads
|
||||||
|
, time
|
||||||
|
, stm
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
executable MainSTMBanking2
|
||||||
|
hs-source-dirs: app
|
||||||
|
main-is: MainSTMBanking2.hs
|
||||||
|
ghc-options: -threaded -eventlog -rtsopts -with-rtsopts=-N
|
||||||
|
build-depends: base
|
||||||
|
, zettel10
|
||||||
|
, threads
|
||||||
|
, time
|
||||||
|
, stm
|
||||||
|
default-language: Haskell2010
|
||||||
|
|
||||||
|
source-repository head
|
||||||
|
type: git
|
||||||
|
location: https://github.com/FFPiHaskell/zettel10
|
Loading…
Reference in New Issue
Block a user