Commit 8ff99eb7 authored by Jochen Schulz's avatar Jochen Schulz
Browse files

fixed example-program for 19

parent 298c2b8f
...@@ -2,14 +2,10 @@ compile with ...@@ -2,14 +2,10 @@ compile with
ghc -Odph -rtsopts -threaded -fno-liberate-case -funfolding-use-threshold1000 -funfolding-keeness-factor1000 -fllvm -optlo-O3 -eventlog mandelbrot.lhs ghc -Odph -rtsopts -threaded -fno-liberate-case -funfolding-use-threshold1000 -funfolding-keeness-factor1000 -fllvm -optlo-O3 -eventlog mandelbrot.lhs
run with (N is the number of threa2015-08-12) run with (N is the number of threads)
./mandelbrot +RTS -s -N2 -l ./mandelbrot +RTS -s -N2 -l
visualize
../../vis.py -x xmat.txt -y ymat.txt -z zmat.txt -t image
and show what the threads are doing and show what the threads are doing
threadscope mandelbrot.eventlog threadscope mandelbrot.eventlog
...@@ -21,10 +17,11 @@ and show what the threads are doing ...@@ -21,10 +17,11 @@ and show what the threads are doing
import Data.Array.Repa as R import Data.Array.Repa as R
import Data.Array.Repa.Algorithms.Complex import Data.Array.Repa.Algorithms.Complex
import Data.Array.Repa.Repr.HintInterleave
import Data.List (findIndex) import Data.List (findIndex)
import Data.Packed.Repa import Data.Array.Repa.Algorithms.ColorRamp
import Numeric.Container (saveMatrix) import Data.Array.Repa.Algorithms.Pixel
import Data.Array.Repa.IO.BMP (writeImageToBMP)
import Control.Monad.Identity (runIdentity)
-- checks if sequence is infinite (and then returns the number of iterations it needed to determine that) -- checks if sequence is infinite (and then returns the number of iterations it needed to determine that)
...@@ -43,22 +40,15 @@ grid (x, y) = (Z :. x) :. y ...@@ -43,22 +40,15 @@ grid (x, y) = (Z :. x) :. y
calcView :: (Complex, Complex) -> (Int, Int) -> DIM2 -> Complex calcView :: (Complex, Complex) -> (Int, Int) -> DIM2 -> Complex
calcView ((left, bottom), (right, top)) (max_x, max_y) (Z :. x :. y) = ((right - left) * (fromIntegral x)/(fromIntegral max_x - 1) + left, (top - bottom) * (fromIntegral y)/(fromIntegral max_y - 1) + bottom) calcView ((left, bottom), (right, top)) (max_x, max_y) (Z :. x :. y) = ((right - left) * (fromIntegral x)/(fromIntegral max_x - 1) + left, (top - bottom) * (fromIntegral y)/(fromIntegral max_y - 1) + bottom)
size = (2048,2048)
view = ((-1.5, -1.5),(1.5,1.5)) view = ((-1.5, -1.5),(1.5,1.5))
main :: IO () main :: IO ()
main = do main = do
let size = (1024,1024) !coord <- computeP $ fromFunction (grid Main.size) ( calcView view Main.size) :: IO (Array U DIM2 Complex)
!coord <- computeP $ fromFunction (grid size) ( calcView view size) :: IO (Array U DIM2 Complex)
let z = R.map ( maybe 0 fromIntegral . isMandel 35 3) coord :: Array D DIM2 Double (writeImageToBMP "../../images/mandel.bmp" . runIdentity . computeP)
!zmat <- computeP $ hintInterleave z :: IO (Array U DIM2 Double) $ R.map ( rgb8OfFloat. rampColorHotToCold 0 35 . maybe 0 fromIntegral . isMandel 35 3) coord
-- !a <- computeP $ R.map ( maybe 0 fromIntegral . isMandel 35 3) coord :: IO (Array U DIM2 Float)
print "finished" print "finished"
-- write out matrices to visualize with python
let xmat = copyS $ R.map fst coord
let ymat = copyS $ R.map snd coord
saveMatrix "xmat.txt" "%f" (repaToMatrix xmat)
saveMatrix "ymat.txt" "%f" (repaToMatrix ymat)
let zmats = copyS zmat
saveMatrix "zmat.txt" "%f" (repaToMatrix zmats)
-- ../vis.py -x xmat.txt -y ymat.txt -z zmat.txt -t image
\end{code} \end{code}
images/threadscope.png

90.3 KB | W: | H:

images/threadscope.png

85.6 KB | W: | H:

images/threadscope.png
images/threadscope.png
images/threadscope.png
images/threadscope.png
  • 2-up
  • Swipe
  • Onion skin
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Parallel computed arrays # Parallel computed arrays
## parallel and concurrent programming ## parallel and concurrent programming
more than one thread doing something in parallel. more than one thread doing something in parallel.
**Parallel** <br /> **Parallel** <br />
- goal: faster calculations - goal: faster calculations
- for deterministic functions - for deterministic functions
- example: matrix multiplication - example: matrix multiplication
**concurrent** <br /> **concurrent** <br />
- structuring of a program - structuring of a program
- for non-deterministic tasks - for non-deterministic tasks
- example: client/server - example: client/server
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## parall arrays with Repa ## parall arrays with Repa
- generalized regular arrays with built-in parallel handling. - generalized regular arrays with built-in parallel handling.
basic datatype is `Array` basic datatype is `Array`
```haskell ```haskell
data Array rep sh e data Array rep sh e
``` ```
- e : datatype of the array elements - e : datatype of the array elements
- sh : shape of the array - sh : shape of the array
- rep : type index or representation - rep : type index or representation
*Shapes:* *Shapes:*
constructors : <br/> constructors : <br/>
- `Z` : Zero dimension <br /> - `Z` : Zero dimension <br />
- `(:.)` : add a dimension. right associative - `(:.)` : add a dimension. right associative
```haskell ```haskell
Z :. Int :. Int == (Z :. Int) :. Int Z :. Int :. Int == (Z :. Int) :. Int
``` ```
the dimension can then be defined as the dimension can then be defined as
```haskell ```haskell
type DIM0 = Z type DIM0 = Z
type DIM1 = DIM0 :. Int type DIM1 = DIM0 :. Int
... ...
``` ```
*representations* *representations*
- manifest (real data) - manifest (real data)
- delayed (functions that compute elements) - delayed (functions that compute elements)
- meta (special and mixed types) - meta (special and mixed types)
internally Repa stores the data in a one-dimensional vector internally Repa stores the data in a one-dimensional vector
### Manifest Representations (real data) ### Manifest Representations (real data)
U -- Adaptive unboxed vectors. U -- Adaptive unboxed vectors.
V -- Boxed vectors. V -- Boxed vectors.
**Boxed** : array values are ordinary Haskell (lazy) values, which are evaluated on demand, and can even contain bottom (undefined) values. **Boxed** : array values are ordinary Haskell (lazy) values, which are evaluated on demand, and can even contain bottom (undefined) values.
**Unboxed** : are arrays only containing plain values. **Unboxed** : are arrays only containing plain values.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
**fromListUnboxed** <br /> **fromListUnboxed** <br />
create unboxed array from a list create unboxed array from a list
```haskell ```haskell
fromListUnboxed :: (Shape sh, Unbox a) => sh -> [a] -> Array U sh a fromListUnboxed :: (Shape sh, Unbox a) => sh -> [a] -> Array U sh a
``` ```
**fromList** <br /> **fromList** <br />
variant that is polymorphic in the output representation (defined in `Data.Array.Repa.Eval`) variant that is polymorphic in the output representation (defined in `Data.Array.Repa.Eval`)
```haskell ```haskell
fromList :: (Target r e, Shape sh) => sh -> [e] -> Array r sh e fromList :: (Target r e, Shape sh) => sh -> [e] -> Array r sh e
``` ```
**ix_N_** <br /> constructs an index **ix_N_** <br /> constructs an index
```haskell ```haskell
ix1 :: Int -> DIM1 ix1 :: Int -> DIM1
ix2 :: Int -> Int -> DIM2 ix2 :: Int -> Int -> DIM2
... ...
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
import Data.Array.Repa as R import Data.Array.Repa as R
a = fromListUnboxed Z [1] :: Array U DIM0 Int -- a scalar of an int a = fromListUnboxed Z [1] :: Array U DIM0 Int -- a scalar of an int
a a
``` ```
%% Output %% Output
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
b = fromListUnboxed (ix1 3) [1,2,3] :: Array U DIM1 Doubler -- a 3 element vector with doubles b = fromListUnboxed (ix1 3) [1,2,3] :: Array U DIM1 Doubler -- a 3 element vector with doubles
b b
ix1 3 ix1 3
``` ```
%% Output %% Output
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
c = fromListUnboxed (ix2 2 4) [1,2..8] :: Array U DIM2 Double -- a (2,4)-matrix with doubles c = fromListUnboxed (ix2 2 4) [1,2..8] :: Array U DIM2 Double -- a (2,4)-matrix with doubles
c c
``` ```
%% Output %% Output
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
**(!)** : <br /> **(!)** : <br />
index operator index operator
```haskell ```haskell
(!) :: (Shape sh, Source r e) => Array r sh e -> sh -> e (!) :: (Shape sh, Source r e) => Array r sh e -> sh -> e
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
a ! Z a ! Z
b ! ix1 1 b ! ix1 1
c ! ix2 1 2 c ! ix2 1 2
``` ```
%% Output %% Output
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
**reshape** <br /> **reshape** <br />
change shape of an array (this is cheap, because the internal representation is the same) change shape of an array (this is cheap, because the internal representation is the same)
```haskell ```haskell
reshape :: (Shape sh1, Shape sh2, Source r1 e) => sh2 -> Array r1 sh1 e -> Array D sh2 e reshape :: (Shape sh1, Shape sh2, Source r1 e) => sh2 -> Array r1 sh1 e -> Array D sh2 e
``` ```
*example:* because it creates a delayed array, we access one element *example:* because it creates a delayed array, we access one element
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
reshape (Z :. 4 :. 2) c ! (Z :. 1 :. 0 :: DIM2) reshape (Z :. 4 :. 2) c ! (Z :. 1 :. 0 :: DIM2)
``` ```
%% Output %% Output
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
**rank** <br /> **rank** <br />
number of dimensions number of dimensions
```haskell ```haskell
rank :: Shape sh => sh -> Int rank :: Shape sh => sh -> Int
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
**size** <br /> **size** <br />
number of elements number of elements
```haskell ```haskell
size :: Shape sh => sh -> Int size :: Shape sh => sh -> Int
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
**extent** <br /> **extent** <br />
get the shape of an array get the shape of an array
```haskell ```haskell
extent :: (Shape sh, Source r e) => Array r sh e -> sh extent :: (Shape sh, Source r e) => Array r sh e -> sh
``` ```
since rank and size work on shapes we use extent often since rank and size work on shapes we use extent often
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
rank (extent c) rank (extent c)
size (extent c) size (extent c)
``` ```
%% Output %% Output
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### Delayed Representations and computations ### Delayed Representations and computations
D -- Functions from indices to elements. D -- Functions from indices to elements.
C -- Cursor functions. C -- Cursor functions.
these are arrays which are not yet calculated. They are calculated with specialised functions for sequentiel or parallel computation. This has the advantage of these are arrays which are not yet calculated. They are calculated with specialised functions for sequentiel or parallel computation. This has the advantage of
- beeing able to exactly choose when and how you calculate - beeing able to exactly choose when and how you calculate
- intermediate arrays are not calculated (*fusion*) - intermediate arrays are not calculated (*fusion*)
*fusion* means, if you have several operations on some data, in the end the combined operations are used in parallel and there will be no intermediate arrays (which is fast and saves memory) *fusion* means, if you have several operations on some data, in the end the combined operations are used in parallel and there will be no intermediate arrays (which is fast and saves memory)
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
**fromFunction** <br /> **fromFunction** <br />
create delayed arrays create delayed arrays
```haskell ```haskell
fromFunction :: sh -> (sh -> a) -> Array D sh a fromFunction :: sh -> (sh -> a) -> Array D sh a
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
d = fromFunction (Z :. 5) (\(Z:.i) -> i :: Int) d = fromFunction (Z :. 5) (\(Z:.i) -> i :: Int)
d ! (Z:.1) d ! (Z:.1)
:ty d :ty d
``` ```
%% Output %% Output
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
or more often with maps oder zips: or more often with maps oder zips:
```haskell ```haskell
map :: (Shape sh, Source r a) => (a -> b) -> Array r sh a -> Array D sh b map :: (Shape sh, Source r a) => (a -> b) -> Array r sh a -> Array D sh b
zipWith :: (Shape sh, Source r1 a, Source r2 b) => (a -> b -> c) -> Array r1 sh a -> Array r2 sh b -> Array D sh c zipWith :: (Shape sh, Source r1 a, Source r2 b) => (a -> b -> c) -> Array r1 sh a -> Array r2 sh b -> Array D sh c
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
e = R.map (+1) d e = R.map (+1) d
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Evaluation of delayed Arrays: Evaluation of delayed Arrays:
**computeS** <br /> **computeS** <br />
sequential sequential
```haskell ```haskell
computeS :: (Load r1 sh e, Target r2 e) => Array r1 sh e -> Array r2 sh e computeS :: (Load r1 sh e, Target r2 e) => Array r1 sh e -> Array r2 sh e
``` ```
**computeP** <br /> **computeP** <br />
parallel parallel
```haskell ```haskell
computeP :: (Monad m, Load r1 sh e, Target r2 e) => Array r1 sh e -> m (Array r2 sh e) computeP :: (Monad m, Load r1 sh e, Target r2 e) => Array r1 sh e -> m (Array r2 sh e)
``` ```
the monad ensures that there is no nested parallel computation (which doesn't work) the monad ensures that there is no nested parallel computation (which doesn't work)
<!--Einfachste Möglichkeit: Benutze Identitätsmonade aus `Control.Monad.Identity`--> <!--Einfachste Möglichkeit: Benutze Identitätsmonade aus `Control.Monad.Identity`-->
*example of sequential calculations* *example of sequential calculations*
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
computeS e :: Array U DIM1 Int computeS e :: Array U DIM1 Int
``` ```
%% Output %% Output
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Some folds which directly create calculated (unboxed) arrays Some folds which directly create calculated (unboxed) arrays
```haskell ```haskell
foldS :: (Shape sh, Source r a, Unbox a, Elt a) => (a -> a -> a) -> a -> Array r (sh :. Int) a -> Array U sh a foldS :: (Shape sh, Source r a, Unbox a, Elt a) => (a -> a -> a) -> a -> Array r (sh :. Int) a -> Array U sh a
foldP :: (Monad m, Shape sh, Source r a, Unbox a, Elt a) => (a -> a -> a) -> a -> Array r (sh :. Int) a -> m (Array U sh a) foldP :: (Monad m, Shape sh, Source r a, Unbox a, Elt a) => (a -> a -> a) -> a -> Array r (sh :. Int) a -> m (Array U sh a)
``` ```
Important: for `foldP` the operator must be associative Important: for `foldP` the operator must be associative
*example adding up all rows* *example adding up all rows*
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
foldP (+) 0 c foldP (+) 0 c
``` ```
%% Output %% Output
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
this is actually also how `sumP` is defined. this is actually also how `sumP` is defined.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
## Example: Mandelbrot fractal ## Example: Mandelbrot fractal
a point $c$ in the complex plane is in the generalised *mandelbrot* set, if and only if the sequence ${z_n},{n \in \mathbb{N}}$ with a point $c$ in the complex plane is in the generalised *mandelbrot* set, if and only if the sequence ${z_n},{n \in \mathbb{N}}$ with
$$z_0 = 0$$ $$z_0 = 0$$
$$z_{n+1} = f_c(z_n)$$ $$z_{n+1} = f_c(z_n)$$
is finite. is finite.
For the classical *mandelbrot* set $f$ is given by $$f_c(z) = z^2 + c$$ For the classical *mandelbrot* set $f$ is given by $$f_c(z) = z^2 + c$$
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
:ext FlexibleContexts :ext FlexibleContexts
import Data.Array.Repa as R import Data.Array.Repa as R
import Data.Array.Repa.Algorithms.Complex import Data.Array.Repa.Algorithms.Complex
import Data.Array.Repa.Algorithms.ColorRamp import Data.Array.Repa.Algorithms.ColorRamp
import Data.Array.Repa.Algorithms.Pixel import Data.Array.Repa.Algorithms.Pixel
import Data.List (findIndex) import Data.List (findIndex)
-- import Data.Packed.Repa -- import Data.Packed.Repa
import Data.Array.Repa.IO.BMP (writeImageToBMP) import Data.Array.Repa.IO.BMP (writeImageToBMP)
import Control.Monad.Identity (runIdentity) import Control.Monad.Identity (runIdentity)
-- checks if sequence is infinite (and then returns the number of iterations it needed to determine that) -- checks if sequence is infinite (and then returns the number of iterations it needed to determine that)
isGeneralMandel :: (Complex -> Complex -> Complex) -> Int -> Double -> Complex -> Maybe Int isGeneralMandel :: (Complex -> Complex -> Complex) -> Int -> Double -> Complex -> Maybe Int
isGeneralMandel f iteration_depth bound c = findIndex ((>bound) . mag) (take iteration_depth (iterate (f c) 0)) isGeneralMandel f iteration_depth bound c = findIndex ((>bound) . mag) (take iteration_depth (iterate (f c) 0))
-- checks if given number is in mandelbrot set -- checks if given number is in mandelbrot set
isMandel :: Int -> Double -> Complex -> Maybe Int isMandel :: Int -> Double -> Complex -> Maybe Int
isMandel = isGeneralMandel (\c z -> z*z + c) isMandel = isGeneralMandel (\c z -> z*z + c)
-- grid: values in complex plane -- grid: values in complex plane
grid :: (Int, Int) -> DIM2 grid :: (Int, Int) -> DIM2
grid (x, y) = (Z :. x) :. y grid (x, y) = (Z :. x) :. y
-- calculates the mesh of points in complex plane -- calculates the mesh of points in complex plane
calcView :: (Complex, Complex) -> (Int, Int) -> DIM2 -> Complex calcView :: (Complex, Complex) -> (Int, Int) -> DIM2 -> Complex
calcView ((left, bottom), (right, top)) (max_x, max_y) (Z :. x :. y) = calcView ((left, bottom), (right, top)) (max_x, max_y) (Z :. x :. y) =
((right - left) * (fromIntegral x)/(fromIntegral max_x - 1) + left, ((right - left) * (fromIntegral x)/(fromIntegral max_x - 1) + left,
(top - bottom) * (fromIntegral y)/(fromIntegral max_y - 1) + bottom) (top - bottom) * (fromIntegral y)/(fromIntegral max_y - 1) + bottom)
size = (1024,1024) size = (1024,1024)
view = ((-1.5, -1.5),(1.5,1.5)) view = ((-1.5, -1.5),(1.5,1.5))
-- parallel computation for the grid -- parallel computation for the grid
coord <- computeP $ fromFunction (grid size) ( calcView view size) :: IO (Array U DIM2 Complex) coord <- computeP $ fromFunction (grid size) ( calcView view size) :: IO (Array U DIM2 Complex)
(writeImageToBMP "../images/mandel.bmp" . runIdentity . computeP) (writeImageToBMP "../images/mandel.bmp" . runIdentity . computeP)
$ R.map ( rgb8OfFloat. rampColorHotToCold 0 35 . maybe 0 fromIntegral . isMandel 35 3) coord $ R.map ( rgb8OfFloat. rampColorHotToCold 0 35 . maybe 0 fromIntegral . isMandel 35 3) coord
``` ```
%% Output %% Output
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
<img src="../images/mandel.bmp"></img> <img src="../images/mandel.bmp"></img>
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
doing it in the ihaskell notebook doesn't run it in parallel.. We need to compile it doing it in the ihaskell notebook doesn't run it in parallel.. We need to compile it
## actually running the program in parallel ## actually running the program in parallel
At compilation we need to at the command-line option `-threaded` and `-rtsopts` which enable multiple threads and the ability to have runtime-options respectively. At compilation we need to at the command-line option `-threaded` and `-rtsopts` which enable multiple threads and the ability to have runtime-options respectively.
For example, for the mandelbrot program we do For example, for the mandelbrot program we do
``` ```
ghc -Odph -rtsopts -threaded -O3 mandelbrot.lhs ghc -Odph -rtsopts -threaded -fno-liberate-case -funfolding-use-threshold1000 -funfolding-keeness-factor1000 -fllvm -optlo-O3 mandelbrot.lhs
``` ```
At runtime we specify with how many threads we will run the program. This is done with the command-line option `-Nx` while `x` is the number of threads. At runtime we specify with how many threads we will run the program. This is done with the command-line option `-Nx` while `x` is the number of threads.
Again for example run the program Again for example run the program
``` ```
./mandelbrot +RTS -N2 -s -RTS ./mandelbrot +RTS -N2 -s -RTS
``` ```
and compare the runtime to `-N1` and compare the runtime to `-N1` (with 4000x4000 points)
``` ```
1 thread: Total time 0.875s ( 0.867s elapsed) 1 thread: Total time 17.759s ( 17.798s elapsed)
2 threads: Total time 0.964s ( 0.607s elapsed) 2 threads: Total time 19.061s ( 11.712s elapsed)
``` ```
This is not perfect but good enough for this quick program. This is not perfect but good enough for this quick program (note: elapsed is the real time passed and the total time is the total cpu time used)
## tool for monitoring parallel processes: threadscope ## tool for monitoring parallel processes: threadscope
*threadscope* is a program which helps visualizing what is happening during a parallel calculation. *threadscope* is a program which helps visualizing what is happening during a parallel calculation.
For this we need to compile it with the fla `-eventlog` option which enables creating a *eventlog* which threadscope uses to create its report. For this we need to compile it with the fla `-eventlog` option which enables creating a *eventlog* which threadscope uses to create its report.
For example, for the mandelbrot program we do For example, for the mandelbrot program we do
``` ```
ghc -Odph -rtsopts -threaded -O3 -eventlog mandelbrot.lhs ghc -Odph -rtsopts -threaded -fno-liberate-case -funfolding-use-threshold1000 -funfolding-keeness-factor1000 -fllvm -optlo-O3 -eventlog mandelbrot.lhs
./mandelbrot +RTS -N2 -s -l -RTS ./mandelbrot +RTS -N2 -s -l -RTS
``` ```
then there is a file `mandelbrot.eventlog` and we can run threadscope with it: then there is a file `mandelbrot.eventlog` and we can run threadscope with it:
``` ```
threadscope mandelbrot.eventlog threadscope mandelbrot.eventlog
``` ```
The result is: The result is:
<img src="../images/threadscope.png"></img> <img src="../images/threadscope.png"></img>
here we can see, that most of the time is spend in a sequential writing the matrix to the drive but the calculation itself is fine in parallel. here we can see, the parallel computation is mostly fine. There is some inbalance which results from the fact that every single computation is quite different.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
### general way to parallelize your program ### general way to parallelize your program
To get the most out of parallelization you need to consider several things. This is out of the scope here but we cover some simple advices for the usage with repa. To get the most out of parallelization you need to consider several things. This is out of the scope here but we cover some simple advices for the usage with repa.
- 1) think about what parts of you program are trivially parallizable (calculations which do not dependent on each other) - 1) think about what parts of you program are trivially parallizable (calculations which do not dependent on each other)
- 2) parallelize them with repa - 2) parallelize them with repa
- 3) think of parts of your program which you can transform into trivially parallelize parts. This usually involves splitting up your algorithm. - 3) think of parts of your program which you can transform into trivially parallelize parts. This usually involves splitting up your algorithm.
Doing especially 3) can be hard. The next step after 3) would be to parallelize over several computers. This has the additional complexity that computers don't share memory and you have to transfer this memory between the computing nodes. This is its own lecture (using for example MPI, the Message Passing Interface). Doing especially 3) can be hard. The next step after 3) would be to parallelize over several computers. This has the additional complexity that computers don't share memory and you have to transfer this memory between the computing nodes. This is its own lecture (using for example MPI, the Message Passing Interface).
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` haskell ``` haskell
``` ```
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment