a -> a And ahas the property of additivity . Therefore, we c...">

Parallel "Fold" in Haskell

I have a function with a type below:

union :: a -> a -> a

And ahas the property of additivity . Therefore, we can consider it unionas a version(+)

Let's say we have [a]and want to execute a parallel "folding", for non-parallel bending we can only do:

foldl1' union [a]

But how to do this in parallel? I can demonstrate the problem by Numand (+).

For example, we have a list [1,2,3,4,5,6]and in (+) parallel we have to split

[1,2,3] (+) [4,5,6]
[1,2] (+) [3] (+) [4,5] (+) [6]
([1] (+) [2]) (+) ([3] (+) [4]) (+) ([5] (+) [6])

then each operation (+)that we want to perform in parallel, and combine to respond

[3] (+) [7] (+) [11] = 21

Please note that we break the list or perform operations in any order due to aadditivity.

?

+10
2

union & oplus; , (a & oplus; b) & oplus; c == a & oplus; (b & oplus; c). , & oplus;, .

, & oplus; , a & oplus; (b & oplus; (c & oplus; d)) == (a & oplus; b) & oplus; (c & oplus; d) - ; "" "" , .

, , chunking , & oplus; - do & oplus; , chunking. - "" - , . Data.Array.Repa .

, , & oplus; .

:

import Control.Parallel
import Data.List

pfold :: (Num a, Enum a) => (a -> a -> a) -> [a] -> a
pfold _ [x] = x
pfold mappend xs  = (ys `par` zs) `pseq` (ys `mappend` zs) where
  len = length xs
  (ys', zs') = splitAt (len `div` 2) xs
  ys = pfold mappend ys'
  zs = pfold mappend zs'

main = print $ pfold (+) [ foldl' (*) 1 [1..x] | x <- [1..5000] ]
  -- need a more complicated computation than (+) of numbers
  -- so we produce a list of products of many numbers

, mappend , , , parallelism; parallelism , mempty.

ghc -O2 -threaded a.hs
a +RTS -N1 -s

8,78 ,

a +RTS -N2 -s

5,89 . , -N2.

+12

, , . GHCI:

Prelude> :m + Data.Monoid
Prelude Data.Monoid> :info Monoid
class Monoid a where
  mempty :: a
  mappend :: a -> a -> a
  mconcat :: [a] -> a

, :

  • mempty . , Num : sum product. mempty 0. mempty 1.

    mempty `mappend` a = a
    a `mappend` mempty = a
    
  • mappend union. Num mappend (+), Num mappend (*).

  • mconcat . - , , . , mappend :

    (a `mappend` b) `mappend` c =  a `mappend` (b `mappend` c)
    

, , Haskell . , Monoid typeclass, , .

, union : a -> a -> a. , . . . union ?

, :

newtype Sum a = Sum { getSum :: a }

instance Num a => Monoid (Sum a) where
    mempty = 0
    mappend = (+)

. mconcat, , mempty mappend. , mempty mappend, mconcat .

Sum :

getSum . mconcat $ map Sum [1..6]

, :

  • Sum [1..6] [Sum 1, Sum 2, Sum 3, Sum 4, Sum 5, Sum 6].
  • mconcat, Sum 21.
  • getSum Num Sum 21.

, , mconcat - foldr mappend mempty (.. ). . :

foldParallel :: Monoid a => [a] -> a
foldParallel []  = mempty
foldParallel [a] = a
foldParallel xs  = foldParallel left `mappend` foldParallel right
    where size = length xs
          index = (size + size `mod` 2) `div` 2
          (left, right) = splitAt index xs

Monoid :

data Something a = Something { getSomething :: a }

instance Monoid (Something a) where
    mempty  = unionEmpty
    mappend = union
    mconcat = foldParallel

:

getSomething . mconcat $ map Something [1..6]

, mempty unionEmpty. , union. , mempty . , unionEmpty. .

+4

All Articles