initial exercise
This commit is contained in:
		
							
								
								
									
										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
 | 
				
			||||||
		Reference in New Issue
	
	Block a user