monad-par (empty) → 0.1
raw patch · 56 files changed
+6782/−0 lines, 56 filesdep +HUnitdep +basedep +deepseqsetup-changed
Dependencies added: HUnit, base, deepseq
Files
- Control/Monad/Par.hs +303/−0
- Control/Monad/Par/AList.hs +190/−0
- Control/Monad/Par/IList.hs +28/−0
- Control/Monad/Par/Internal.hs +292/−0
- Control/Monad/Par/OpenList.hs +454/−0
- Control/Monad/Par/Stream.hs +367/−0
- LICENSE +30/−0
- Setup.hs +3/−0
- examples/Makefile +33/−0
- examples/PortablePixmap.lhs +127/−0
- examples/benchlist.txt +27/−0
- examples/benchmark.sh +226/−0
- examples/blackscholes.hs +153/−0
- examples/blackscholes_data.hs +1006/−0
- examples/cholesky.hs +321/−0
- examples/cholesky_matrix6.dat +1/−0
- examples/coins.hs +240/−0
- examples/common.mk +10/−0
- examples/get_cholesky_data.sh +2/−0
- examples/mandel.hs +96/−0
- examples/matmult/ListAux.hs +41/−0
- examples/matmult/Makefile +4/−0
- examples/matmult/MatMult.hs +215/−0
- examples/matmult/matmult.stdout +1/−0
- examples/minimax/Board.hs +121/−0
- examples/minimax/Game.hs +67/−0
- examples/minimax/Main.hs +20/−0
- examples/minimax/Makefile +4/−0
- examples/minimax/Prog.hs +47/−0
- examples/minimax/Tree.hs +41/−0
- examples/minimax/Wins.hs +39/−0
- examples/minimax/minimax.stdout +18/−0
- examples/nbody.hs +123/−0
- examples/ntimes +153/−0
- examples/ntimes_minmedmax +38/−0
- examples/parfib.hs +74/−0
- examples/partree/Makefile +4/−0
- examples/partree/Tree.hs +146/−0
- examples/partree/partree.hs +34/−0
- examples/plot_scaling.hs +355/−0
- examples/primes.hs +52/−0
- examples/queens.hs +32/−0
- examples/run_tests.sh +19/−0
- examples/stream/DEVLOG.txt +141/−0
- examples/stream/Makefile +32/−0
- examples/stream/disjoint_working_sets_pipeline.hs +276/−0
- examples/stream/fft_pipeline.hs +75/−0
- examples/stream/simple1_measureSrc.hs +35/−0
- examples/sumeuler/ListAux.hs +41/−0
- examples/sumeuler/Makefile +7/−0
- examples/sumeuler/SumEuler.hs +287/−0
- examples/sumeuler/SumEulerPrimes.hs +36/−0
- examples/timeout.sh +91/−0
- monad-par.cabal +93/−0
- tests/AListTest.hs +37/−0
- tests/Test.hs +74/−0
+ Control/Monad/Par.hs view
@@ -0,0 +1,303 @@+{-# LANGUAGE RankNTypes, NamedFieldPuns, BangPatterns,+ ExistentialQuantification+ #-}+{-# OPTIONS_GHC -Wall -fno-warn-name-shadowing -fwarn-unused-imports #-}++-- | This module provides a monad @Par@, for speeding up pure+-- computations using parallel processors. It cannot be used for+-- speeding up computations that use IO (for that, see+-- @Control.Concurrent@). The result of a given @Par@ computation is+-- always the same - ie. it is deterministic, but the computation may+-- be performed more quickly if there are processors available to+-- share the work.+--+-- For example, the following program fragment computes the values of+-- @(f x)@ and @(g x)@ in parallel, and returns a pair of their results:+--+-- > runPar $ do+-- > fx <- pval (f x) -- start evaluating (f x)+-- > gx <- pval (g x) -- start evaluating (g x)+-- > a <- get fx -- wait for fx+-- > b <- get gx -- wait for gx+-- > return (a,b) -- return results+--+-- @Par@ can be used for specifying pure parallel computations in+-- which the order of the computation is not known beforehand.+-- The programmer specifies how information flows from one+-- part of the computation to another, but not the order in which+-- computations will be evaluated at runtime. Information flow is+-- described using "variables" called @IVar@s, which support 'put' and+-- 'get' operations. For example, suppose you have a problem that+-- can be expressed as a network with four nodes, where @b@ and @c@+-- require the value of @a@, and @d@ requires the value of @b@ and @c@:+--+-- > a+-- > / \ +-- > b c+-- > \ /+-- > d+--+-- Then you could express this in the @Par@ monad like this:+--+-- > runPar $ do+-- > [a,b,c,d] <- sequence [new,new,new,new]+-- > fork $ do x <- get a; put b (x+1)+-- > fork $ do x <- get a; put c (x+2)+-- > fork $ do x <- get b; y <- get c; put d (x+y)+-- > fork $ do put a (3 :: Int)+-- > get d+--+-- The result of the above computation is always 9. The 'get' operation+-- waits until its input is available; multiple 'put's to the same+-- @IVar@ are not allowed, and result in a runtime error. Values+-- stored in @IVar@s are usually fully evaluated (although there are+-- ways provided to pass lazy values if necessary).+--+-- In the above example, @b@ and @c@ will be evaluated in parallel.+-- In practice the work involved at each node is too small here to see+-- the benefits of parallelism though: typically each node should+-- involve much more work. The granularity is completely under your+-- control - too small and the overhead of the @Par@ monad will+-- outweigh any parallelism benefits, whereas if the nodes are too+-- large then there might not be enough parallelism to use all the+-- available processors.+--+-- Unlike @Control.Parallel@, in @Control.Monad.Par@ parallelism is+-- not combined with laziness, so sharing and granulairty are+-- completely under the control of the programmer. New units of+-- parallel work are only created by @fork@, @par@, and a few other+-- combinators.+--+-- The implementation is based on a work-stealing scheduler that+-- divides the work as evenly as possible betwen the available+-- processors at runtime.+--++module Control.Monad.Par (+ -- * The @Par@ monad+ Par,+ runPar,+ fork,++ -- * Communication: @IVar@s+ IVar,+ new, newFull, newFull_,+ get,+ put, put_,++ -- * Operations+ pval,+ spawn, spawn_,+ parMap, parMapM,+ parMapReduceRangeThresh, parMapReduceRange,+ InclusiveRange(..),+ parFor,++ ) where++import Control.Monad.Par.Internal+import Control.DeepSeq+import Data.Traversable+import Control.Monad as M hiding (mapM, sequence, join)+import Prelude hiding (mapM, sequence, head,tail)++import GHC.Conc (numCapabilities)++-- -----------------------------------------------------------------------------++-- | forks a computation to happen in parallel. The forked+-- computation may exchange values with other computations using+-- @IVar@s.+fork :: Par () -> Par ()+fork p = Par $ \c -> Fork (runCont p (\_ -> Done)) (c ())++-- > both a b >> c == both (a >> c) (b >> c)+-- is this useful for anything?+-- both :: Par a -> Par a -> Par a+-- both a b = Par $ \c -> Fork (runCont a c) (runCont b c)++-- -----------------------------------------------------------------------------+-- Derived functions++-- | Like 'spawn', but the result is only head-strict, not fully-strict.+spawn_ :: Par a -> Par (IVar a)+spawn_ p = do+ r <- new+ fork (p >>= put_ r)+ return r++-- | Like 'fork', but returns a @IVar@ that can be used to query the+-- result of the forked computataion.+--+-- > spawn p = do+-- > r <- new+-- > fork (p >>= put r)+-- > return r+--+spawn :: NFData a => Par a -> Par (IVar a)+spawn p = do+ r <- new+ fork (p >>= put r)+ return r++-- | equivalent to @spawn . return@+pval :: NFData a => a -> Par (IVar a)+pval a = spawn (return a)++-- -----------------------------------------------------------------------------+-- Parallel maps over Traversable data structures++-- | Applies the given function to each element of a data structure+-- in parallel (fully evaluating the results), and returns a new data+-- structure containing the results.+--+-- > parMap f xs = mapM (pval . f) xs >>= mapM get+--+-- @parMap@ is commonly used for lists, where it has this specialised type:+--+-- > parMap :: NFData b => (a -> b) -> [a] -> Par [b]+--+parMap :: (Traversable t, NFData b) => (a -> b) -> t a -> Par (t b)+parMap f xs = mapM (pval . f) xs >>= mapM get++-- | Like 'parMap', but the function is a @Par@ monad operation.+--+-- > parMapM f xs = mapM (spawn . f) xs >>= mapM get+--+parMapM :: (Traversable t, NFData b) => (a -> Par b) -> t a -> Par (t b)+parMapM f xs = mapM (spawn . f) xs >>= mapM get++{-# SPECIALISE parMap :: (NFData b) => (a -> b) -> [a] -> Par [b] #-}+{-# SPECIALISE parMapM :: (NFData b) => (a -> Par b) -> [a] -> Par [b] #-}+++-- TODO: Perhaps should introduce a class for the "splittable range" concept.+data InclusiveRange = InclusiveRange Int Int++-- | Computes a binary map\/reduce over a finite range. The range is+-- recursively split into two, the result for each half is computed in+-- parallel, and then the two results are combined. When the range+-- reaches the threshold size, the remaining elements of the range are+-- computed sequentially.+--+-- For example, the following is a parallel implementation of+--+-- > foldl (+) 0 (map (^2) [1..10^6])+--+-- > parMapReduceRangeThresh 100 (InclusiveRange 1 (10^6))+-- > (\x -> return (x^2))+-- > (\x y -> return (x+y))+-- > 0+--+parMapReduceRangeThresh+ :: NFData a+ => Int -- ^ threshold+ -> InclusiveRange -- ^ range over which to calculate+ -> (Int -> Par a) -- ^ compute one result+ -> (a -> a -> Par a) -- ^ combine two results (associative)+ -> a -- ^ initial result+ -> Par a++parMapReduceRangeThresh threshold (InclusiveRange min max) fn binop init+ = loop min max+ where+ loop min max+ | max - min <= threshold =+ let mapred a b = do x <- fn b;+ result <- a `binop` x+ return result+ in foldM mapred init [min..max]++ | otherwise = do+ let mid = min + ((max - min) `quot` 2)+ rght <- spawn $ loop (mid+1) max+ l <- loop min mid+ r <- get rght+ l `binop` r++-- How many tasks per process should we aim for. Higher numbers+-- improve load balance but put more pressure on the scheduler.+auto_partition_factor :: Int+auto_partition_factor = 4++-- | \"Auto-partitioning\" version of 'parMapReduceRangeThresh' that chooses the threshold based on+-- the size of the range and the number of processors..+parMapReduceRange :: NFData a => InclusiveRange -> (Int -> Par a) -> (a -> a -> Par a) -> a -> Par a+parMapReduceRange (InclusiveRange start end) fn binop init =+ loop (length segs) segs+ where+ segs = splitInclusiveRange (auto_partition_factor * numCapabilities) (start,end)+ loop 1 [(st,en)] =+ let mapred a b = do x <- fn b;+ result <- a `binop` x+ return result+ in foldM mapred init [st..en]+ loop n segs =+ let half = n `quot` 2+ (left,right) = splitAt half segs in+ do l <- spawn$ loop half left+ r <- loop (n-half) right+ l' <- get l+ l' `binop` r+++-- TODO: A version that works for any splittable input domain. In this case+-- the "threshold" is a predicate on inputs.+-- parMapReduceRangeGeneric :: (inp -> Bool) -> (inp -> Maybe (inp,inp)) -> inp ->+++-- Experimental:++-- | Parallel for-loop over an inclusive range. Semantically equivalent+-- to+-- +-- > parFor (InclusiveRange n m) f = forM_ [n..m] f+--+-- except that the implementation will split the work into an+-- unspecified number of subtasks in an attempt to gain parallelism.+-- The exact number of subtasks is chosen at runtime, and is probably+-- a small multiple of the available number of processors.+--+-- Strictly speaking the semantics of 'parFor' depends on the+-- number of processors, and its behaviour is therefore not+-- deterministic. However, a good rule of thumb is to not have any+-- interdependencies between the elements; if this rule is followed+-- then @parFor@ has deterministic semantics. One easy way to follow+-- this rule is to only use 'put' or 'put_' in @f@, never 'get'.++parFor :: InclusiveRange -> (Int -> Par ()) -> Par ()+parFor (InclusiveRange start end) body =+ do+ let run (x,y) = for_ x (y+1) body+ range_segments = splitInclusiveRange (4*numCapabilities) (start,end)++ vars <- M.forM range_segments (\ pr -> spawn_ (run pr))+ M.mapM_ get vars+ return ()++splitInclusiveRange :: Int -> (Int, Int) -> [(Int, Int)]+splitInclusiveRange pieces (start,end) =+ map largepiece [0..remain-1] +++ map smallpiece [remain..pieces-1]+ where+ len = end - start + 1 -- inclusive [start,end]+ (portion, remain) = len `quotRem` pieces+ largepiece i =+ let offset = start + (i * (portion + 1))+ in (offset, offset + portion)+ smallpiece i =+ let offset = start + (i * portion) + remain+ in (offset, offset + portion - 1)++-- My own forM for numeric ranges (not requiring deforestation optimizations).+-- Inclusive start, exclusive end.+{-# INLINE for_ #-}+for_ :: Monad m => Int -> Int -> (Int -> m ()) -> m ()+for_ start end _fn | start > end = error "for_: start is greater than end"+for_ start end fn = loop start+ where+ loop !i | i == end = return ()+ | otherwise = do fn i; loop (i+1)+++
+ Control/Monad/Par/AList.hs view
@@ -0,0 +1,190 @@+{-# LANGUAGE CPP #-}+{-# OPTIONS_GHC -Wall -fno-warn-name-shadowing -fwarn-unused-imports #-}++-- | This module defines the 'AList' type, a list that supports+-- constant-time append, and is therefore ideal for building the+-- result of tree-shaped parallel computations.++module Control.Monad.Par.AList+ (+ -- * The 'AList' type and operations+ AList(..),+ empty, singleton, cons, head, tail, length, null, append,+ toList, fromList,+ -- * Operations to build 'AList's in the 'Par' monad+ parBuildThresh, parBuildThreshM,+ parBuild, parBuildM,+ )+where +++import Control.DeepSeq+import Prelude hiding (length,head,tail,null)+import qualified Prelude as P+import Control.Monad.Par++-- | List that support constant-time append (sometimes called+-- join-lists).+data AList a = ANil | ASing a | Append (AList a) (AList a) | AList [a]++instance NFData a => NFData (AList a) where+ rnf ANil = ()+ rnf (ASing a) = rnf a + rnf (Append l r) = rnf l `seq` rnf r+ rnf (AList l) = rnf l++#if 0+ data Tree a = Empty | Leaf a | Node (Tree a) a (Tree a)+ instance Traversable Tree+ traverse f Empty = pure Empty+ traverse f (Leaf x) = Leaf <$> f x+ traverse f (Node l k r) = Node <$> traverse f l <*> f k <*> traverse f r+#endif+++-- TODO: Finish me:+-- instance F.Foldable AList where+-- foldr fn init al = +-- case al of +-- ANil -> ++-- instance Functor AList where+-- fmap = undefined++-- -- Walk the data structure without introducing any additional data-parallelism.+-- instance Traversable AList where +-- traverse f al = +-- case al of +-- ANil -> pure ANil+-- ASing x -> ASing <$> f x++instance Show a => Show (AList a) where + show al = "fromList "++ show (toList al)++-- | /O(1)/ Append two 'AList's+append :: AList a -> AList a -> AList a+append ANil r = r+append l ANil = l+append l r = Append l r++{-# INLINE empty #-}+{-# INLINE singleton #-}+{-# INLINE fromList #-}++-- | /O(1)/ an empty 'AList'+empty :: AList a+empty = ANil++-- | /O(1)/ a singleton 'AList'+singleton :: a -> AList a+singleton = ASing++-- | /O(1)/ convert an ordinary list to an 'AList'+fromList :: [a] -> AList a+fromList = AList++-- | /O(1)/ prepend an element+cons :: a -> AList a -> AList a+cons x ANil = ASing x+cons x al = Append (ASing x) al+-- If we tracked length perhaps this could make an effort at balance.++-- | /O(n)/ take the head element of an 'AList'+--+-- NB. linear-time, because the list might look like this:+--+-- > (((... `append` a) `append` b) `append` c)+--+head :: AList a -> a+head al = + case loop al of+ Just x -> x + Nothing -> error "cannot take head of an empty AList"+ where + -- Alas there are an infinite number of representations for null:+ loop al =+ case al of + Append l r -> case loop l of + x@(Just _) -> x+ Nothing -> loop r+ ASing x -> Just x+ AList (h:_) -> Just h+ AList [] -> Nothing+ ANil -> Nothing++-- | /O(n)/ take the tail element of an 'AList'+tail :: AList a -> AList a+tail al = + case loop al of+ Just x -> x + Nothing -> error "cannot take tail of an empty AList"+ where + loop al =+ case al of + Append l r -> case loop l of + (Just x) -> Just (Append x r)+ Nothing -> loop r++ ASing _ -> Just ANil+ AList (_:t) -> Just (AList t)+ AList [] -> Nothing+ ANil -> Nothing++-- | /O(n)/ find the length of an 'AList'+length :: AList a -> Int+length ANil = 0+length (ASing _) = 1+length (Append l r) = length l + length r+length (AList l) = P.length l +++-- | /O(n)/ returns 'True' if the 'AList' is empty+null :: AList a -> Bool+null = (==0) . length ++-- | /O(n)/ converts an 'AList' to an ordinary list+toList :: AList a -> [a]+toList a = go a []+ where go ANil rest = rest+ go (ASing a) rest = a : rest+ go (Append l r) rest = go l $! go r rest+ go (AList xs) rest = xs ++ rest++-- TODO: Provide a strategy for @par@-based maps:+++appendM :: AList a -> AList a -> Par (AList a)+appendM x y = return (append x y)++-- | Build a balanced 'AList' in parallel, constructing each element as a+-- function of its index. The threshold argument provides control+-- over the degree of parallelism. It indicates under what number+-- of elements the build process should switch from parallel to+-- serial.+parBuildThresh :: NFData a => Int -> InclusiveRange -> (Int -> a) -> Par (AList a)+parBuildThresh threshold range fn =+ parMapReduceRangeThresh threshold range+ (return . singleton . fn) appendM empty++-- | Variant of 'parBuildThresh' in which the element-construction function is itself a 'Par' computation.+parBuildThreshM :: NFData a => Int -> InclusiveRange -> (Int -> Par a) -> Par (AList a)+parBuildThreshM threshold range fn =+ parMapReduceRangeThresh threshold range + ((fmap singleton) . fn) appendM empty++-- | \"Auto-partitioning\" version of 'parBuildThresh' that chooses the threshold based on+-- the size of the range and the number of processors..+parBuild :: NFData a => InclusiveRange -> (Int -> a) -> Par (AList a)+parBuild range fn =+ parMapReduceRange range (return . singleton . fn) appendM empty++-- | like 'parBuild', but the construction function is monadic+parBuildM :: NFData a => InclusiveRange -> (Int -> Par a) -> Par (AList a)+parBuildM range fn =+ parMapReduceRange range ((fmap singleton) . fn) appendM empty+++-- | A parMap over an AList can result in more balanced parallelism than+-- the default parMap over Traversable data types.+-- parMap :: NFData b => (a -> b) -> AList a -> Par (AList b)+
+ Control/Monad/Par/IList.hs view
@@ -0,0 +1,28 @@++-- ILists: lists whose cdr fields are IVars, filled in asynchronously+-- via Par computation.++-- This module mostly exists as a datatype to use in building other,+-- higher-level abstractions. (See OpenList and Stream.)++module Control.Monad.Par.IList + (+ IList(..)+ )+where++import Control.Monad.Par+import Control.DeepSeq++-- | An 'IList' is the equivalent of a lazy list in the 'Par' monad.+-- The tail of the list is an 'IVar', which allows the list to be+-- produced and consumed in parallel.+data IList a = Null | Cons { hd :: a, tl :: IVar (IList a) }++-- | To fully evaluate an 'IList' means to evaluate both the head+-- and tail. This does not evaluate the entire spine of the list+-- of course, because the tail is an 'IVar'.+instance NFData a => NFData (IList a) where+-- rnf Null = r0+ rnf Null = ()+ rnf (Cons a b) = rnf a `seq` rnf b
+ Control/Monad/Par/Internal.hs view
@@ -0,0 +1,292 @@+{-# LANGUAGE RankNTypes, NamedFieldPuns, BangPatterns,+ ExistentialQuantification, CPP+ #-}+{-# OPTIONS_GHC -Wall -fno-warn-name-shadowing -fno-warn-unused-do-bind #-}++-- | This module exposes the internals of the @Par@ monad so that you+-- can build your own scheduler or other extensions. Do not use this+-- module for purposes other than extending the @Par@ monad with new+-- functionality.++module Control.Monad.Par.Internal (+ Trace(..), Sched(..), Par(..),+ IVar(..), IVarContents(..),+ sched,+ runPar, runParAsync, runParAsyncHelper,+ new, newFull, newFull_, get, put_, put,+ pollIVar, yield,+ ) where+++import Control.Monad as M hiding (mapM, sequence, join)+import Prelude hiding (mapM, sequence, head,tail)+import Data.IORef+import System.IO.Unsafe+import Control.Concurrent hiding (yield)+import GHC.Conc hiding (yield)+import Control.DeepSeq+import Control.Applicative+-- import Text.Printf++-- ---------------------------------------------------------------------------++data Trace = forall a . Get (IVar a) (a -> Trace)+ | forall a . Put (IVar a) a Trace+ | forall a . New (IVarContents a) (IVar a -> Trace)+ | Fork Trace Trace+ | Done+ | Yield Trace++-- | The main scheduler loop.+sched :: Bool -> Sched -> Trace -> IO ()+sched _doSync queue t = loop t+ where + loop t = case t of+ New a f -> do+ r <- newIORef a+ loop (f (IVar r))+ Get (IVar v) c -> do+ e <- readIORef v+ case e of+ Full a -> loop (c a)+ _other -> do+ r <- atomicModifyIORef v $ \e -> case e of+ Empty -> (Blocked [c], reschedule queue)+ Full a -> (Full a, loop (c a))+ Blocked cs -> (Blocked (c:cs), reschedule queue)+ r+ Put (IVar v) a t -> do+ cs <- atomicModifyIORef v $ \e -> case e of+ Empty -> (Full a, [])+ Full _ -> error "multiple put"+ Blocked cs -> (Full a, cs)+ mapM_ (pushWork queue. ($a)) cs+ loop t+ Fork child parent -> do+ pushWork queue child+ loop parent+ Done ->+ if _doSync+ then reschedule queue+-- We could fork an extra thread here to keep numCapabilities workers+-- even when the main thread returns to the runPar caller...+ else do putStrLn " [par] Forking replacement thread..\n"+ forkIO (reschedule queue); return ()+-- But even if we don't we are not orphaning any work in this+-- threads work-queue because it can be stolen by other threads.+-- else return ()++ Yield parent -> do + -- Go to the end of the worklist:+ let Sched { workpool } = queue+ -- TODO: Perhaps consider Data.Seq here.+ -- This would also be a chance to steal and work from opposite ends of the queue.+ atomicModifyIORef workpool $ \ts -> (ts++[parent], ())+ reschedule queue++-- | Process the next item on the work queue or, failing that, go into+-- work-stealing mode.+reschedule :: Sched -> IO ()+reschedule queue@Sched{ workpool } = do+ e <- atomicModifyIORef workpool $ \ts ->+ case ts of+ [] -> ([], Nothing)+ (t:ts') -> (ts', Just t)+ case e of+ Nothing -> steal queue+ Just t -> sched True queue t+++-- RRN: Note -- NOT doing random work stealing breaks the traditional+-- Cilk time/space bounds if one is running strictly nested (series+-- parallel) programs.++-- | Attempt to steal work or, failing that, give up and go idle.+steal :: Sched -> IO ()+steal q@Sched{ idle, scheds, no=my_no } = do+ -- printf "cpu %d stealing\n" my_no+ go scheds+ where+ go [] = do m <- newEmptyMVar+ r <- atomicModifyIORef idle $ \is -> (m:is, is)+ if length r == numCapabilities - 1+ then do+ -- printf "cpu %d initiating shutdown\n" my_no+ mapM_ (\m -> putMVar m True) r+ else do+ done <- takeMVar m+ if done+ then do+ -- printf "cpu %d shutting down\n" my_no+ return ()+ else do+ -- printf "cpu %d woken up\n" my_no+ go scheds+ go (x:xs)+ | no x == my_no = go xs+ | otherwise = do+ r <- atomicModifyIORef (workpool x) $ \ ts ->+ case ts of+ [] -> ([], Nothing)+ (x:xs) -> (xs, Just x)+ case r of+ Just t -> do+ -- printf "cpu %d got work from cpu %d\n" my_no (no x)+ sched True q t+ Nothing -> go xs++-- | If any worker is idle, wake one up and give it work to do.+pushWork :: Sched -> Trace -> IO ()+pushWork Sched { workpool, idle } t = do+ atomicModifyIORef workpool $ \ts -> (t:ts, ())+ idles <- readIORef idle+ when (not (null idles)) $ do+ r <- atomicModifyIORef idle (\is -> case is of+ [] -> ([], return ())+ (i:is) -> (is, putMVar i False))+ r -- wake one up++data Sched = Sched+ { no :: {-# UNPACK #-} !Int,+ workpool :: IORef [Trace],+ idle :: IORef [MVar Bool],+ scheds :: [Sched] -- Global list of all per-thread workers.+ }+-- deriving Show++newtype Par a = Par {+ runCont :: (a -> Trace) -> Trace+}++instance Functor Par where+ fmap f m = Par $ \c -> runCont m (c . f)++instance Monad Par where+ return a = Par ($ a)+ m >>= k = Par $ \c -> runCont m $ \a -> runCont (k a) c++instance Applicative Par where+ (<*>) = ap+ pure = return++newtype IVar a = IVar (IORef (IVarContents a))+-- data IVar a = IVar (IORef (IVarContents a))++-- Forcing evaluation of a IVar is fruitless.+instance NFData (IVar a) where+ rnf _ = ()+++-- From outside the Par computation we can peek. But this is nondeterministic.+pollIVar :: IVar a -> IO (Maybe a)+pollIVar (IVar ref) = + do contents <- readIORef ref+ case contents of + Full x -> return (Just x)+ _ -> return (Nothing)+++data IVarContents a = Full a | Empty | Blocked [a -> Trace]+++{-# INLINE runPar_internal #-}+runPar_internal :: Bool -> Par a -> a+runPar_internal _doSync x = unsafePerformIO $ do+ workpools <- replicateM numCapabilities $ newIORef []+ idle <- newIORef []+ let states = [ Sched { no=x, workpool=wp, idle, scheds=states }+ | (x,wp) <- zip [0..] workpools ]++#if __GLASGOW_HASKELL__ >= 701 /* 20110301 */+ --+ -- We create a thread on each CPU with forkOnIO. The CPU on which+ -- the current thread is running will host the main thread; the+ -- other CPUs will host worker threads.+ --+ -- Note: GHC 7.1.20110301 is required for this to work, because that+ -- is when threadCapability was added.+ --+ (main_cpu, _) <- threadCapability =<< myThreadId+#else+ --+ -- Lacking threadCapability, we always pick CPU #0 to run the main+ -- thread. If the current thread is not running on CPU #0, this+ -- will require some data to be shipped over the memory bus, and+ -- hence will be slightly slower than the version above.+ --+ let main_cpu = 0+#endif++ m <- newEmptyMVar+ forM_ (zip [0..] states) $ \(cpu,state) ->+ forkOnIO cpu $+ if (cpu /= main_cpu)+ then reschedule state+ else do+ rref <- newIORef Empty+ sched _doSync state $ runCont (x >>= put_ (IVar rref)) (const Done)+ readIORef rref >>= putMVar m++ r <- takeMVar m+ case r of+ Full a -> return a+ _ -> error "no result"+++runPar :: Par a -> a+runPar = runPar_internal True++-- | An asynchronous version in which the main thread of control in a+-- Par computation can return while forked computations still run in+-- the background. +runParAsync :: Par a -> a+runParAsync = runPar_internal False++-- | An alternative version in which the consumer of the result has+-- | the option to "help" run the Par computation if results it is+-- | interested in are not ready yet.+runParAsyncHelper :: Par a -> (a, IO ())+runParAsyncHelper = undefined -- TODO: Finish Me.++-- -----------------------------------------------------------------------------++-- | creates a new @IVar@+new :: Par (IVar a)+new = Par $ New Empty++-- | creates a new @IVar@ that contains a value+newFull :: NFData a => a -> Par (IVar a)+newFull x = deepseq x (Par $ New (Full x))++-- | creates a new @IVar@ that contains a value (head-strict only)+newFull_ :: a -> Par (IVar a)+newFull_ !x = Par $ New (Full x)++-- | read the value in a @IVar@. The 'get' can only return when the+-- value has been written by a prior or parallel @put@ to the same+-- @IVar@.+get :: IVar a -> Par a+get v = Par $ \c -> Get v c++-- | like 'put', but only head-strict rather than fully-strict.+put_ :: IVar a -> a -> Par ()+put_ v !a = Par $ \c -> Put v a (c ())++-- | put a value into a @IVar@. Multiple 'put's to the same @IVar@+-- are not allowed, and result in a runtime error.+--+-- 'put' fully evaluates its argument, which therefore must be an+-- instance of 'NFData'. The idea is that this forces the work to+-- happen when we expect it, rather than being passed to the consumer+-- of the @IVar@ and performed later, which often results in less+-- parallelism than expected.+--+-- Sometimes partial strictness is more appropriate: see 'put_'.+--+put :: NFData a => IVar a -> a -> Par ()+put v a = deepseq a (Par $ \c -> Put v a (c ()))++-- | Allows other parallel computations to progress. (should not be+-- necessary in most cases).+yield :: Par ()+yield = Par $ \c -> Yield (c ())
+ Control/Monad/Par/OpenList.hs view
@@ -0,0 +1,454 @@+{-# LANGUAGE ScopedTypeVariables, CPP, BangPatterns #-}+{-# OPTIONS_GHC -fwarn-unused-imports #-}+-- -Wall -fno-warn-name-shadowing++-- | Some experimental support for 'OpenList's, which are streams in+-- the 'Par' monad that support constant-time append.++module Control.Monad.Par.OpenList+--module Main+ (+ OpenList(),+ empty, singleton, cons, head, tail, length,+ close, join,+ toList, fromList, toLazyList, + parMapM, parBuild, parBuildM, + openlist_tests, + chaintest, + async_test, lazy_chaintest+-- , main++ , IList(..), newCell+ )+where ++import Control.Monad hiding (join)+import Control.DeepSeq+import Control.Concurrent.MVar+import Control.Monad.Par hiding (parMapM)+import Control.Monad.Par.IList+import Control.Monad.Par.Internal++import Prelude hiding (length,head,tail,drop,take,null)+import qualified Prelude as P+-- import System.IO.Unsafe+import GHC.IO (unsafePerformIO, unsafeDupablePerformIO)+import Test.HUnit +import Debug.Trace++-- -----------------------------------------------------------------------------+-- Open Lists -- IVars at the tail.+--+-- These have some of the advantages of imperative lists, such as+-- constant time appending, while retaining determinism and having+-- O(1) access to the head of the list unlike tree-shaped lists+-- (e.g. append-based rather than cons-based).+++-- An OpenList must be handled functionally. Extending the list as+-- an effect will not change its tail pointer.+data OpenList a = OpenList (IList a) (IList a)++-- This is likewise a pretty meaningless NFData instance:+instance NFData a => NFData (OpenList a) where + rnf (OpenList hp tp) = rnf hp `seq` rnf tp +++-- | An empty open list. Supports further extension.+empty :: OpenList a+empty = OpenList Null Null++null :: OpenList a -> Bool+null (OpenList Null Null) = True+null _ = False++-- | A single element open list.+singleton :: a -> Par (OpenList a)+singleton x = + do pv <- new + let cell = Cons x pv+ return (OpenList cell cell)++-- TODO/FIXME: Need to decide whether there should be closed and open empty lists!!++-- | Terminate a non-empty open list so that it cannot be extended further.+close :: NFData a => OpenList a -> Par (OpenList a)+close orig@(OpenList Null _) = return orig+close orig@(OpenList _ tp) = do put (tl tp) Null; return orig+++-- This version ignores the tail pointer and seeks out the end of the+-- list (at the present time).+-- unsafeClose :: NFData a => OpenList a -> Par (OpenList a)+-- unsafeClose orig@(OpenList Null _) = return orig++++-- | Destructive append operation.+join :: NFData a => OpenList a -> OpenList a -> Par (OpenList a)+join (OpenList Null _) right = return right+join left (OpenList Null _) = return left +join (OpenList hp1 tp1) (OpenList hp2 tp2) =+ do put (tl tp1) hp2+ return (OpenList hp1 tp2)++-- | Head of an OpenList.+head :: OpenList a -> a+head (OpenList Null _) = error "cannot take head of null OpenList"+head (OpenList hp _) = hd hp++headCell (OpenList hp _) = OpenList hp hp +lastCell (OpenList _ tp) = OpenList tp tp++-- | Tail of an OpenList. Beware, if the list contains only one+-- element (e.g. the result of tail will be null), it must be CLOSED+-- for tail to work.+tail :: OpenList a -> Par (OpenList a)+-- NOTE: We could fix this limitation by adding a length field to the OpenList.+tail (OpenList Null _) = error "cannot take tail of null OpenList"+tail (OpenList hp tp) = + do nxt <- get (tl hp)+ case nxt of+ Null -> return empty+ _ -> return (OpenList nxt tp)+++drop :: NFData a => Int -> OpenList a -> Par (OpenList a)+drop 0 ls = return ls+drop n ls = do tl <- tail ls+ drop (n-1) tl++-- This copies a prefix and makes it open once again irrespective of+-- whether the input list is open or closed.+take :: NFData a => Int -> OpenList a -> Par (OpenList a)+take 0 ls = return empty+take n ls = do tl <- tail ls+ rest <- take (n-1) tl+ cons (head ls) rest++-- Take the length of a closed OpenList.+-- length :: OpenList a -> Par Int+length (OpenList Null _) = return 0+-- length (OpenList (Cons a _) (Cons b _)) | a == b = return 1+length ls = do t <- tail ls + len <- length t+ return (len+1)++-- | Add an element to the front of an OpenList. Works irrespective+-- | of whether the input is closed.+cons :: NFData a => a -> OpenList a -> Par (OpenList a)+-- Careful, consing should not close the openlist:+cons car (OpenList Null _) = singleton car+cons car (OpenList hp tp) = + do cdr <- newFull_ hp+ return (OpenList (Cons car cdr) tp)++newCell x = do pv <-new; return (Cons x pv)++-- | Convert a list to an OpenList, open to extension at the tail.+fromList :: NFData a => [a] -> Par (OpenList a)+fromList [] = return empty+fromList (h:t) = + -- This function is inefficient and could be replaced with an additional IList data constructor.+ do head <- newCell h+ rest <- loop head t+ return (OpenList head rest)+ where + loop last [] = return last+ loop last (h:t) = + do cell <- newCell h+ put (tl last) cell+ loop cell t++-- | Convert a CLOSED OpenList to a list. +toList :: NFData a => (OpenList a) -> Par [a] +-- Note: presently not tail-recursive:+toList (OpenList hp _) = loop hp+ where + loop Null = return []+ loop (Cons head pv) = + do + rest <- get pv+ converted <- loop rest+ return (head : converted)++-- Strict map over closed lists.+-- +-- parMap for OpenLists does not support a nice divide-and-conquer.+-- (Well, it would support the appending if we were willing to scan ahead to find the length.)+-- OpenLists are not Traversable... so we can't just use Par.parMap.+--+-- TODO: Perhaps this should use a strategy for each element:+-- parMapM :: NFData b => (a -> Par b) -> OpenList a -> Par (OpenList b)+parMapM _ (OpenList Null _) = return empty+-- parMapM fn (OpenList (Cons a _) (Cons b _)) | a == b = fn a >>= singleton +parMapM fn ls = + do h <- spawn (fn (head ls))+ t <- tail ls+ h' <- get h+ t2 <- parMapM fn t+ cons h' t2++-- maybe the following too?+-- parMapM_ :: (a -> Par ()) -> OpenList a -> Par () ++-- | Build an OpenList with a divide-and-conquer parallel strategy.+parBuild :: NFData a => InclusiveRange -> (Int -> a) -> Par (OpenList a)+parBuild range fn =+ parMapReduceRange range (singleton . fn) join empty++-- | Build an OpenList with a divide-and-conquer parallel strategy,+-- allowing nested parallelism in the per-element computation.+parBuildM :: NFData a => InclusiveRange -> (Int -> Par a) -> Par (OpenList a)+parBuildM range fn =+ parMapReduceRange range ((>>= singleton) . fn) join empty+++-- | OpenLists can only be printed properly in the Par monad. @show@+-- on an open list will only give a hint -- what the first and last+-- elements of the openlist are.+instance Show a => Show (OpenList a) where + show (OpenList Null _) = "OpenList []"+ show (OpenList (Cons fst _) (Cons lst _)) = + "OpenList ["++show fst++".."++ show lst ++"]"++ ++debugshow (OpenList (Cons h1 _) (Cons h2 _)) = "Cons|Cons|eq/"++show(h1==h2)+debugshow (OpenList Null Null) = "Null|Null"+debugshow (OpenList Null (Cons _ _)) = error$ "invalid Null|Cons openlist"+debugshow (OpenList (Cons _ _) Null) = error$ "invalid Cons|Null openlist"++-- Check the length of an openlist from head pointer to tail pointer+-- (not including anything present beyond the tail pointer).+-- WARNING: ASSUMES UNIQUE ELEMENTS:+debuglength :: Eq a => OpenList a -> Par Int+debuglength (OpenList Null Null) = return 0+debuglength orig@(OpenList (Cons hp1 tp1) (Cons hp2 tp2))+ | hp1 == hp2 = return 1+ | otherwise = do rest <- tail orig+ sum <- debuglength rest+ return (1 + sum)++-- -----------------------------------------------------------------------------+-- Synchronization using native Haskell IVars (e.g. MVars).++-- The MList datatype is internal to the module.+-- These MVars are only written once:+data MList a = MNull | MCons (a, MVar (MList a))++_unsafe_io :: IO a -> Par a+_unsafe_io io = let x = unsafePerformIO io in+ x `seq` return x++_unsafe_dupable :: IO a -> Par a+_unsafe_dupable io = + let x = unsafeDupablePerformIO io in + x `seq` return x++-- Return a lazy list:+mListToList :: MList a -> [a]+mListToList MNull = []+mListToList (MCons(hd,tl)) = + let rest = unsafeDupablePerformIO$ + do tl' <- readMVar tl + return (mListToList tl')+ in (hd : rest)++iListToMList :: IList a -> Par (MList a)+iListToMList Null = return MNull+iListToMList il = + do mv <- _unsafe_dupable newEmptyMVar+ fork $ do t <- get (tl il)+ r <- iListToMList t+ _unsafe_io$ putMVar mv r+ return (MCons (hd il, mv))++-- | Asynchronously convert an OpenList to a lazy list. Returns immediately.+toLazyList :: OpenList a -> Par [a]+toLazyList (OpenList head _) = iListToMList head >>= return . mListToList +-- toLazyList ol = toMList ol >>= return . mListToList +++++++-- -----------------------------------------------------------------------------+-- Testing++test_ol0 = runPar (cons 'a' empty >>= cons 'b' >>= close >>= tail >>= tail >>= length)++test_ol1 :: Int+test_ol1 = runPar$ do l :: OpenList Int <- join empty empty+ length l++test_ol2 :: String+test_ol2 = show$ runPar$ do + ls1 <- fromList [10,11,12]+ ls2 <- singleton (5::Int)+ join ls1 ls2++test_ol3 :: [Int]+test_ol3 = runPar$ do ol :: OpenList Int <- fromList [1..10]+ close ol+ toList ol++test_ol4 :: Int+test_ol4 = runPar$ do ol <- fromList [1..10] + t1 <- tail ol+ t2 <- tail t1+ return (head t2)++test_ol5 :: Int+test_ol5 = runPar$ fromList ([1..10] :: [Int]) >>= close >>= length++test_ol6 :: [Int]+test_ol6 = runPar$ do+ l1 <- fromList [1..10]+ close l1+ l2 <- parMapM (return . (+ 1)) l1+ close l2+ toList l2+++test_ol7 :: [Int]+test_ol7 = runPar$ do + a <- singleton 1+ b <- singleton 2+ join a b+ close b+ toLazyList a++test_ol8 :: [Int]+test_ol8 = runPar$ do + a <- singleton 1+ b <- singleton 2+ c <- singleton 3+ d <- singleton 4+ join c d+ join a b+ join b c+ close d+ toLazyList a++test_ll :: [Int]+test_ll = runPar$+ do l <- fromList [1..1000]+ close l + toLazyList l++chaintest :: Int -> Par (IList Int)+chaintest 0 = error "must have chain length >= 1"+chaintest len = loop 0 len + where + loop i 1 = do tl <- if i == len-1 + then newFull_ Null + else new+ when (i == len-1) (print_$ " == GOT END: "++show i)+ return (Cons i tl)+ loop i n =+ do let half = n `quot` 2+ ifst <- spawn_$ loop i half + fork $ do + snd <- loop (i+half) half+ fst <- get ifst+ lastfst <- dropIList (half-1) fst + put (tl lastfst) snd+ return () + get ifst++dropIList :: NFData a => Int -> IList a -> Par (IList a)+dropIList 0 ls = return ls+dropIList n ls = do rest <- get (tl ls)+ dropIList (n-1) rest++-- lazy_chaintest i = chaintest i >>= toLazyList+lazy_chaintest :: Int -> Par [Int]+lazy_chaintest i = do il <- chaintest i + ml <- iListToMList il+ return (mListToList ml)++-- If we create a large, lazy chain, taking just the head should be quick.+async_test = + do putStrLn "BeginTest"+-- let lazy = runParAsync$ lazy_chaintest 1048576+-- let lazy = runParAsync$ lazy_chaintest 32768+ let lazy = runParAsync$ lazy_chaintest 1024+-- let lazy = runPar$ lazy_chaintest 1024+ putStrLn$ "Resulting list "++ show lazy+ putStrLn$ "Got head: "++ show (P.take 3 lazy)+ putStrLn "EndTest"++--------------------------------------------------------------------------------++print_ msg = trace msg $ return ()++dbg0 = debugshow$ runPar$ singleton 'a' >>= close ++-- This one is an error:+err1 = debugshow$ runPar$ singleton 'a' >>= tail >>= close +-- But this will work:+dbg1 = debugshow$ runPar$ fromList "ab" >>= tail >>= close ++dbg2 = debugshow$ runPar$ singleton 'a' >>= close >>= tail ++-- This is invalid:+err2 = debugshow$ runPar$ singleton 'a' >>= tail ++-- TODO: HUnit These.+openlist_tests :: Test+openlist_tests = + TestList + [+ -- First a few small, unnamed tests:+ 0 ~=? runPar (length (empty :: OpenList Int)),+ "a" ~=? runPar (singleton 'a' >>= close >>= toList),+ 1 ~=? runPar (singleton 'a' >>= close >>= length),+ 1 ~=? runPar (cons 'b' empty >>= close >>= length),++ TestLabel "singleton, close" $ "Cons|Cons|eq/True" ~=? dbg0,+ TestLabel "tail then close - SKETCHY" $ "Cons|Cons|eq/True" ~=? dbg1,+ TestLabel "close then tail" $ "Null|Null" ~=? dbg2,+-- TestLabel "tail no close" $ "" ~=? dbg3,++ TestLabel "tail of singleton" $ + 0 ~=? runPar (singleton 'a' >>= close >>= tail >>= length),+ TestLabel "tail tail of cons cons" $ + 0 ~=? test_ol0,++ TestLabel "join of two empty's still length zero" $ + 0 ~=? test_ol1,+ TestLabel "test show instance" $ + "OpenList [10..5]" ~=? test_ol2,++ TestLabel "toList" $ + [1..10] ~=? test_ol3,++ TestLabel "head . tail . tail" $ + 3 ~=? test_ol4,++ TestLabel "length . fromList" $ + 10 ~=? test_ol5,++ TestLabel "test parMap" $ + [2..11] ~=? test_ol6,++ TestLabel "test 7" $ + [1,2] ~=? test_ol7,++ TestLabel "test 8" $ + [1..4] ~=? test_ol8,++ TestLabel "test lazy list conversion" $ + [1..1000] ~=? test_ll,++ TestLabel "chaintest" $+ [0..511] ~=? runPar (lazy_chaintest 512),++ TestLabel "asynchronous chaintest" $+ [0..511] ~=? runParAsync (lazy_chaintest 512)++ ]++main = async_test
+ Control/Monad/Par/Stream.hs view
@@ -0,0 +1,367 @@+{-# LANGUAGE BangPatterns, CPP #-}+{-# OPTIONS_GHC -fno-warn-name-shadowing -fwarn-unused-imports #-}+-- -Wall ++-- A module for stream processing built on top of Control.Monad.Par++-- (In the future may want to look into the stream interface used by+-- the stream fusion framework.)++#define DEBUGSTREAMS++module Control.Monad.Par.Stream + ( + streamMap, streamScan, streamFold+ , countupWin, generate+ , runParList, toListSpin+ , measureRate, measureRateList+ , browseStream+ , Stream, Window, WStream++ -- TEMP:+ , one_second, commaint+ )+where+import Control.Monad+import Control.Monad.Par as P+import Control.Monad.Par.IList+import Control.DeepSeq++--import qualified Data.Array.Unboxed as U+import Data.Array.Unboxed as U+import Data.Array.CArray as C+import Data.Int+import Data.Word+import Data.List (intersperse)+import Data.List.Split (chunk)++import Foreign.Storable++import System.CPUTime+import System.CPUTime.Rdtsc+import GHC.Conc as Conc+import System.IO+import GHC.IO (unsafePerformIO, unsafeDupablePerformIO, unsafeInterleaveIO)+++import Debug.Trace+import Control.Monad.Par.Logging++debugflag = True++--------------------------------------------------------------------------------+-- Types++type Stream a = IVar (IList a)++-- A windowed stream passes chunks of stream elements.+type WStream a = Stream (Window a)++#define CARRAY+#ifdef CARRAY+type Window a = CArray Int a+#else+type Window a = U.UArray Int a+#endif+++--------------------------------------------------------------------------------+-- Stream Operators++-- | This version applies a function to every element in a stream,+-- exposing data parallelism and pipeline parallelism.+streamMapDP :: NFData b => (a -> b) -> Stream a -> Par (Stream b)+streamMapDP fn instrm = + do outstrm <- new+ fork$ loop instrm outstrm+ return outstrm+ where+ loop instrm outstrm = + do + ilst <- get instrm+ case ilst of + Null -> put outstrm Null -- End of stream.+ Cons h t -> + do newtl <- new+ h' <- pval (fn h) ++-- WARNING: This only makes sense with continuation-stealing.. With child stealing this will go crazy.+ fork$ loop t newtl+ h'' <- get h'+ put outstrm (Cons h'' newtl)+ ++-- This version exposes pipeline parallelism but no data parallelism.+-- It shouldn't be necessary if fork is sufficiently efficient and if+-- work stealing is done right.+streamMap :: NFData b => (a -> b) -> Stream a -> Par (Stream b)+streamMap fn instrm = + do outstrm <- new+ fork$ loop instrm outstrm+ return outstrm+ where+ loop instrm outstrm = + do + ilst <- get instrm+ case ilst of + Null -> put outstrm Null -- End of stream.+ Cons h t -> + do newtl <- new+ put outstrm (Cons (fn h) newtl)+ loop t newtl+++-- | Applies a stateful kernel to the stream. Output stream elements match input one-to-one.+-- streamScan :: (NFData b, NFData c) => +streamScan :: (NFData a, NFData b, NFData c) => -- <- TEMP, don't need NFData a in general.+ (a -> b -> (a,c)) -> a -> Stream b -> Par (Stream c)+streamScan fn initstate instrm = + do outstrm <- new+ fork$ loop initstate instrm outstrm+ return outstrm+ where+#ifdef DEBUGSTREAMS+ -- Create a task log for each unique input stream fed to this function:+ tasklog = unsafeNewTaskSeries (nameFromValue instrm)+#endif++ loop state instrm outstrm = + do + ilst <- get instrm+ case ilst of + Null -> put outstrm Null -- End of stream.+ Cons h t -> + do newtl <- new+ let (newstate, outp) = +#ifdef DEBUGSTREAMS+ timePure tasklog$ fn state h+#else+ fn state h+#endif+ put outstrm (Cons outp newtl)+ loop newstate t newtl++-- TODO: streamMapM -- monadic version. Define the non-monadic one in+-- terms of it and watch for performance regression.+++-- TODO: More flexible version that passes an "emit" function to the+-- kernel so that it may produce zero output elements or more than one.+-- This also enables nested parallelism within the kernel.+-- +-- streamKernel :: ((c -> Par ()) -> a -> b -> Par ()) -> a -> Stream b -> Par (Stream c)+--+-- ALSO: Can have a "concat" operator for streams of lists where+-- streamScan . concat rewrites to streamKernel perhaps...++++-- | Reduce a stream to a single value. This function will not return+-- until it reaches the end-of-stream.+streamFold :: (a -> b -> a) -> a -> Stream b -> Par a+streamFold fn acc instrm = + do ilst <- get instrm+ case ilst of + Null -> return acc + Cons h t -> streamFold fn (fn acc h) t ++-- | Generate a stream of the given length by applying the function to each index (starting at zero).+-- +-- WARNING, this source calls yield, letting other par computations+-- run, but there is no backpressure. Thus if the source runs at a+-- higher rate than its consumer, buffered stream elements accumulate.+generate :: NFData a => Int -> (Int -> a) -> Par (Stream a)+-- NOTE: I don't currently know of a good way to do backpressure+-- directly in this system... but here are some other options: +--+-- (1) we can use timers and look at maximum sustained rate. ++-- (2) Also, we can use coarse grained global barriers. That is, we+-- can produce some number of output elements, wait until quiescence+-- of all Par computations, and then produce more.++-- (3) We can register computations that should only execute when a+-- worker goes idle. This is a simple form of priority scheduling.+generate size fn = + do outstrm <- new+ fork$ loop (0::Int) outstrm+ return outstrm+ where + loop n strm | n == size = + do when debugflag (print_$ " [generate] Done. Produced "++ show size++" elements.\n")+ put strm Null+ return ()+ loop n strm = + do + newtl <- new+ put strm (Cons (fn n) newtl)+ P.yield -- This is necessary to avoid starving others when there+ -- aren't enough worker threads to go around.+ loop (n+1) newtl+++-- | Create a [windowed] stream of consecutive integers. Generates at+-- least the target number of elements windowed into segments of a+-- specified size.+countupWin :: (Storable a, NFData a, Num a) => + Int -> Int -> Par (WStream a)+countupWin bufsize target = + generate num fn+ where + num = case r of 0 -> q+ _ -> q+1+ (q,r) = quotRem target bufsize+ fn n = + let start = n * bufsize in+ array (start,start + bufsize-1)+ [(i, fromIntegral (n + fromIntegral i)) + | i <- [start .. start + bufsize-1]]++++measureRate :: Stream a -> IO ()+measureRate strm = + do lazyls <- toListSpin strm+ measureRateList lazyls++measureRateList :: [a] -> IO ()+measureRateList lazyls = + do + t0 <- getTime+ print_$ " [measureRate] Counting stream rate starting at time: "++ show t0+ loop t0 t0 (0::Int64) (0::Int64) lazyls+ + where + loop _ _ _ n [] = + do print_$ " [measureRate] Hit end of stream after "++show n++" elements."+ return ()++ loop start time lastN n (h:t) = + do + time2 <- getTime+ if time2 - time > one_second then do+ (print_$ " [measureRate] current rate: "++show (n+1-lastN) ++ + " Total elems&time "++ commaint (n+1)++ " " ++commaint (time2-start))+-- print_ (show (n+1))+ loop start time2 (n+1) (n+1) t+ else do+ loop start time lastN (n+1) t+++-- | Use the keyboard to interactively browse through stream elements.+browseStream :: Show a => Stream a -> IO ()+browseStream strm = + do putStrLn$ "[browseStream] Beginning interactive stream browser, press enter for more elements:"+ ls <- toListSpin strm+ loop 0 ls+ where + loop n ls = + do putStr$ show n ++ "# "+ hFlush stdout+ c <- getChar + if c == '\EOT' -- User presses ctrl D to exit.+ then putStrLn$ "[browseStream] Ctrl-D pressed, exiting."+ else case ls of + [] -> putStrLn$ "[browseStream] Reached end of stream after "++show n++" elements."+ (h:t) -> do print h+ loop (n+1) t+++--------------------------------------------------------------------------------+-- Conversion:++-- Convert a stream to a lazy list. Spin wait (with yield) until stream elements are available.+toListSpin :: Stream a -> IO [a]+toListSpin strm = + do x <- pollIVar strm+ case x of+ Nothing -> do Conc.yield -- run other GHC threads+ toListSpin strm -- spin wait+ Just (ils) -> + case ils of + Null -> return []+ Cons h t -> return (h : unsafePerformIO (unsafeInterleaveIO (toListSpin t)))+++-- TODO: If it is unavailable we should help run the computation and then try again.+-- This version will do runParAsync itself:++-- Run a Par computation to produce a stream. Convert that stream to a lazy list.+runParList :: Par (Stream a) -> [a]+runParList = + undefined+-- runForList parcomp = loop (runParAsync parcomp) +-- where +-- loop strm = +-- do x <- pollIVar strm+-- case x of+-- Nothing -> +-- -- For now we just spin:+-- do yield -- run other GHC threads+-- loop strm+-- Just (ils) -> +-- case ils of +-- Null -> return []+-- Cons h t -> return (h : unsafePerformIO (unsafeInterleaveIO (loop t)))+++++--------------------------------------------------------------------------------+-- Helpers and Scrap:++print_ msg = trace msg $ return ()++_unsafe_io :: IO a -> Par a+_unsafe_io io = let x = unsafePerformIO io in+ x `seq` return x++_unsafe_dupable :: IO a -> Par a+_unsafe_dupable io = + let x = unsafeDupablePerformIO io in + x `seq` return x++-- This version simply busy-waits to stay on the same core:+measure_freq2 :: IO Word64+measure_freq2 = do +-- let second = 1000 * 1000 * 1000 * 1000 -- picoseconds are annoying+ let tenth = 100 * 1000 * 1000 * 1000 -- picoseconds are annoying + coef = 10+ t1 <- rdtsc + start <- getCPUTime+ let loop !n !last = + do t2 <- rdtsc + when (t2 < last) $+ putStrLn$ "WARNING, measure_freq2: COUNTERS WRAPPED "++ show (last,t2) + cput <- getCPUTime +-- if (cput - start < second) + if (cput - start < tenth)+ then loop (n+1) t2+ else return (n,t2)+ (n,t2) <- loop 0 t1+ putStrLn$ " Approx getCPUTime calls per second: "++ commaint (coef * n)+ when (t2 < t1) $ + putStrLn$ "WARNING: rdtsc not monotonically increasing, first "++show t1++" then "++show t2++" on the same OS thread"++ return$ coef * fromIntegral (t2 - t1)++commaint :: Integral a => a -> String+commaint n = + reverse $+ concat $+ intersperse "," $ + chunk 3 $ + reverse (show n)++-- Having trouble with this:+-- getTime = getCPUTime+-- one_second = 1000000000000 -- picoseconds+getTime = rdtsc+one_second = unsafePerformIO$ measure_freq2+++instance NFData (U.UArray a b) where + rnf !arr = ()++instance NFData (C.CArray a b) where + rnf !arr = ()
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Simon Marlow 2011++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 Simon Marlow 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.
+ Setup.hs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+import Distribution.Simple+main = defaultMain
+ examples/Makefile view
@@ -0,0 +1,33 @@+include common.mk++BENCHMARKS= queens.hs mandel.hs blackscholes.hs nbody.hs parfib.hs primes.hs \+ cholesky.hs parfib.hs coins.hs++# binomial_lattice.hs+EXES= $(BENCHMARKS:.hs=.exe)++OTHEREXES= matmult/matmult.exe minimax/minimax.exe sumeuler/sumeuler.exe \+ stream/simple1_measureSrc.exe++ALLEXES= $(EXES) $(OTHEREXES)++all: $(EXES)+ (cd sumeuler; $(MAKE))+ (cd matmult; $(MAKE))+ (cd minimax; $(MAKE))+ (cd stream; $(MAKE))+ (cd partree; $(MAKE))++%.exe : %.hs $(ALLPARSRC)+ $(GHC) -O2 --make -i.. $< -o $@ -threaded -rtsopts++runtests: + ./run_tests.sh $(ALLEXES) ++clean:+ rm -f $(ALLEXES) *.o *.hi + (cd sumeuler; $(MAKE) clean)+ (cd matmult; $(MAKE) clean)+ (cd minimax; $(MAKE) clean)+ (cd stream; $(MAKE) clean)+ (cd partree; $(MAKE) clean)
+ examples/PortablePixmap.lhs view
@@ -0,0 +1,127 @@++\begin{verbatim}+ppm(5) FILE FORMATS ppm(5)++NAME+ ppm - portable pixmap file format++DESCRIPTION+ The portable pixmap format is a lowest common denominator+ color image file format. The definition is as follows:++ - A "magic number" for identifying the file type. A ppm+ file's magic number is the two characters "P3".++ - Whitespace (blanks, TABs, CRs, LFs).++ - A width, formatted as ASCII characters in decimal.++ - Whitespace.++ - A height, again in ASCII decimal.++ - Whitespace.++ - The maximum color-component value, again in ASCII decimal.++ - Whitespace.++ - Width * height pixels, each three ASCII decimal values+ between 0 and the specified maximum value, starting at the+ top-left corner of the pixmap, proceding in normal English+ reading order. The three values for each pixel represent+ red, green, and blue, respectively; a value of 0 means+ that color is off, and the maximum value means that color+ is maxxed out.++ - Characters from a "#" to the next end-of-line are ignored+ (comments).++ - No line should be longer than 70 characters.++ Here is an example of a small pixmap in this format:+ P3+ # feep.ppm+ 4 4+ 15+ 0 0 0 0 0 0 0 0 0 15 0 15+ 0 0 0 0 15 7 0 0 0 0 0 0+ 0 0 0 0 0 0 0 15 7 0 0 0+ 15 0 15 0 0 0 0 0 0 0 0 0++ Programs that read this format should be as lenient as pos-+ sible, accepting anything that looks remotely like a pixmap.++ There is also a variant on the format, available by setting+ the RAWBITS option at compile time. This variant is++Sun Release 4.1 Last change: 15 September 1990 1++ppm(5) FILE FORMATS ppm(5)++ different in the following ways:++ - The "magic number" is "P6" instead of "P3".++ - The pixel values are stored as plain bytes, instead of+ ASCII decimal.++ - Whitespace is not allowed in the pixels area, and only a+ single character of whitespace (typically a newline) is+ allowed after the maxval.++ - The files are smaller and many times faster to read and+ write.++ Note that this raw format can only be used for maxvals less+ than or equal to 255. If you use the ppm library and try to+ write a file with a larger maxval, it will automatically+ fall back on the slower but more general plain format.++SEE ALSO+ giftoppm(1), gouldtoppm(1), ilbmtoppm(1), imgtoppm(1),+ mtvtoppm(1), pcxtoppm(1), pgmtoppm(1), pi1toppm(1), pict-+ toppm(1), qrttoppm(1), rawtoppm(1), rgb3toppm(1),+ spctoppm(1), sputoppm(1), tgatoppm(1), ximtoppm(1),+ xpmtoppm(1), ppmtogif(1), ppmtoicr(1), ppmtoilbm(1),+ ppmtopcx(1), ppmtopgm(1), ppmtopi1(1), ppmtopict(1),+ ppmtops(1), ppmtopuzz(1), ppmtorgb3(1), ppmtouil(1),+ ppmtoxpm(1), ppmhist(1), ppmmake(1), ppmpat(1), ppmquant(1),+ ppmquantall(1), ppmrelief(1), pnm(5), pgm(5), pbm(5)++AUTHOR+ Copyright (C) 1989, 1991 by Jef Poskanzer.++Sun Release 4.1 Last change: 15 September 1990 2+\end{verbatim}+\begin{code}+module PortablePixmap where++data PixMap = Pixmap Integer Integer Int [(Int,Int,Int)]++createPixmap::Integer -> Integer -> Int -> [(Int,Int,Int)] -> PixMap+createPixmap width height max colours = Pixmap width height max colours++instance Show PixMap where+ showsPrec prec (Pixmap x y z rgbs) = showHeader x y z . showRGB rgbs+++showHeader::Integer -> Integer -> Int -> ShowS+showHeader x y z = showString "P6\n" . showBanner .+ shows x . showReturn .+ shows y . showReturn .+ shows z . showReturn++showRGB::[(Int,Int,Int)] -> ShowS+showRGB [] = id+showRGB ((r,g,b):rest) = showChar (toEnum r) .+ showChar (toEnum g) .+ showChar (toEnum b) .+ showRGB rest++showSpace = showChar ' '+showReturn = showChar '\n'++showBanner = showString "# Portable pixmap created by Haskell Program :\n" .+ showString "#\tPortablePixmap.lhs (Jon.Hill 28/5/92)\n"+\end{code}
+ examples/benchlist.txt view
@@ -0,0 +1,27 @@+# This is a default set of benchmarks reasonable for a powerful four core machine.++parfib monad 36+parfib sparks 36++blackscholes 10000 15000000++cholesky 1000 50 cholesky_matrix1000.dat++nbody 13000++# mandel 300 300 4000+mandel 2000 2000 3000000++coins 8 1250++stream/disjoint_working_sets_pipeline monad 4 256 10 10000+stream/disjoint_working_sets_pipeline sparks 4 256 10 10000++partree/partree 600 20++# What should the arguments be here:+# minimax/minimax ? ? ++# These don't match the naming convention at the moment.+matmult/matmult 768 0 64+sumeuler/sumeuler 38 8000 100
+ examples/benchmark.sh view
@@ -0,0 +1,226 @@+#!/bin/bash++# Runs benchmarks. Simon Marlow has his own setup. This is just temporary.++# ---------------------------------------------------------------------------+# Usage: [set env vars] ./benchmark.sh++# Call it with environment variable SHORTRUN=1 to get a shorter run for+# testing rather than benchmarking.++# Call it with THREADSETTINGS="1 2 4" to run with # threads = 1, 2, or 4.++# Call it with KEEPGOING=1 to keep going after the first error.++# Call it with TRIALS=N to control the number of times each benchmark is run.+# ---------------------------------------------------------------------------+++# Settings:+# ----------------------------------------++if [ "$THREADSETTINGS" == "" ] +then THREADSETTINGS="4"+#then THREADSETTINGS="0 1 2 3 4"+fi++if [ "$GHC" == "" ]; then GHC=ghc; fi++# HACK: with all the intermachine syncing and different version control systems I run into permissions problems sometimes.+chmod +x ./ntime* ./*.sh+++# Where to put the timing results:+RESULTS=results.dat+if [ -e $RESULTS ];+then BAK="$RESULTS".bak.`date +%s`+ echo "Backing up old results to $BAK"+ mv $RESULTS $BAK+fi++# How many times to run a process before taking the best time:+if [ "$TRIALS" == "" ]; then + TRIALS=1+fi++# Determine number of hardware threads on the machine:+ if [ -d /sys/devices/system/cpu/ ]; # linux+ then + MAXTHREADS=`ls /sys/devices/system/cpu/ | grep "cpu[0123456789]*$" | wc -l`+ echo "Detected the number of CPUs on the machine to be $MAXTHREADS"+ elif [ `uname` == "Darwin" ];+ then MAXTHREADS=`sysctl -n hw.ncpu`+ else MAXTHREADS=2+ fi ++GHC_FLAGS="$GHC_FLAGS -O2 -rtsopts"+GHC_RTS="$GHC_RTS -qa"++# ================================================================================+echo "# TestName Variant NumThreads MinTime MedianTime MaxTime" > $RESULTS+echo "# "`date` >> $RESULTS+echo "# "`uname -a` >> $RESULTS+echo "# "`$GHC -V` >> $RESULTS+echo "# "+echo "# Running each test for $TRIALS trials." >> $RESULTS+echo "# ... with default compiler options: $GHC_FLAGS" >> $RESULTS+echo "# ... with default runtime options: $GHC_RTS" >> $RESULTS++cnt=0++function check_error() +{+ CODE=$1+ MSG=$2+ # Error code 143 was a timeout+ if [ "$CODE" == "143" ]+ then echo " # Return code $CODE Params: $GHC_FLAGS, RTS $GHC_RTS " | tee -a $RESULTS+ echo " # Process TIMED OUT!!" | tee -a $RESULTS+ elif [ "$CODE" != "0" ]+ then echo " # $MSG" | tee -a $RESULTS+ echo " # Error code $CODE Params: $GHC_FLAGS, RTS $GHC_RTS " | tee -a $RESULTS+ echo "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"+ if [ "$KEEPGOING" == "" ];+ then exit $CODE+ fi+ fi+}+++function runit() +{+ cnt=$((cnt+1))+ echo + echo "--------------------------------------------------------------------------------"+ echo " Running Config $cnt: $test variant threads $NUMTHREADS "+ echo "--------------------------------------------------------------------------------"+ echo + echo "(In directory `pwd`)"+ if [ "$NUMTHREADS" != "0" ] && [ "$NUMTHREADS" != "" ]+ then export RTS=" $GHC_RTS -s -N$NUMTHREADS "+ export FLAGS=" $GHC_FLAGS -threaded "+ else export RTS=""+ export FLAGS=" $GHC_FLAGS "+ fi++ CONTAININGDIR=`dirname $test`++ # We compile the test case using runcnc:+ if [ -e "$test".hs ]; then + FINALARGS="-i../ -i`dirname $test` $FLAGS $test.hs -o $test.exe"+ echo "Compiling with a single GHC command: "+ echo " $GHC $FINALARGS"+ $GHC $FINALARGS+ check_error $? "ERROR: compilation failed."++ elif [ -d "$CONTAININGDIR" ] && + [ "$CONTAININGDIR" != "." ] && + [ -e "$CONTAININGDIR/Makefile" ]; then+ echo " ** Benchmark appears in a subdirectory with Makefile. Using it."+ echo " ** WARNING: Can't currently control compiler options for this benchmark!"+ (cd "$CONTAININGDIR/"; make)++ else+ echo "ERROR: File does not exist: $test.hs"+ exit 1+ fi+++ echo "Executing $NTIMES $TRIALS $test.exe $ARGS +RTS $RTS -RTS "+ if [ "$SHORTRUN" != "" ]; then export HIDEOUTPUT=1; fi++ # One option woud be dynamic feedback where if the first one+ # takes a long time we don't bother doing more trials.++ times=`$NTIMES "$TRIALS" ./$test.exe $ARGS +RTS $RTS -RTS`+ CODE=$?++ echo " >>> MIN/MEDIAN/MAX TIMES $times"++ check_error $CODE "ERROR: run_all_tests this test failed completely: $test.exe"++ set -- $ARGS++ if [ "$CODE" == "143" ];+ then echo "$test.exe" $1 "$NUMTHREADS" "TIMEOUT TIMEOUT TIMEOUT" >> $RESULTS+ elif [ "$CODE" != "0" ] ;+ then echo "$test.exe" $1 "$NUMTHREADS" "ERR ERR ERR" >> $RESULTS+ else + echo "$test.exe" $1 "$NUMTHREADS" "$times" >> $RESULTS+ fi+}+++echo "Running all tests, for THREADSETTINGS in {$THREADSETTINGS}"+echo++# Hygiene:+make clean+echo; echo;++#====================================================================================================++function run_benchmark() +{+ set -- $line+ test=$1; shift++ if [ "$SHORTRUN" == "" ];+ # If we're in SHORTRUN mode we run each executable with no+ # arguments causing it to go to its default (small) problem size.+ then ARGS=$*+ else ARGS=+ fi++ echo "================================================================================"+ echo " Running Test: $test.exe $ARGS "+ echo "================================================================================"++ echo "# *** Config [$cnt ..], testing with command/args: $test.exe $ARGS " >> $RESULTS+++ for NUMTHREADS in $THREADSETTINGS; do+ runit+ echo >> $RESULTS;+ done # threads++ export NUMTHREADS=0++ echo >> $RESULTS;+ echo >> $RESULTS;+}++# Read $line and do the benchmark with ntimes_binsearch.sh+function run_binsearch_benchmark() +{+ NTIMES=./ntimes_binsearch.sh+ run_benchmark+ NTIMES=UNSET+}++# Read $line and do the benchmark with ntimes_minmedmax+function run_normal_benchmark() +{+ NTIMES=./ntimes_minmedmax+ run_benchmark+ NTIMES=UNSET+}+++#====================================================================================================+++if [ "$BENCHLIST" == "" ];+then BENCHLIST="./benchlist.txt"+fi++echo "Reading benchmarks from $BENCHLIST ..."+cat $BENCHLIST | grep -v "\#" | +while read line+do+ if [ "$line" == "" ]; then continue; fi+ echo RUNNING BENCH: $line+ run_normal_benchmark+done++echo "Finished with all test configurations."
+ examples/blackscholes.hs view
@@ -0,0 +1,153 @@+{-# LANGUAGE RecordWildCards, CPP, ScopedTypeVariables, FlexibleInstances #-}++-- Ported from CnC/C++ program by Ryan Newton+-- Then ported again from the Haskell-CnC interface to monad-par. [2011.02.16]++-- Description+-- ===========++-- The Black-Scholes equation is a differential equation that describes how,+-- under a certain set of assumptions, the value of an option changes as the +-- price of the underlying asset changes.++-- The formula for a put option is similar. The cumulative normal distribution +-- function, CND(x), gives the probability that normally distributed random+-- variable will have a value less than x. There is no closed form expression for+-- this function, and as such it must be evaluated numerically. The other +-- parameters are as follows: S underlying asset's current price, +-- X the strike price, T time to the expiration date, r risk-less rate of return,+-- and v stock's volatility.++-- Usage+-- =====++-- The command line is:++-- blackscholes b n+-- b : positive integer for the size of blocks+-- n : positive integer for the number of options +-- e.g.+-- blackscholes 100000 100 4++import Control.Seq+import Control.Monad+import Control.DeepSeq+import Control.Exception++import Control.Monad.Par+import Control.Monad.Par.AList++import Data.Array+import Data.List+import qualified Data.Array.Unboxed as U+import System.Environment++--------------------------------------------------------------------------------++type FpType = Float++-- This tuple contains the inputs for one invocation of our kernel+data ParameterSet = ParameterSet {+ sptprice :: FpType,+ strike :: FpType,+ rate :: FpType,+ volatility :: FpType ,+ otime :: FpType,+ otype :: Bool+} deriving Show++data_init :: Array Int ParameterSet++-- This defines some hard coded data as a big constant array:+#include "blackscholes_data.hs"+size_init = let (s,e) = bounds data_init in e - s + 1++inv_sqrt_2xPI = 0.39894228040143270286++--------------------------------------------------------------------------------+-- Scalar code follows:++cndf :: FpType -> FpType+cndf inputX = if sign then 1.0 - xLocal else xLocal+ where + sign = inputX < 0.0+ inputX' = if sign then -inputX else inputX+ + -- Compute NPrimeX term common to both four & six decimal accuracy calcs+ xNPrimeofX = inv_sqrt_2xPI * exp(-0.5 * inputX * inputX);++ xK2 = 1.0 / (0.2316419 * inputX + 1.0); + xK2_2 = xK2 * xK2; -- Need all powers of xK2 from ^1 to ^5:+ xK2_3 = xK2_2 * xK2;+ xK2_4 = xK2_3 * xK2;+ xK2_5 = xK2_4 * xK2;+ + xLocal = 1.0 - xLocal_1 * xNPrimeofX;+ xLocal_1 = xK2 * 0.319381530 + xLocal_2;+ xLocal_2 = xK2_2 * (-0.356563782) + xLocal_3 + xLocal_3' + xLocal_3'';+ xLocal_3 = xK2_3 * 1.781477937;+ xLocal_3' = xK2_4 * (-1.821255978);+ xLocal_3'' = xK2_5 * 1.330274429;+++blkSchlsEqEuroNoDiv :: FpType -> FpType -> FpType -> FpType -> FpType -> Bool -> Float -> FpType+blkSchlsEqEuroNoDiv sptprice strike rate volatility time otype timet =+ if not otype+ then (sptprice * nofXd1) - (futureValueX * nofXd2)+ else let negNofXd1 = 1.0 - nofXd1+ negNofXd2 = 1.0 - nofXd2+ in (futureValueX * negNofXd2) - (sptprice * negNofXd1)+ where + logValues = log( sptprice / strike ) + xPowerTerm = 0.5 * volatility * volatility+ xDen = volatility * sqrt(time)+ xD1 = (((rate + xPowerTerm) * time) + logValues) / xDen+ xD2 = xD1 - xDen++ nofXd1 = cndf xD1 + nofXd2 = cndf xD1 + futureValueX = strike * exp ( -(rate) * (time) )++--------------------------------------------------------------------------------+++computeSegment :: Int -> Int -> U.UArray Int FpType+computeSegment granularity t = arr+ where + arr = U.listArray (0, granularity-1) $+ Prelude.map fn [0 .. granularity-1]+ fn i = let ParameterSet { .. } = data_init U.! ((t+i) `mod` size_init)+ in blkSchlsEqEuroNoDiv sptprice strike rate volatility otime otype 0++--------------------------------------------------------------------------------++-- No need to go deeper here because its unboxed, right?+instance NFData (U.UArray Int FpType) where++main = do args <- getArgs + let (numOptions, granularity) =+ case args of + [] -> (10000, 1000)+ [b] -> (10, read b)+ [b,n] -> (read n, read b)++ if granularity > numOptions+ then error "Granularity must be bigger than numOptions!!"+ else return ()++ putStrLn$ "Running blackscholes, numOptions "++ show numOptions ++ " and block size " ++ show granularity++ let numChunks = numOptions `quot` granularity+-- results = runPar$ parMap (computeSegment granularity . (* granularity)) [0..numChunks-1]++#if 1+ results = runPar$ parMap (computeSegment granularity) [0, granularity .. numOptions-1]+#else+-- Not working right yet [2011.02.18]+ results = toList$ runPar$ + parBuild 1 0 (numChunks-1) + (computeSegment granularity . (* granularity))+#endif+ sum = foldl1' (+) $ map (U.! 0) results++ putStrLn$ "Final checksum: "++ show sum
+ examples/blackscholes_data.hs view
@@ -0,0 +1,1006 @@+-- #include file of test data inpout params and DerivaGem control reference value+--+-- S, K, r, q, vol, T, P/C, Divs, DG RefValue++data_init = listArray (0,999) [ + ParameterSet { sptprice=42.00, strike=40.00, rate=0.1000, volatility=0.20, otime=0.50, otype=True},+ ParameterSet {sptprice=42.00, strike=40.00, rate=0.1000, volatility=0.20, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.15, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.15, otime=1.00, otype=True},+ ParameterSet {sptprice=60.00, strike=65.00, rate=0.0800, volatility=0.30, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.10, otime=0.10, otype=True},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.10, otime=0.50, otype=True},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.10, otime=1.00, otype=True},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.10, otime=0.10, otype=True},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.10, otime=0.50, otype=True},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.10, otime=1.00, otype=True},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.10, otime=0.10, otype=True},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.10, otime=0.50, otype=True},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.10, otime=1.00, otype=True},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.25, otime=0.10, otype=True},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.25, otime=0.50, otype=True},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.25, otime=1.00, otype=True},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.25, otime=0.10, otype=True},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.25, otime=0.50, otype=True},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.25, otime=1.00, otype=True},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.25, otime=0.10, otype=True},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.25, otime=0.50, otype=True},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.25, otime=1.00, otype=True},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.50, otime=0.10, otype=True},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.50, otime=0.50, otype=True},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.50, otime=1.00, otype=True},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.50, otime=0.10, otype=True},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.50, otime=0.50, otype=True},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.50, otime=1.00, otype=True},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.50, otime=0.10, otype=True},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.50, otime=0.50, otype=True},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.50, otime=1.00, otype=True},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.10, otime=0.10, otype=False},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.10, otime=0.50, otype=False},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.10, otime=1.00, otype=False},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.10, otime=0.10, otype=False},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.10, otime=0.50, otype=False},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.10, otime=1.00, otype=False},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.10, otime=0.10, otype=False},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.10, otime=0.50, otype=False},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.10, otime=1.00, otype=False},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.25, otime=0.10, otype=False},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.25, otime=0.50, otype=False},+ ParameterSet{sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.25, otime=1.00, otype=False},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.25, otime=0.10, otype=False},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.25, otime=0.50, otype=False},+ ParameterSet{sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.25, otime=1.00, otype=False},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.25, otime=0.10, otype=False},+ ParameterSet{sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.1000, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.1000, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.1000, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0500, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0500, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0500, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0500, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0500, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0500, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0725, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0725, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0725, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0725, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0725, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0725, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0825, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0825, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0825, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.10, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.10, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.10, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.25, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.25, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.25, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.25, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0825, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0825, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.50, otime=0.10, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.50, otime=0.50, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0825, volatility=0.50, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.10, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.10, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.10, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.50, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.50, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.50, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.10, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.10, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.10, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.50, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.50, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.50, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.05, otime=0.05, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.15, otime=0.15, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.25, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.35, otime=0.35, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.45, otime=0.40, otype=True},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.65, otime=0.75, otype=True},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=41.25, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=50.00, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.05, otime=0.05, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.15, otime=0.15, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.65, otime=0.75, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.25, otime=0.25, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.35, otime=0.35, otype=False},+ ParameterSet {sptprice=50.00, strike=60.75, rate=0.0275, volatility=0.45, otime=0.40, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.25, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.25, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.50, otime=0.10, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.50, otime=0.50, otype=True},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.50, otime=1.00, otype=True},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=90.00, rate=0.1000, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=100.00, rate=0.1000, volatility=0.10, otime=1.00, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.10, otime=0.10, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.10, otime=0.50, otype=False},+ ParameterSet {sptprice=100.00, strike=110.00, rate=0.1000, volatility=0.10, otime=1.00, otype=False}+ ]
+ examples/cholesky.hs view
@@ -0,0 +1,321 @@+{-+ - Intel Concurrent Collections for Haskell+ - Copyright (c) 2010, Intel Corporation.+ -+ - This program is free software; you can redistribute it and/or modify it+ - under the terms and conditions of the GNU Lesser General Public License,+ - version 2.1, as published by the Free Software Foundation.+ -+ - This program is distributed in the hope it will be useful, but WITHOUT+ - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or+ - FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for+ - more details.+ -+ - You should have received a copy of the GNU Lesser General Public License along with+ - this program; if not, write to the Free Software Foundation, Inc., + - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.+ -+ -}+{-# LANGUAGE ExistentialQuantification+ , ScopedTypeVariables+ , BangPatterns+ , NamedFieldPuns + , RecordWildCards+ , FlexibleInstances+ , DeriveDataTypeable+ , TypeSynonymInstances+ , CPP+ #-}++-- Author: Chih-Ping Chen+-- Modified by Ryan Newton.++-- This program uses monad-par to do cholesky transformation. ++-- Description+-- -----------+-- Given a symmetric positive definite matrix A, the Cholesky decomposition is+-- a lower triangular matrix L such that A=L.L^(T). ++-- Usage+-- -----++-- The command line is:++-- cholesky n b filename+-- n : input SPD matrix size+-- b : block/tile size+-- filename: input matrix file name++-- Several sample input files are provided. m6.in is a 6x6 matrix (n=6).+-- Input_matrix.zip contains the files m50.in, m100.in, m500.in, and m1000.in with+-- corresponding 'n' of 50, 100, 500, and 1000.++-- e.g.+-- cholesky 1000 50 m1000.in 4+-- cholesky v 6 2 m6.in++-- The input SPD matrix is read from the file specified. The output will be a+-- lower triangular matrix. ++import Data.Int+import qualified Data.List as List+import qualified Data.Array.Unboxed as Array+import Data.Array.IO+import Data.Array.MArray+import Debug.Trace+import System.Posix.Files+import System.Environment+import System.IO+import System.IO.Unsafe+import Data.Map+import Data.IORef+import qualified Data.ByteString.Char8 as B++import Control.DeepSeq+import Control.Exception+import Data.Time.Clock -- Not in 6.10++import Control.Monad+import Control.Monad.Par++timeit io = + do strt <- getCurrentTime+ io + end <- getCurrentTime+ return (diffUTCTime end strt)++-- The type of the input/output array.+type Matrix = Array.UArray (Int, Int) Float++instance NFData Matrix++-- A matrix is divided into "Tile"s, and carries intermediate results+-- of the computation.+type Tile = IOUArray (Int, Int) Float++-- Tile3D allows us to refer to a IVar associated with a tile. The first+-- two dimensions of the index are the coordinates of the tile in the matrix.+-- The last dimension is the "generation" dimension. I.e., a (IVar Tile) mapped+-- by (i, j, k+1) is the next generation of the (IVar Tile) mapped by (i, j, k).+type Tiles3D = Map (Int, Int, Int) (IVar Tile)++instance NFData Tile where+-- SDM: use the default. All we require is that the IOUArray is evaluated,+-- since all its contents are unboxed.+-- rnf x = unsafePerformIO $+-- do bounds <- getBounds x+-- elems <- getElems x+-- _ <- return $ rnf (bounds, elems)+-- return ()++parMap_ :: (a -> Par ()) -> [a] -> Par ()+parMap_ f xs = mapM (spawn . f) xs >> return ()++getTileV :: (Int, Int, Int) -> Tiles3D -> IVar Tile+getTileV triplet tiles =+ findWithDefault (error "This can't be happening...") triplet tiles++-- This kicks off cholesky factorization on the diagonal tiles.+s0Compute :: IVar Tiles3D -> Int -> Int -> Par ()+s0Compute lkjiv p b =+ do lkji <- get lkjiv+ parMap_ (s1Compute lkji p b) [0..p-1]++-- This does the cholesky factorization on the a diagonal tile, and+-- kicks off triangular system solve on the tiles that are below and +-- on the same column as the diagonal tile.+s1Compute :: Tiles3D -> Int -> Int -> Int -> Par ()+s1Compute lkji p b k = + do+ -- Read the tile:+ aBlock <- get $ getTileV (k, k, k) lkji+ -- Write an output tile:+ put (getTileV (k, k, k+1) lkji) (s1Core aBlock b)+ -- Do triangular solves on the tiles with the same column number+ parMap_ (s2Compute lkji b) [(k,j) | j <- [k+1..p-1]]+ where s1Core aBlock b = unsafePerformIO $ + do lBlock <- newArray ((0,0), (b-1,b-1)) 0.0+ forM_ [0..b-1] (outer aBlock lBlock b)+ return lBlock+ outer aBlock lBlock b kb = do base <- readArray aBlock (kb,kb)+ writeArray lBlock (kb,kb) (sqrt base)+ forM_ [kb+1 .. b-1] (inner1 aBlock lBlock kb)+ forM_ [kb+1 .. b-1] (inner2 aBlock lBlock kb b)+ inner1 aBlock lBlock kb jb = do base1 <- readArray aBlock (jb,kb)+ base2 <- readArray lBlock (kb,kb)+ writeArray lBlock (jb,kb) (base1 /base2)+ inner2 aBlock lBlock kb b jbb = do forM_ [kb+1 .. b-1] (inner3 aBlock lBlock jbb kb)+ inner3 aBlock lBlock jbb kb ib = do base1 <- readArray aBlock (ib, jbb)+ base2 <- readArray lBlock (ib, kb)+ base3 <- readArray lBlock (jbb, kb)+ writeArray aBlock (ib,jbb) (base1 - base2 * base3)++-- This does the triangular system solve on a tile T, and+-- kicks off the symmetric rank-k update on the tiles that +-- are to the right and on the same row as T. +s2Compute :: Tiles3D -> Int -> (Int, Int) -> Par ()+s2Compute lkji b (k, j) =+ do + aBlock <- get $ getTileV (j,k,k) lkji+ liBlock <- get $ getTileV (k,k,k+1) lkji+ put (getTileV (j,k,k+1) lkji) (s2Core aBlock liBlock b)+ parMap_ (s3Compute lkji b) [(k, j, i) | i <- [k+1..j]]+ where s2Core aBlock liBlock b = unsafePerformIO $+ do loBlock <- newArray ((0,0),(b-1,b-1)) 0.0+ forM_ [0..b-1] (outer aBlock liBlock loBlock b)+ return loBlock+ outer aBlock liBlock loBlock b kb = do forM_ [0..b-1] (inner1 aBlock liBlock loBlock kb)+ forM_ [kb+1..b-1] (inner2 aBlock liBlock loBlock b kb)+ inner1 aBlock liBlock loBlock kb ib = do base1 <- readArray aBlock (ib,kb)+ base2 <- readArray liBlock (kb,kb)+ writeArray loBlock (ib,kb) (base1 / base2)+ inner2 aBlock liBlock loBlock b kb jb = do forM_ [0..b-1] (inner3 aBlock liBlock loBlock kb jb)+ inner3 aBlock liBlock loBlock kb jb ib = do base1 <- readArray aBlock (ib,jb)+ base2 <- readArray liBlock (jb,kb)+ base3 <- readArray loBlock (ib,kb)+ writeArray aBlock (ib,jb) (base1 - (base2 * base3))+ ++-- This computes the symmetric rank-k update on a tile.+s3Compute :: Tiles3D -> Int -> (Int, Int, Int) -> Par ()+s3Compute lkji b (k,j,i) | i == j =+ do + aBlock <- get $ getTileV (j,i,k) lkji+ l2Block <- get $ getTileV (j,k,k+1) lkji+ put (getTileV (j,i,k+1) lkji) (s3Core aBlock l2Block b)+-- pval lkji+ return ()+ where s3Core aBlock l2Block b = unsafePerformIO $+ do forM_ [0..b-1] (outer aBlock l2Block b)+ return aBlock+ outer aBlock l2Block b jb = do forM_ [0..b-1] (inner1 aBlock l2Block b jb)+ inner1 aBlock l2Block b jb kb = do base <- readArray l2Block (jb,kb) + forM_ [jb..b-1] (inner2 aBlock l2Block jb kb (-base))+ inner2 aBlock l2Block jb kb temp ib = do base1 <- readArray aBlock (ib,jb)+ base2 <- readArray l2Block (ib,kb)+ writeArray aBlock (ib,jb) (base1 + temp * base2)+ +s3Compute lkji b (k,j,i) | otherwise =+ do + aBlock <- get $ getTileV (j,i,k) lkji+ l2Block <- get $ getTileV (i,k,k+1) lkji+ l1Block <- get $ getTileV (j,k,k+1) lkji+ put (getTileV (j,i,k+1) lkji) (s3Core aBlock l1Block l2Block b)+ return ()+ where s3Core aBlock l1Block l2Block b = unsafePerformIO $+ do forM_ [0..b-1] (outer aBlock l1Block l2Block b)+ return aBlock+ outer aBlock l1Block l2Block b jb = do forM_ [0..b-1] (inner1 aBlock l1Block l2Block b jb)+ inner1 aBlock l1Block l2Block b jb kb = do base <- readArray l2Block (jb,kb) + forM_ [0..b-1] (inner2 aBlock l1Block jb kb (-base))+ inner2 aBlock l1Block jb kb temp ib = do base1 <- readArray aBlock (ib,jb)+ base2 <- readArray l1Block (ib,kb)+ writeArray aBlock (ib,jb) (base1 + temp * base2)++-- initLkji initialize the (IVar Tile) map using the input array.+initLkji :: Matrix -> Int -> Int -> Int -> Par (IVar Tiles3D) +initLkji arrA n p b = + let tile i j = unsafePerformIO $ newListArray ((0,0),(b-1,b-1)) (tileList i j)+ tileList i j = [ arrA Array.! (i * b + ii, j * b + jj) | ii <- [0..b-1], jj <-[0..b-1]]+ fn c (i, j, k) | k == 0 = + do mv <- c+ m <- get mv+ tv <- pval $ tile i j+ pval $ insert (i, j, k) tv m+ fn c (i, j, k) | otherwise = + do mv <- c+ m <- get mv+ tv <- new+ pval $ insert (i, j, k) tv m+ in foldl fn (pval empty) [(i, j, k) | i <- [0..p-1], j <- [0..i], k <- [0..j+1]] + ++-- composeResult collect the tiles with the final results back into one single matrix. +composeResult :: Tiles3D -> Int -> Int -> Int -> Par Matrix +composeResult lkji n p b =+ do assocs <- sequence [ grab i ib j | i <- [0..p-1], ib <- [0..b-1], j <- [0..i]]+ return $ Array.array ((0,0),(n-1,n-1)) (concat assocs)+ where grab i ib j = if (i == j) then+ do matOut <- get $ getTileV (i,j,j+1) lkji+ compose1 matOut + else+ do matOut <- get $ getTileV (i,j,j+1) lkji+ compose2 matOut+ where compose1 matOut = do forM [0..ib] (compose11 matOut)+ compose11 matOut jb = let elem = unsafePerformIO $+ do readArray matOut (ib,jb)+ in return ((i*b+ib,j*b+jb),elem)+ compose2 matOut = do forM [0..b-1] (compose11 matOut) ++{-# INLINE for_ #-} +for_ start end fn | start > end = error "for_: start is greater than end"+for_ start end fn = loop start+ where + loop !i | i == end = return () + | otherwise = do fn i; loop (i+1)++run :: Int -> Int -> Matrix -> Matrix+run n b arrA = + let p = n `div` b+ in + runPar $+ do + lkjiv <- initLkji arrA n p b+ _ <- s0Compute lkjiv p b+ lkji' <- get lkjiv+ composeResult lkji' n p b++main = + do ls <- getArgs + let (n, b, fname) =+ case ls of + [] -> (6, 2, "cholesky_matrix6.dat")++ -- To get more data try this:+ -- wget http://people.csail.mit.edu/newton/haskell-cnc/datasets/cholesky_matrix_data.tbz++ ["medium"] -> (500, 50, "cholesky_matrix500.dat")+ ["big"] -> (1000, 50, "cholesky_matrix1000.dat")+ [a,b,c] -> (read a, read b, c)++ bool <- fileExist fname+ let fname' = if bool then fname else "examples/"++fname+ + ref <- newIORef undefined+ let meaningless_write !val = writeIORef ref val++ t1 <- getCurrentTime+ putStrLn "Begin reading from disk..."+ arrA <- initMatrix n fname'+ evaluate arrA+ t2 <- getCurrentTime+ putStrLn $" ... ArrA read from disk: time " ++ show (diffUTCTime t2 t1)+ hFlush stdout++ arrB <- return $ run n b arrA+ --putStrLn $ show $ [((i,j),arrB Array.! (i,j)) | i <-[0..n-1], j<-[0..i]]++ putStrLn "Making sure evaluation of arrB is forced..."+ evaluate arrB+ --putStrLn $ show $ [((i,j),arrB Array.! (i,j)) | i <-[0..n-1], j<-[0..i]]+ t3 <- getCurrentTime++-- FIXME: Using deepseq here seems to delay the evaluation to the reference of+-- t3 <- case deepseq arrB () of _ -> getCurrentTime+-- t3 <- arrB `deepseq` getCurrentTime+ putStrLn$ "Finished: eval time "++ show (diffUTCTime t3 t2)++ putStrLn$ "SELFTIMED " ++ show ((fromRational $ toRational $ diffUTCTime t3 t2) :: Double)+ t4 <- getCurrentTime+ val <- readIORef ref+ putStrLn$ "Last value: " ++ show (arrB Array.! (n-1, n-1))+ t5 <- getCurrentTime+ putStrLn$ "SELFTIMED' " ++ show ((fromRational $ toRational $ diffUTCTime t5 t4) :: Double) ++initMatrix :: Int -> [Char] -> IO Matrix+initMatrix n fname = + do fs <- B.readFile fname+ return $! Array.listArray ((0,0), (n-1, n-1))+ (List.cycle $ List.map (read . B.unpack) (B.words fs))+
+ examples/cholesky_matrix6.dat view
@@ -0,0 +1,1 @@+4 -2 6 8 6 10 -2 10 3 -4 15 1 6 3 14 11 19 22 8 -4 11 33 2 21 6 15 19 2 62 28 10 1 22 21 28 73
+ examples/coins.hs view
@@ -0,0 +1,240 @@+{-# LANGUAGE BangPatterns #-}++import Data.List+import System.Environment+import Control.Parallel+import Control.Parallel.Strategies+import Control.Applicative+import Control.Monad.Par++-- Rough results, GHC 6.13: (val=777)+-- V1 (SDM): 2.2s+-- V2 (SDM): 2.7s+-- V3 (SDM, parallel): 1.0s on 7 cores+-- V4 (original): got bored waiting+-- V5 (HWL assoc): 5.2s+-- V6 (SDM, Int result): 0.9s+-- V7 (SDM, parallel): 0.2s on 7 cores++-----------------------------------------------------------------------------+-- Version 1: returns results as a list of list of coins++payL :: Int -> [(Int,Int)] -> [Int] -> [[Int]]+payL 0 coins acc = [acc]+payL _ [] acc = []+payL val ((c,q):coins) acc+ | c > val = payL val coins acc+ | otherwise = left ++ right+ where+ left = payL (val - c) coins' (c:acc)+ right = payL val coins acc++ coins' | q == 1 = coins+ | otherwise = (c,q-1) : coins++-----------------------------------------------------------------------------+-- Version 2: uses a custom AList type to avoid repeated appends++-- The idea here is that by avoiding the append we might be able to+-- parallelise this more easily by just forcing evaluation to WHNF at+-- each level. I haven't parallelised this version yet, though (V5+-- below is much easier) --SDM++data AList a = ANil | ASing a | Append (AList a) (AList a)++lenA :: AList a -> Int+lenA ANil = 0+lenA (ASing _) = 1+lenA (Append l r) = lenA l + lenA r++append ANil r = r+append l ANil = l -- **+append l r = Append l r++ -- making append less strict (omit ** above) can make the algorithm+ -- faster in sequential mode, because it runs in constant space.+ -- However, ** helps parallelism.++payA :: Int -> [(Int,Int)] -> [Int] -> AList [Int]+payA 0 coins acc = ASing acc+payA _ [] acc = ANil+payA val ((c,q):coins) acc+ | c > val = payA val coins acc+ | otherwise = append left right -- strict in l, maybe strict in r+ where+ left = payA (val - c) coins' (c:acc)+ right = payA val coins acc+ coins' | q == 1 = coins+ | otherwise = (c,q-1) : coins++-----------------------------------------------------------------------------+-- Version 3: parallel version of V2++payA_par :: Int -> Int -> [(Int,Int)] -> [Int] -> AList [Int]+payA_par 0 val coins acc = payA val coins acc+payA_par _ 0 coins acc = ASing acc+payA_par _ _ [] acc = ANil+payA_par depth val ((c,q):coins) acc+ | c > val = payA_par depth val coins acc+ | otherwise = res+ + where+ res = unEval $ pure append <*> rpar left <*> rwhnf right++ left = payA_par (if q == 1 then (depth-1) else depth) (val - c) coins' (c:acc)+ right = payA_par (depth-1) val coins acc++ coins' | q == 1 = coins+ | otherwise = (c,q-1) : coins++-----------------------------------------------------------------------------+-- Version 4: original list-of-list version (very slow)++pay :: Int -> Int -> [Int] -> [Int] -> [[Int]]+pay _ 0 coins accum = [accum]+pay _ val [] _ = []+pay pri val coins accum = + res + where -- + coins' = dropWhile (>val) coins+ coin_vals = nub coins' + res = concat ( map+ ( \ c -> let + new_coins = + ((dropWhile (>c) coins')\\[c])+ in + pay (pri-1)+ (val-c) + new_coins+ (c:accum)+ )+ coin_vals )+++-----------------------------------------------------------------------------+-- Version 5: assoc-list version (by HWL?)++-- assoc-list-based version; still multiple list traversals+pay1 :: Int -> Int -> [(Int,Int)] -> [(Int,Int)] -> [[(Int,Int)]]+pay1 _ 0 coins accum = [accum]+pay1 _ val [] _ = []+pay1 pri val coins accum = res+ where --+ coins' = dropWhile ((>val) . fst) coins+ res = concat ( + map+ ( \ (c,q) -> let + -- several traversals + new_coins = + filter (not . (==0) . snd) $+ map (\ x'@(c',q') -> if c==c' then (c',q'-1) else x') $+ dropWhile ((>c) . fst) $+ coins'+ new_accum = + map (\ x'@(c',q') -> if c==c' then (c',q'+1) else x') accum+ in + pay1 (pri-1)+ (val-c) + new_coins+ new_accum+ )+ coins' )++-----------------------------------------------------------------------------+-- Version 6: just return the number of results, not the results themselves++payN :: Int -> [(Int,Int)] -> Int+payN 0 coins = 1+payN _ [] = 0+payN val ((c,q):coins)+ | c > val = payN val coins+ | otherwise = left + right+ where+ left = payN (val - c) coins'+ right = payN val coins++ coins' | q == 1 = coins+ | otherwise = (c,q-1) : coins++-----------------------------------------------------------------------------+-- Version 7: parallel version of payN++payN_par :: Int -> Int -> [(Int,Int)] -> Int+payN_par 0 val coins = payN val coins+payN_par _ 0 coins = 1+payN_par _ _ [] = 0+payN_par depth val ((c,q):coins)+ | c > val = payN_par depth val coins+ | otherwise = res+ + where+ res = right `par` left `pseq` left + right++ left = payN_par (if q == 1 then (depth-1) else depth) (val - c) coins'+ right = payN_par (depth-1) val coins++ coins' | q == 1 = coins+ | otherwise = (c,q-1) : coins++-----------------------------------------------------------------------------++-----------------------------------------------------------------------------+-- Version 8: monad-par version of payN+-- Competitive with Version 7.++payN_mp :: Int -> Int -> [(Int,Int)] -> Int+payN_mp depth val coins = + runPar $ + payN_mpM depth val coins ++payN_mpM :: Int -> Int -> [(Int,Int)] -> Par Int+payN_mpM 0 val coins = return $ payN val coins+payN_mpM _ 0 coins = return 1+payN_mpM _ _ [] = return 0+payN_mpM depth val ((c,q):coins)+ | c > val = payN_mpM depth val coins+ | otherwise = res+ + where+ res = + do lv <- spawn $ left+ r <- right+ l <- get lv+ return (l + r)++ left = payN_mpM (if q == 1 then (depth-1) else depth) (val - c) coins'+ right = payN_mpM (depth-1) val coins++ coins' | q == 1 = coins+ | otherwise = (c,q-1) : coins++-----------------------------------------------------------------------------+++-- driver++main = do+ let vals = [250, 100, 25, 10, 5, 1] + -- let quants = [1, 3, 2, 5, 7, 12] -- small setup+ -- let quants = [5, 8, 8, 9, 12, 17] -- std setup+ let quants = [55, 88, 88, 99, 122, 177] -- large setup++ let coins = concat (zipWith replicate quants vals)+ coins1 = zip vals quants++ [n, arg] <- fmap (fmap read) getArgs++ case n of+ -- sequential, list of results+ 1 -> print $ length $ payL arg coins1 []+ -- sequential, append-list of results+ 2 -> print $ lenA $ payA arg coins1 []+ -- parallel, append-list of results+ 3 -> print $ lenA $ payA_par 4 arg coins1 []++ 4 -> print $ length (pay 0 arg coins [])+ 5 -> print $ length (pay1 0 arg coins1 (map (\(c,q) -> (c,0)) coins1))+ 6 -> print $ payN arg coins1+ 7 -> print $ payN_par 4 arg coins1+ 8 -> print $ payN_mp 4 arg coins1+
+ examples/common.mk view
@@ -0,0 +1,10 @@++# RRN: allow setting it via the command line. (I don't have a ghc-testing2 ;-). )+ifeq (,$(GHC))+ GHC = ghc+ # GHC = ghc-testing2+ # GHC = ghc-stable-nightly2+endif++ALLPARSRC= ../Control/Monad/Par.hs ../Control/Monad/Par/AList.hs ../Control/Monad/Par/OpenList.hs \+ ../Control/Monad/Par/IList.hs ../Control/Monad/Par/Stream.hs ../Control/Monad/Par/Logging.hs
+ examples/get_cholesky_data.sh view
@@ -0,0 +1,2 @@+#!/bin/bash+wget http://people.csail.mit.edu/~newton/haskell-cnc/datasets/cholesky_matrix_data.tbz
+ examples/mandel.hs view
@@ -0,0 +1,96 @@+{-# LANGUAGE BangPatterns, CPP #-}+import System.Environment+import Control.Monad+import Control.Seq+import Data.Complex+import System.IO+import Debug.Trace+import Control.DeepSeq+import Control.Monad.Par+import Control.Exception++import PortablePixmap+import Control.Monad.Par.AList as A++mandel :: Int -> Complex Double -> Int+mandel max_depth c = loop 0 0+ where + fn = magnitude+ loop i !z+ | i == max_depth = i+ | fn(z) >= 2.0 = i+ | otherwise = loop (i+1) (z*z + c)+++threshold = 1++runMandel :: Double -> Double -> Double -> Double -> Int -> Int -> Int -> Par (AList [Int])+runMandel minX minY maxX maxY winX winY max_depth = do++ parBuildThreshM threshold (InclusiveRange 0 (winY-1)) $ \y -> + do+ let l = [ mandelStep y x | x <- [0.. winX-1] ]+ deepseq l (return l)++ where+ mandelStep i j = mandel max_depth z+ where z = ((fromIntegral j * r_scale) / fromIntegral winY + minY) :++ ((fromIntegral i * c_scale) / fromIntegral winX + minX)++ r_scale = maxY - minY :: Double+ c_scale = maxX - minX :: Double+++makeImage :: Integer -> Integer -> Int -> AList [Int] -> PixMap+makeImage x y depth ls =+ createPixmap x y depth + (map prettyRGB (concat (toList ls)))+ where + prettyRGB :: Int -> (Int,Int,Int)+ prettyRGB s = let t = (depth - s) in (s,t,t)++simple x y depth = + runMandel 0 0 x' y' x y depth+ where + x' = fromIntegral x+ y' = fromIntegral y ++--------------------------------------------------------------------------------++-- A meaningless checksum.+mandelCheck :: AList [Int] -> Int -> Int -> Int+mandelCheck als max_col max_depth = loop 0 als 0+ where + loop i als !sum | A.null als = sum+ loop i als !sum = loop (i+1) (A.tail als)+ (loop2 i 0 (A.head als) sum)+ loop2 i j [] !sum = sum+ loop2 i j (h:t) !sum | h == max_depth = loop2 i (j+1) t (sum + i*max_col + j)+ | otherwise = loop2 i (j+1) t sum+ +main = do args <- getArgs++ let (x,y,depth) = + case args of+ [] -> + -- runPar $ simple 3 3 3+ (3,3,3)++ [x,y,depth] -> + -- simple (read x) (read y) (read depth)+ (read x, read y, read depth)++ -- [minX,minY,maxX,maxY,winX,winY,depth] ->+ -- runPar $ + -- runMandel (read minX) (read minY)+ -- (read maxX) (read maxY)+ -- (read winX) (read winY) (read depth)++ let ls = runPar$ simple x y depth+ when (False) $ do + hnd <- openFile "mandel_image.ppm" WriteMode+ hSetBinaryMode hnd True+ hPrint hnd (makeImage (fromIntegral x) (fromIntegral y) depth ls)+ hClose hnd++ putStrLn$ "Spot check: " ++ show (mandelCheck ls y depth)
+ examples/matmult/ListAux.hs view
@@ -0,0 +1,41 @@+module ListAux where++import Data.List+++-- splitting into n parts, and its inverse:++splitIntoN :: Int -> [a] -> [[a]]+splitIntoN n xs = takeIter parts xs+ where l = length xs+ parts = zipWith (+) ((replicate (l `mod` n) 1) ++ repeat 0)+ (replicate n (l `div` n))+takeIter :: [Int] -> [a] -> [[a]]+takeIter [] [] = []+takeIter [] _ = error "elements left over"+takeIter (t:ts) xs = hs : takeIter ts rest+ where (hs,rest) = splitAt t xs++unSplit :: [[a]] -> [a]+unSplit = concat++-- splitting into parts of same size. Inverse is concat again.++splitAtN :: Int -> [a] -> [[a]]+splitAtN n [] = []+splitAtN n xs = ys : splitAtN n zs+ where (ys,zs) = splitAt n xs++----------------------------------------++-- splitting round-robin until list runs empty, and its inverse:++unshuffle :: Int -> [a] -> [[a]]+unshuffle n xs = [takeEach n (drop i xs) | i <- [0..n-1]]+ where takeEach n [] = []+ takeEach n (x:xs) = x : takeEach n (drop (n-1) xs)++-- inverse to unshuffle+shuffle :: [[a]] -> [a]+shuffle = concat . transpose+
+ examples/matmult/Makefile view
@@ -0,0 +1,4 @@+include ../common.mk++matmult.exe : $(wildcard *.hs) ../../Control/Monad/Par.hs+ $(GHC) -O2 -cpp --make -i../.. MatMult.hs -o $@ -threaded -rtsopts
+ examples/matmult/MatMult.hs view
@@ -0,0 +1,215 @@+{-# OPTIONS -cpp #-}+{-# LANGUAGE BangPatterns #-}++{- Matrix multiplication using a torus (gentleman algorithm) -- FR10 -- -}++{-+RL/JB ParCo2005: eliminate result communication (Maybe-Type)++JB PhD2008: adapt for simple PhD skeleton tests++JB MSR07/2008: modified to use all available toroid skeletons.++JB MSR07/2008: derived a straight-forward GpH program using identical+ helpers and strategies++JB optimised prodEscalar++JB for ghc-6.9: replaced Control.Parallel.Strategies by a workaround+ (reexporting what should work)++-}+ +module Main(main) where++import System.Environment+import Data.List hiding (foldl', foldl1')++import ListAux+import Control.DeepSeq++import Control.Monad.Par++-------------------------------------++type Vector = [Int]+type Matrix = [Vector]++-- main computation, different versions:+mult :: Int -> Matrix -> Matrix -> Int -> [[Maybe Matrix]]+mult 0 m1 m2 _ = +#ifdef OUTPUT+ [[Just $ multMatricesTr m1 (transpose m2)]]+#else+ rnf (multMatricesTr m1 (transpose m2)) `seq` [[Nothing]]+#endif+mult v m1 m2 c = results+ where results :: [[Maybe Matrix]]+#ifdef OUTPUT+ results = [[Just computed]]+#else+ results = (rnf computed `seq` [[Nothing]])+#endif+ computed = multMatricesTr m1 m2Tr+-- strats' = strats ++ repeat undef+ m2Tr = transpose m2++prMM' :: (Matrix,Matrix) -> Matrix+prMM' (c,mt) = [[prVV f c | c <- mt]|f <-c]+prVV :: Vector -> Vector -> Int+prVV f c = sum (zipWith (*) f c)+ +shiftRight c [] = []+shiftRight c (xs:xss) = (xs2++xs1):shiftRight (c-1) xss+ where (xs1,xs2) = splitAt c xs++shiftDown c xss = transpose (shiftRight c (transpose xss))++join2 :: Matrix -> Matrix -> Matrix+join2 xs ys = zipWith (++) xs ys+join :: [Matrix] -> Matrix+join xss = foldr join2 (repeat []) xss+ +splitIntoClusters :: Int -> Matrix -> [[Matrix]]+splitIntoClusters c m | c < 1 = splitIntoClusters 1 m+splitIntoClusters c m1 = mss+ where bh = kPartition (length m1) c+ bhsplit [] [] = []+ bhsplit [] _ = error "some elements left over"+ bhsplit (t:ts) xs = hs : (bhsplit ts rest)+ where (hs,rest) = splitAt t xs + ms = bhsplit bh m1 -- blocks of rows + mss = map (colsplit bh) ms+ colsplit [] _ = []+ colsplit (t:ts) rs+ | head rs == [] = []+ | otherwise = (cab:colsplit ts resto)+ where (cab,resto) = unzip (map (splitAt t) rs)+ +-- mss = map (repartir (length m1 `div` c)) ms+-- repartir c xs+-- | head xs == [] = []+-- | otherwise = (cab:repartir c resto)+-- where (cab,resto) = unzip (map (splitAt c) xs)++-- helper for splitIntoClusters (formerly bresenham)+kPartition :: Int -> Int -> [Int]+kPartition n k = zipWith (+) ((replicate (n `mod` k) 1) ++ repeat 0)+ (replicate k (n `div` k))++ +mult' :: Int -> Int -> ((Matrix,Matrix),[Matrix],[Matrix]) -> (Maybe Matrix,[Matrix],[Matrix])+mult' nc nr ((sm1,sm2),sm1s,sm2s) +#ifdef OUTPUT+ = (Just result,toRight,toDown)+#else+ = (rnf result `seq` Nothing ,toRight,toDown)+#endif+ where toRight = take (nc-1) (sm1:sm1s)+ toDown = take (nr-1) (sm2':sm2s)+ sm2' = transpose sm2+ sms = zipWith multMatricesTr (sm1:sm1s) (sm2':sm2s)+ result = foldl1' addMatrices sms -- foldr1: not enough demand??++ +addMatrices :: Matrix -> Matrix -> Matrix+addMatrices m1 m2 = zipWith addVectors m1 m2+ where addVectors :: Vector -> Vector -> Vector+ addVectors v1 v2 = zipWith (+) v1 v2++-- Assumes the second matrix has already been transposed +multMatricesTr :: Matrix -> Matrix -> Matrix+multMatricesTr m1 m2 =+ runPar $ parMap (\row -> [prodEscalar2 row col | col <- m2]) m1++-- JB 2008: a lot faster, directly consuming lists, and tail-recursive (optimised with -O2)+prodEscalar2JB :: Vector -> Vector -> Int+prodEscalar2JB v1 v2 = addProd v1 v2 0+ where addProd :: Vector -> Vector -> Int -> Int+ addProd (v:vs) (w:ws) acc = addProd vs ws (acc + v*w)+ addProd [] [] n = n+ addProd _ _ _ = error "addProd: length does not match"++-- JB 2008: identical when using ghc-6.8.3, avoids bug in ghc-HEAD. Version suggested by SM+prodEscalar2 :: Vector -> Vector -> Int+prodEscalar2 v1 v2 = addProd v1 v2 0+addProd :: Vector -> Vector -> Int -> Int+addProd (v:vs) (w:ws) !acc = addProd vs ws (acc + v*w)+addProd _ _ !n = n+++prodEscalar :: Vector -> Vector -> Int+prodEscalar v1 v2 = sum (zipWith (*) v1 v2)+++------- foldl, strict in head element+foldl1' :: NFData a => (a->a->a) -> [a] -> a+foldl1' f (x:xs) = foldl' f x xs++foldl' :: NFData a => (a -> b -> a) -> a -> [b] -> a+foldl' f a [] = a+foldl' f a (x:xs) = -- whnf, not enough( (foldl' f) $! (f a x)) xs+ let first = f a x + in rnf first `seq` foldl' f first xs+++usage :: String -> String+usage name = "Cannon's algorithm: Usage:\n\t "+++ name ++ " <matrix size> <version> <blocksPerRow> \n" +++ "Version selects from " -- ++ show (zip [0..] names)++main = do + args <- getArgs+ let l = length args+ if l == 0 then do n <- getProgName+ putStrLn (usage n)+ putStrLn "\n *** defaults: size 100, seq. computation ***"+ else return () --putStrLn "Cannon's algorithm"++ let size = if null args then 100 else read (head args)+ opt = if length args < 2 then 0 else read (args!!1)+ chunk = if length args < 3 then 1 + else read (args!!2)+ a = "Matrices of size " ++ show size ++ +-- " with skeleton " ++ ((names++repeat "UNDEF")!!opt) +++ " using chunk parameter " ++ show chunk ++ "\n"+ res = mult opt (mA size) (mB size) chunk+ b = multMatricesTr (mA size) (transpose (mB size))+ -- putStrLn a+#ifdef OUTPUT+ putStrLn "Output wanted, checking result for correctness..."+ let computed = map (map fromJust) res+ computed' = concat (map join computed)+ printMat computed'+ if (b == computed') + then putStrLn "Correct!"+ else do putStrLn "WRONG RESULT! Should be"+ printMat b+#else+ -- putStrLn "No Output, matrix stays distributed."+ putStrLn (show res)+#endif +++ +m1 size = replicate size [1..size]+m2 size = listToListList size [1..size*size]+mA size = if size <= 4000 then m1 size else listToListList size (concat (take 20 (repeat [1..(size*size `div` 20)])))+mB size = if size <= 4000 then m1 size else listToListList size (concat (take 20 (repeat [0,2.. ((size*size) `div` 20)-2])))+listToListList c m + | length m <= c = [m]+ | otherwise = c1 : listToListList c resto+ where (c1,resto) = splitAt c m+++printMat :: Matrix -> IO ()+printMat m = putStrLn ("Matrix: " ++ (show (length (head m))) + ++ " x " ++ (show $ length m) ++ "\n" + ++ (showMat m))++-- instance Show a => Show (Matrix a) where+showMat m_ = "<<" ++ unlines (map (concatMap (\ x -> show x ++ " ")) m_) ++ ">>"++fromJust :: Maybe a -> a+fromJust (Just x) = x+fromJust Nothing = error "fromJust"
+ examples/matmult/matmult.stdout view
@@ -0,0 +1,1 @@+[[Nothing]]
+ examples/minimax/Board.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE BangPatterns #-}+module Board where++import Wins++import Data.List+import Control.Parallel+import Control.Parallel.Strategies+import Control.DeepSeq++boardDim = 4++type Board = [Row] +type Row = [Piece]+data Piece = X | O | Empty deriving (Eq,Show)++isEmpty Empty = True+isEmpty _ = False++showBoard :: Board -> String+showBoard board = intercalate "\n--------\n" (map showRow board) ++ "\n"+ where showRow r = intercalate "|" (map showPiece r)++showPiece :: Piece -> String+showPiece X = "X"+showPiece O = "O"+showPiece Empty = " "++placePiece :: Piece -> Board -> (Int,Int) -> Board+placePiece new board pos+ = [[ if (x,y) == pos then new else old+ | (x,old) <- zip [1..] row ]+ | (y,row) <- zip [1..] board ]++empty :: (Int,Int) -> Board -> Bool+empty (x,y) board = isEmpty ((board !! (y-1)) !! (x-1))++fullBoard b = all (not.isEmpty) (concat b)++newPositions :: Piece -> Board -> [Board]+newPositions piece board = +-- [ placePiece piece board (x,y) | (x,y) <- empties board ]+ goRows piece id board++goRows p rowsL [] = []+goRows p rowsL (row:rowsR) + = goRow p rowsL id row rowsR ++ goRows p (rowsL . (row:)) rowsR++goRow p rowsL psL [] rowsR = []+goRow p rowsL psL (Empty:psR) rowsR+ = (rowsL $ (psL $ (p:psR)) : rowsR) : goRow p rowsL (psL . (Empty:)) psR rowsR+goRow p rowsL psL (p':psR) rowsR = goRow p rowsL (psL . (p':)) psR rowsR++empties board = [ (x,y) | (y,row) <- zip [1..] board,+ (x,Empty) <- zip [1..] row ]+++initialBoard :: Board+initialBoard = replicate boardDim (replicate boardDim Empty)++data Evaluation = OWin | Score {-# UNPACK #-}!Int | XWin+ -- higher scores denote a board in X's favour+ deriving (Show,Eq)++instance NFData Evaluation where+ rnf x = x `seq` ()++maxE :: Evaluation -> Evaluation -> Evaluation+maxE XWin _ = XWin+maxE _ XWin = XWin+maxE b OWin = b+maxE OWin b = b+maxE a@(Score x) b@(Score y) | x>y = a+ | otherwise = b++minE :: Evaluation -> Evaluation -> Evaluation+minE OWin _ = OWin+minE _ OWin = OWin+minE b XWin = b+minE XWin b = b+minE a@(Score x) b@(Score y) | x<y = a+ | otherwise = b++eval n | n == boardDim = XWin+ | -n == boardDim = OWin+ | otherwise = Score n++static :: Board -> Evaluation+static board = interpret 0 (score board)++interpret :: Int -> [Evaluation] -> Evaluation+interpret x [] = (Score x)+interpret x (Score y:l) = interpret (x+y) l+interpret x (XWin:l) = XWin+interpret x (OWin:l) = OWin++scorePiece X = 1+scorePiece O = -1+scorePiece Empty = 0++scoreString !n [] = n+scoreString !n (X:ps) = scoreString (n+1) ps+scoreString !n (O:ps) = scoreString (n-1) ps+scoreString !n (Empty:ps) = scoreString n ps++score :: Board -> [Evaluation]+score board = + [ eval (scoreString 0 row) | row <- board ] +++ [ eval (scoreString 0 col) | col <- transpose board ] +++ [ eval (scoreString 0 (zipWith (!!) board [0..])),+ eval (scoreString 0 (zipWith (!!) board [boardDim-1,boardDim-2 ..])) ]++{-+#if 0+-- This looks very much like a zipWith f to me+map2 :: (a -> b -> c) -> [a] -> [b] -> [c]+map2 f [] x = []+map2 f x [] = []+map2 f (x:xs) (y:ys) = f x y:map2 f xs ys+#endif+-}
+ examples/minimax/Game.hs view
@@ -0,0 +1,67 @@+-- Time-stamp: <2011-02-12 21:11:31 simonmar>+-----------------------------------------------------------------------------++module Game where++import Board+import Tree++import Control.Parallel+import Control.Parallel.Strategies hiding (parMap)+import Debug.Trace++import Control.Monad.Par++type Player = Evaluation -> Evaluation -> Evaluation+type Move = (Board,Evaluation)++alternate :: Int -> Piece -> Player -> Player -> Board -> [Move]+alternate _ _ _ _ b | fullBoard b = []+alternate _ _ _ _ b | static b == XWin = []+alternate _ _ _ _ b | static b == OWin = []+alternate depth player f g board = move : alternate depth opponent g f board'+ where+ move@(board',eval) = best f possibles scores+ scores = runPar $ parMapM (bestMove depth opponent g f) possibles+ possibles = newPositions player board+ opponent = opposite player++opposite :: Piece -> Piece+opposite X = O+opposite O = X+++best :: Player -> [Board] -> [Evaluation] -> Move+best f (b:bs) (s:ss) = best' b s bs ss+ where+ best' b s [] [] = (b,s)+ best' b s (b':bs) (s':ss) | s==(f s s') = best' b s bs ss+ | otherwise = best' b' s' bs ss++showMove :: Move -> String+showMove (b,e) = show e ++ "\n" ++ showBoard b++bestMove :: Int -> Piece -> Player -> Player -> Board -> Par Evaluation+bestMove depth p f g board+ = do+ let tree = cropTree $ mapTree static $ prune depth $ searchTree p $ board+ parMise 2 f g tree++cropTree :: (Tree Evaluation) -> (Tree Evaluation)+cropTree (Branch a []) = (Branch a [])+cropTree (Branch (Score x) l) = Branch (Score x) (map cropTree l)+cropTree (Branch x l) = Branch x []++searchTree :: Piece -> Board -> (Tree Board)+searchTree p board = repTree (newPositions p) (newPositions (opposite p)) board++mise :: Player -> Player -> (Tree Evaluation) -> Evaluation+mise f g (Branch a []) = a+mise f g (Branch _ l) = foldr f (g OWin XWin) (map (mise g f) l)++parMise :: Int -> Player -> Player -> (Tree Evaluation) -> Par Evaluation+parMise 0 f g t = return (mise f g t)+parMise n f g (Branch a []) = return a+parMise n f g (Branch _ l) = do+ es <- parMapM (parMise (n-1) g f) l+ return (foldr f (g OWin XWin) es)
+ examples/minimax/Main.hs view
@@ -0,0 +1,20 @@+-- Time-stamp: <2009-05-06 13:54:34 simonmar>+-----------------------------------------------------------------------------++module Main where++import System.Environment+import Prog+import Board+import System.Random++main = do+ args <- getArgs+ let [n, depth] = case args of + [n, depth] -> [read n, read depth]+ _ -> [10,10]+ + setStdGen (mkStdGen 99999)+ b <- randomBoard n+ putStrLn $ showBoard b+ putStrLn $ solve depth b
+ examples/minimax/Makefile view
@@ -0,0 +1,4 @@+include ../common.mk++minimax.exe : $(wildcard *.hs) ../../Control/Monad/Par.hs+ $(GHC) -O2 -cpp --make -i../.. Main.hs -o $@ -threaded -rtsopts
+ examples/minimax/Prog.hs view
@@ -0,0 +1,47 @@+-- Time-stamp: <2009-05-06 13:55:20 simonmar>+-----------------------------------------------------------------------------++module Prog(prog,randomBoard,solve) where++import Board+import Wins+import Game+import Tree+import System.Random+import Data.List++-- First arg decaffinates game+prog :: Int -> String+prog decaf = showMove (head game)+ --"OXO\n" +++ --concat (map showMove game)+ where+ game = if decaf == 0 + then error "Decaffination error\n"+ else alternate decaf X maxE minE testBoard++-- X to play: find the best move+solve :: Int -> Board -> String+solve depth board+ = unlines+ . map showMove+ . take 1+ . alternate depth X maxE minE $ board++testBoard = [[Empty,O,Empty,Empty],[Empty,X,Empty,Empty],[Empty,Empty,Empty,Empty],[Empty,Empty,Empty,Empty]]++randomBoard :: Int -> IO Board+randomBoard moves = do+ g <- newStdGen+ let (g1,g2) = split g+ xs = randomRs (1,boardDim) g1+ ys = randomRs (1,boardDim) g2++ let+ play 0 _ _ board = board+ play n (pos:poss) (p:ps) board+ | not (empty pos board) = play n poss (p:ps) board+ | otherwise = play (n-1) poss ps (placePiece p board pos)++ return $ play moves (zip xs ys) (cycle [X,O]) initialBoard+
+ examples/minimax/Tree.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE CPP #-}+module Tree where++import Control.Parallel+import Control.Parallel.Strategies++data Tree a = Branch a [Tree a] deriving Show++repTree :: (a->[a]) -> (a->[a])-> a -> (Tree a)+repTree f g a = Branch a (map (repTree g f) (f a))++#define SEQ++#ifndef SEQ++mapTree :: (a -> b) -> Tree a -> Tree b+mapTree f (Branch a l) + = fa `par` Branch fa (map (mapTree f) l `using` myParList)+ where fa = f a++#else {- SEQ -}++mapTree :: (a -> b) -> (Tree a) -> (Tree b)+mapTree f (Branch a l) = Branch (f a) (map (mapTree f) l)++#endif++myParList [] = ()+myParList (x:xs) = x `par` myParList xs++mySeqList [] = ()+mySeqList (x:xs) = x `seq` mySeqList xs++parTree :: Int -> Tree a -> ()+parTree 0 (Branch a xs) = ()+parTree n (Branch a xs) = a `par` mySeqList (map (parTree (n-1)) xs)++prune :: Int -> (Tree a) -> (Tree a)+prune 0 (Branch a l) = Branch a []+prune n (Branch a l) = Branch a (map (prune (n-1)) l)+
+ examples/minimax/Wins.hs view
@@ -0,0 +1,39 @@+module Wins where++type Win = [[Int]]++wins :: [Win] +wins = [win1,win2,win3,win4,win5,win6,win7,win8]++win1,win2,win3,win4,win5,win6,win7,win8 :: Win +win1 = [[1,1,1],+ [0,0,0],+ [0,0,0]]+ +win2 = [[0,0,0],+ [1,1,1],+ [0,0,0]]+ +win3 = [[0,0,0],+ [0,0,0],+ [1,1,1]]+ +win4 = [[1,0,0],+ [1,0,0],+ [1,0,0]]+ +win5 = [[0,1,0],+ [0,1,0],+ [0,1,0]]+ +win6 = [[0,0,1],+ [0,0,1],+ [0,0,1]]+ +win7 = [[1,0,0],+ [0,1,0],+ [0,0,1]]+ +win8 = [[0,0,1],+ [0,1,0],+ [1,0,0]]
+ examples/minimax/minimax.stdout view
@@ -0,0 +1,18 @@+ |X| | +--------+ | | | +--------+ |O| | +--------+O| | |X++Score 2+X|X| | +--------+ | | | +--------+ |O| | +--------+O| | |X++
+ examples/nbody.hs view
@@ -0,0 +1,123 @@+{-+ - Modified from code released with:+ - Intel Concurrent Collections for Haskell+ - Copyright (c) 2010, Intel Corporation.+ -}+{-# OPTIONS -fglasgow-exts #-}+{-# LANGUAGE ExistentialQuantification+ , ScopedTypeVariables+ , BangPatterns+ , NamedFieldPuns + , RecordWildCards+ , FlexibleInstances+ , DeriveDataTypeable+ , MagicHash + , CPP+ #-}+-- This is INCOMPATIBLE with CncPure..++-- Author: Chih-Ping Chen+-- Ported to Monad-par by Ryan Newton.++-- This program uses CnC to calculate the accelerations of the bodies in a 3D system. + +import Control.Monad.Par+import Control.Monad+import Data.Int+import qualified Data.List as List+import qualified Data.Array as A+import GHC.Exts+import System.Environment++type Float3D = (Float, Float, Float)+type UFloat3D = (# Float#, Float#, Float# #)+++-- This step generates the bodies in the system.+genVector tag = (tag' * 1.0, tag' * 0.2, tag' * 30.0)+ where tag' = fromIntegral tag++-- We are keeping the idiomatic Haskell version around as well for comparison: +-- #define IDIOMATIC_VER++-- Only doing the O(N^2) part in parallel:+-- This step computes the accelerations of the bodies. +compute :: A.Array Int Float3D -> A.Array Int (IVar Float3D) -> Int -> Par ()+compute vecList accels tag =+ do + let myvector = vecList A.! (tag-1)+ put (accels A.! tag) (accel myvector vecList)+ where + g = 9.8++ multTriple :: Float -> Float3D -> Float3D+ multTriple c ( x,y,z ) = ( c*x,c*y,c*z )++ pairWiseAccel :: Float3D -> Float3D -> Float3D+ pairWiseAccel (x,y,z) (x',y',z') = let dx = x'-x+ dy = y'-y+ dz = z'-z+ eps = 0.005+ -- Performance degredation here:+ distanceSq = dx*dx + dy*dy + dz*dz + eps+ factor = 1/sqrt(distanceSq * distanceSq * distanceSq)++-- in multTriple factor (dx,dy,dz)+ in multTriple factor (dx,dy,dz)+#ifdef IDIOMATIC_VER+ sumTriples = foldr (\(x,y,z) (x',y',z') -> (x+x',y+y',z+z')) (0,0,0)+ accel vector vecList = multTriple g $ sumTriples $ List.map (pairWiseAccel vector) vecList+#else+-- Making this much less idiomatic to avoid allocation:+ (strt,end) = A.bounds vecList++ accel :: Float3D -> (A.Array Int Float3D) -> Float3D+ accel vector vecList = ++ -- Manually inlining to see if the tuples unbox:+ let (# sx,sy,sz #) = loop strt 0 0 0+ loop !i !ax !ay !az+ | i == end = (# ax,ay,az #)+ | otherwise = + let ( x,y,z ) = vector+ ( x',y',z' ) = vecList A.! i++ (# dx,dy,dz #) = (# x'-x, y'-y, z'-z #)+ eps = 0.005+ distanceSq = dx*dx + dy*dy + dz*dz + eps+ factor = 1/sqrt(distanceSq * distanceSq * distanceSq)++ (# px,py,pz #) = (# factor * dx, factor * dy, factor *dz #)++ in loop (i+1) (ax+px) (ay+py) (az+pz)+ in ( g*sx, g*sy, g*sz )+#endif+++run :: Int -> [Float3D]+run n = runPar $ + do + vars <- sequence$ take n $ repeat new+-- accels <- A.array (0,n-1) [ (i,) | i <- [0..n-1]]+ -- Is there a better way to make an array of pvars?+ let accels = A.array (1,n) (zip [1..n] vars)++#ifdef IDIOMATIC_VER+ let initVecs = List.map genVector [1..n]+#else+ let initVecs = A.array (0,n-1) [ (i, genVector i) | i <- [0..n-1] ]+#endif+ + forM_ [1..n] $ \ t -> fork (compute initVecs accels t)++ sequence (List.map (\i -> get (accels A.! i)) [1..n])++ +main = + do args <- getArgs + let accList = case args of + [] -> run (3::Int)+ [s] -> run (read s)+ putStrLn $ show (foldl (\sum (x,y,z) -> if x>0 then sum+1 else sum) 0 accList)++
+ examples/ntimes view
@@ -0,0 +1,153 @@+#!/bin/bash+# ---------------------------------------------------------------------------+# Intel Concurrent Collections for Haskell+# Copyright (c) 2010, Intel Corporation.+# +# This program is free software; you can redistribute it and/or modify it+# under the terms and conditions of the GNU Lesser General Public License,+# version 2.1, as published by the Free Software Foundation.+# +# This program is distributed in the hope it will be useful, but WITHOUT+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for+# more details.+# +# You should have received a copy of the GNU Lesser General Public License along with+# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.+# ---------------------------------------------------------------------------+++# Usage: ntimes <N> cmd args ...++# Takes the best time out of N.+# Returns that best time in seconds to stdout.++# This script writes a bunch of stuff to stderr, but only one thing to+# stdout. The one thing, the "return value" of this process is the+# best time in seconds.++# Responds to the environment variable HIDEOUTPUT, which, if non-empty+# suppresses echoing of the child command's output.++# Also responds to NOTIME which turns off the timing.+++# Time out processes after three minutes.+TIMEOUT=1000++# Unfortunately 'tempfile' is not a standard command:+function mytempfile {+ date=`date +"%Y.%m.%d"`+ secs=`date +"%s"`+ #index=$(($index+1))+ index=$1+ file=./runs/"$date"_"$base"_"$CNC_VARIANT"_"$CNC_SCHEDULER"_"$NUMTHREADS"_"$secs"_"$index".log+ touch $file+ echo $file+}++N=$1+shift+CMD=$*++if [ "$CMD" == "" ];+then echo Usage: "ntimes <trials> <cmd> <cmdargs> ..."+ exit 1+fi+base=`basename $1`++if [ ! -d "./runs" ]; then mkdir ./runs; fi ++CAT=/bin/cat++ # This serves as the log+ TMP1=`mytempfile 1`+ echo "Execution log file: " >> /dev/stderr+ echo " $TMP1" >> /dev/stderr++ #echo "=================== ASYNCHRONOUS TEST OUTPUT TO FOLLOW ======================" > $TMP1++ # if [ "$HIDEOUTPUT" == "" ];+ # then (tail -f $TMP1 >> /dev/stderr) &+ # fi++EXITCODE=0++ for ((i=1; i <= $N; i++)); do+ # Stores just this one executable's output:+ TMP2=`mytempfile 2`++# [2009.12.17] I need to get a good cross-platform process time-out system:+ # HACK: Sometimes I run this on systems WITHOUT a working GHC:+ if [ -e ./timeout.sh ];+ then TIMEOUTRUN="./timeout.sh -t $TIMEOUT"+ elif [ -e ./timeout ];+ # [2010.06.03] --RTS is a hack for working around a problem with +RTS flags:+ then TIMEOUTRUN="./timeout $TIMEOUT --RTS "+ else TIMEOUTRUN=+ fi++ if [ "$HIDEOUTPUT" == "" ];+ then MYOUT=/dev/stderr+ else MYOUT=/dev/null+ fi++ echo | tee -a $TMP2 >> $MYOUT+ echo "Running trial $i of $N:" | tee -a $TMP2 >> $MYOUT+ echo "------------------------------------------------------------" | tee -a $TMP2 >> $MYOUT++ # This is hackish, it depends on the program output not containing+ # the string "real". (Aside from the timing results.)++ if [ "$NOTIME" != "" ];+ then ($TIMEOUTRUN $CMD) &> /dev/stdout | tee -a $TMP2 >> $MYOUT; CODE=${PIPESTATUS[0]}+ elif [ `uname` == "Linux" ];+ then (/usr/bin/time --format="%e real" $TIMEOUTRUN $CMD) &> /dev/stdout | tee -a $TMP2 >> $MYOUT; CODE=${PIPESTATUS[0]}+ else (/usr/bin/time $TIMEOUTRUN $CMD) &> /dev/stdout | tee -a $TMP2 >> $MYOUT; CODE=${PIPESTATUS[0]}+ fi++ # If there was an error, we don't commit the output to $TMP1:+ if [ "$CODE" == "0" ];+ then echo " Run $i of command succeeded" >> /dev/stderr++ # SUPERHACK terrain... Here's a special symbol that the script can+ # use to override the external timing and use internal timing+ # mechinasms.+ selftime=`grep SELFTIME $TMP2`+ if [ "$selftime" != "" ]; then + echo " +++ Executable appears self-timed!!:" >> $MYOUT+ echo "$selftime" >> $MYOUT+ cat $TMP2 | grep -v "real" | sed 's/SELFTIMED/real/' >> $TMP1+ else+ cat $TMP2 >> $TMP1+ fi+++ # [2010.05.11] I used to just give warnings when not ALL of the trials failed:+ # This was for timing the nondeterministic hashtable hack:+ #else echo "Warning: run $i of command failed with code $CODE: $CMD" >> /dev/stderr+ else echo "ERROR run $i of command failed with code $CODE: $CMD" >> /dev/stderr+ #exit $CODE+ EXITCODE=$CODE+ fi++ rm -f $TMP2+done;++ # Stores the times:+ TMP3=`mytempfile 3`++ # HACK HACK: this assumes the string "real" doesn't occur in the test output.+ grep real $TMP1 | awk '{ print $1" "$2 }' | sort -n > $TMP3++ # Echo the final output to stdout:++ echo "Final Timings: " > /dev/stderr++ cat $TMP3 | sed 's/real //' | sed 's/ real//' ++ # Leave behind only $TMP1+ rm -f $TMP3++exit $EXITCODE
+ examples/ntimes_minmedmax view
@@ -0,0 +1,38 @@+#!/bin/bash+# ---------------------------------------------------------------------------+# Intel Concurrent Collections for Haskell+# Copyright (c) 2010, Intel Corporation.+# +# This program is free software; you can redistribute it and/or modify it+# under the terms and conditions of the GNU Lesser General Public License,+# version 2.1, as published by the Free Software Foundation.+# +# This program is distributed in the hope it will be useful, but WITHOUT+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for+# more details.+# +# You should have received a copy of the GNU Lesser General Public License along with+# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.+# ---------------------------------------------------------------------------++ntimes=`dirname $0`/ntimes++times=`$ntimes $*`+CODE=$?+if [ "$CODE" != "0" ];+then exit $CODE+fi++lines=`echo $times | xargs -n1 echo | wc -l`+half=$((($lines+1)/2))++echo "Median time (of $lines): " >> /dev/stderr+#echo "Median time of: $times" >> /dev/stderr++MIN=`echo $times | xargs -n1 echo | sort -n | head -n1`+MED=`echo $times | xargs -n1 echo | sort -n | head -n$half | tail -n1`+MAX=`echo $times | xargs -n1 echo | sort -n | tail -n1`++echo $MIN $MED $MAX
+ examples/parfib.hs view
@@ -0,0 +1,74 @@++import Data.Int+import System.Environment+-- import Control.Monad.Par+import Control.Monad.ParElision+import GHC.Conc++type FibType = Int64++-- sequential version of the code+fib :: FibType -> FibType+fib 0 = 1+fib 1 = 1+fib x = fib (x-2) + fib (x-1) + 1+++-- Basic, non-monadic parallel-fib:+parfib0 :: FibType -> FibType+parfib0 n | n < 2 = 1 +parfib0 n = x `par` y `pseq` (x+y)+ where + x = parfib0 (n-1)+ y = parfib0 (n-2) ++++parfib1 :: FibType -> Par FibType+parfib1 n | n < 2 = return 1 +parfib1 n = + do + xf <- spawn_$ parfib1 (n-1)+ y <- parfib1 (n-2) + x <- get xf+ return (x+y)++main = do args <- getArgs + let (version,size) = + case args of + [] -> ("monad",10)+ [v,n] -> (v,read n)++ case version of + "monad" -> do + putStrLn "Monad-par based version:"+ print$ runPar$ parfib1 size+ "sparks" -> do + putStrLn "Sparks-based, Non-monadic version:"+ print$ parfib0 size+ _ -> error$ "unknown version: "++version+++{- On 4-core nehalem, 3.33ghz:++ Non-monadic version, real/user time:+ fib(40) 4 threads: 1.1s 4.4s+ fib(42) 4 threads: 2.9s 11.6s 17GB allocated+ + SPARKS: 433784785 (290 converted, 280395620 pruned)++ Monad-par version:+ fib(38) non-threaded: 23.3s 23.1s+ fib(38) 1 thread : 24.7s 24.5s+ fib(38) 4 threads: 8.2s 31.3s++ fib(40) 4 threads: 20.6s 78.6s 240GB allocated+++For comparison, Cilkarts Cilk++:+ fib(42) 4 threads: 3.029s 23.610s++Intel Cilk Plus:+ fib(42) 4 threads: 4.212s 16.770s++-}
+ examples/partree/Makefile view
@@ -0,0 +1,4 @@+include ../common.mk++partree.exe : $(wildcard *.hs) ../../Control/Monad/Par.hs+ $(GHC) -O2 -cpp --make -i../.. partree.hs -o $@ -threaded -rtsopts
+ examples/partree/Tree.hs view
@@ -0,0 +1,146 @@+-- -*- haskell -*-+--+-- ADT of a binary tree (values only in leaves).+-- Parallel functions use par and seq directly.+-- ---------------------------------------------------------------------------++module Tree(Tree, + list2tree, tree2list, (^:), + tree_map, tree_fold, + depth, create_forest, + force_tree, par_tree_map) where++import Control.Parallel+import Control.Parallel.Strategies+import Control.Monad.Par++infixl 2 ^:++data Tree a = Leaf a+ | Node (Tree a) (Tree a)+ deriving (Eq, Read, Show)++ +tree_map :: (Integral a, Integral b) => (a -> b) -> Tree a -> Tree b+tree_map f (Leaf x) = Leaf (f x)+tree_map f (Node left right) = Node (tree_map f left) (tree_map f right)+++par_tree_map :: (Integral a, Integral b) => (a -> b) -> Tree a -> Tree b+par_tree_map f t =+ runPar $ par_tree_map' f t++par_tree_map' :: (Integral a, Integral b) => (a -> b) -> Tree a -> Par (Tree b)+par_tree_map' f (Leaf x) = return $ Leaf (f x)+par_tree_map' f (Node left right) = + do l' <- spawn_ $ par_tree_map' f left+ r <- par_tree_map' f right+ l <- get l'+ return (Node l r)++-- force evaluation of tree (could use Strategies module instead!)+force_tree :: (Integral a) => Tree a -> ()+force_tree t@(Leaf x) = x `seq` ()+force_tree t@(Node left right) = (force_tree left) `seq` + (force_tree right) `seq` + ()+-- just would you'd expect+tree_fold :: (Integral a) => (a -> a -> a) -> a -> Tree a -> a+tree_fold o z (Leaf x) = z `o` x+tree_fold o z (Node left right) = tree_fold o z' right+ where z' = tree_fold o z left++list2tree :: (Integral a) => [a] -> Tree a +list2tree [] = error "list2tree: empty list"+list2tree [x] = Leaf x+list2tree l = Node (list2tree left) (list2tree right)+ where (left,right) = splitAt ((length l) `div` 2 ) l++tree2list :: (Integral a) => Tree a -> [a]+tree2list (Leaf x) = [x]+tree2list (Node left right) = tree2list left ++ tree2list right++-- combine 2 trees+(^:) :: (Integral a) => Tree a -> Tree a -> Tree a+t1 ^: t2 = Node t1 t2++depth :: Tree a -> Int+depth (Leaf _) = 0+depth (Node left right) = max (depth left) (depth right) + 1++-- The following functions are useful for heavily heap allocating test fcts+create_forest :: (Integral a) => Tree a -> [Tree a] +create_forest (Leaf x) = [ (Leaf y) | y <- [2..x], gcd x y == 1 ]+create_forest (Node left right) = [ (Node left' right') + | left' <- create_forest left,+ right' <- create_forest right]++{-+On a Harpertown Windows machine with 4 cores (8 threads), using+Haskell Platform 2011.2.0.0. +Note the CPU utilization rates (elapsed time * num_of_threads/CPU time)+range between 70% and 77% when -N > 1. ++Compare that with Strategies, which has a higher CPU utilization rate+(> 95%) and a smaller user time for -N > 1.++E:\cchen15\icfp\partree-mp>timeit partree.exe 1000 10 +RTS -N1+partree 1000 10 = 23712++Fri Mar 18 13:56:45 2011+Cmd: partree.exe 1000 10 +RTS -N1+Elapsed: 4.898 sec+User 4.867 sec+System 0.016 sec+Total CPU 4.883 sec+Peak WorkingSet Size: 7229440+Peak Pagefile Usage: 5836800+Page Fault Count: 1806+Peak Paged Pool usage: 85688+Peak NonPaged Pool usage: 5568++E:\cchen15\icfp\partree-mp>timeit partree.exe 1000 10 +RTS -N2+partree 1000 10 = 23712++Fri Mar 18 13:56:54 2011+Cmd: partree.exe 1000 10 +RTS -N2+Elapsed: 9.313 sec+User 12.605 sec+System 1.841 sec+Total CPU 14.446 sec+Peak WorkingSet Size: 12619776+Peak Pagefile Usage: 10133504+Page Fault Count: 3122+Peak Paged Pool usage: 85688+Peak NonPaged Pool usage: 6048++E:\cchen15\icfp\partree-mp>timeit partree.exe 1000 10 +RTS -N4+partree 1000 10 = 23712++Fri Mar 18 13:57:07 2011+Cmd: partree.exe 1000 10 +RTS -N4+Elapsed: 9.968 sec+User 22.761 sec+System 5.756 sec+Total CPU 28.517 sec+Peak WorkingSet Size: 13414400+Peak Pagefile Usage: 11677696+Page Fault Count: 3317+Peak Paged Pool usage: 85688+Peak NonPaged Pool usage: 6720++E:\cchen15\icfp\partree-mp>timeit partree.exe 1000 10 +RTS -N8+partree 1000 10 = 23712++Fri Mar 18 13:57:25 2011+Cmd: partree.exe 1000 10 +RTS -N8+Elapsed: 9.843 sec+User 46.239 sec+System 11.029 sec+Total CPU 57.268 sec+Peak WorkingSet Size: 14729216+Peak Pagefile Usage: 15175680+Page Fault Count: 3637+Peak Paged Pool usage: 85688+Peak NonPaged Pool usage: 7968+-}
+ examples/partree/partree.hs view
@@ -0,0 +1,34 @@+-- -*- haskell -*-+-- partree+-- parallel map over a tree +-----------------------------------------------------------------------------++module Main where++import System.Environment(getArgs)+import Control.Parallel+import Tree++main = do [arg1,arg2] <- getArgs+ let + n = read arg1 :: Int -- size of tree in nodes+ c = read arg2 :: Int -- work per node+ res = partree c n+ putStrLn ("partree " ++ unwords [arg1,arg2] ++ " = " ++ show res)++-- worker function to be mapped over the tree; heavily allocating!+bar :: Int -> Int -> Int+bar c n = tree_fold (\x y -> (x+y) `quot` 2) 0 t + where forest = [ let + l = take n (iterate (+i) i)+ in+ list2tree l + | i <- [1..c + n `mod` 15] ]+ t = foldl1 (^:) forest++-- generate a tree with n nodes;+-- then map and fold 2 functions over it+partree :: Int -> Int -> Int+partree c n = (force_tree t) `seq` (tree_fold max 0 t)+ where t = par_tree_map (bar c) (list2tree [1..n])+
+ examples/plot_scaling.hs view
@@ -0,0 +1,355 @@+#!/usr/bin/env runhaskell+{-# LANGUAGE NamedFieldPuns+ #-}++-- This script generates gnuplot plots.+-- Give it a .dat file as input... (or it will try to open results.dat)+++import Text.PrettyPrint.HughesPJClass+import Text.Regex+import Data.List+import Data.Function+import Control.Monad+import System+import System.IO+import System.FilePath +import System.Environment++import HSH+import Data.Array (listArray, )+import Data.Monoid (mappend, )+import Debug.Trace+++linewidth = "5.0"++-- Schedulers that we don't care to graph right now.+-- This happens BEFORE rename+--scheduler_MASK = [5,6,99,10]+scheduler_MASK = []++-- Ok, gunplot line type 6 is YELLOW... that's not to smart:+line_types = [0..5] ++ [7..]++round_2digits :: Double -> Double+round_2digits n = (fromIntegral $round (n * 100)) / 100++--x11 = terminal Terminal.X11.cons+--x11 = terminal cons+--x11 = terminal Graphics.Gnuplot.Terminal.X11.cons+--x11 = terminal X11.cons++-- Split +parse [a,b,c,d,e,f] =+ Entry { name = a, + variant = b,+ sched = "trace",+ threads = read c,+ tmin = read d,+ tmed = read e,+ tmax = read f,+ normfactor = 1.0+ }++--parse [a,b,c,d,e,f,g,h,i] = +-- trace ("Got line with norm factor: "++ show [a,b,c,d,e,f,g,h,i])+-- (parse [a,b,c,d,e,f,g,h]) { normfactor = read i }++parse other = error$ "Cannot parse, wrong number of fields, "++ show (length other) ++" expected 8 or 9: "++ show other+++--------------------------------------------------------------------------------+-- Let's take a particular interpretation of Enum for pairs:+instance (Enum t1, Enum t2) => Enum (t1,t2) where + succ (a,b) = (succ a, succ b)+ pred (a,b) = (pred a, pred b)+ toEnum n = (toEnum n, toEnum n)+ fromEnum (a,b) = case (fromEnum a, fromEnum b) of+ (x,y) | x == y -> x+ (x,y) -> error$ "fromEnum of pair: nonmatching numbers: " ++ show x ++" and "++ show y+++-- Removes single blanks and separates lines into groups based on double blanks.+sepDoubleBlanks :: [String] -> [[String]]+sepDoubleBlanks ls = loop [] ls + where + loop acc [] = [reverse acc]+ loop acc ("":"":t) = reverse acc : loop [] (stripLeadingBlanks t)+ loop acc ("":t) = loop acc t+ loop acc (h :t) = loop (h:acc) t + stripLeadingBlanks [] = [] + stripLeadingBlanks ("":t) = stripLeadingBlanks t+ stripLeadingBlanks ls = ls+++remComments :: String -> [String] -> [String]+remComments commentchars ls = filter (pred . stripLeadingWhitespace) ls+ where + pred str = not (take (length commentchars) str == commentchars) + stripLeadingWhitespace [] = [] + stripLeadingWhitespace (' ':t) = stripLeadingWhitespace t+ stripLeadingWhitespace ls = ls++--------------------------------------------------------------------------------++-- Here's the schema for the data from my timing tests:+data Entry = Entry { + name :: String,+ variant :: String,+ sched :: String,+ threads :: Int, + tmin :: Double,+ tmed :: Double,+ tmax :: Double,+ normfactor :: Double+}+ deriving Show++instance Pretty Entry where+ --pPrint x = pPrint$ show x+ pPrint Entry { name, sched, variant, threads, tmin, tmed, tmax, normfactor } = + pPrint ("ENTRY", name, sched, variant, threads, (tmin, tmed, tmax), normfactor )+-- pPrint ("ENTRY", name, variant, sched, threads, tmin, tmed, tmax, normfactor)+++groupSort fn = + (groupBy ((==) `on` fn)) . + (sortBy (compare `on` fn))++-- Add three more levels of list nesting to organize the data:+--organize_data :: [Entry] -> [[[[Entry]]]]+organize_data :: [Entry] -> [[[[Entry]]]]+organize_data = + (map (map (groupSort sched))) . + (map (groupSort variant)) .+ (groupSort name)+++newtype Mystr = Mystr String++instance Show Mystr where+ show (Mystr s) = s++{-+-- I ended up giving up on using the gnuplot package on hackage:+-- mypath :: Graph2D.T +--Plot2D.T+--plot_benchmark :: [[[Entry]]] -> IO ()+--plot_benchmark :: [[[Entry]]] -> Plot2D.T+plot_benchmark [io, pure] = + --Plot.plot (X11.title "foobar" X11.cons) $+ Plot.plot X11.cons $+ Frame.cons (Opts.title ("Benchmark: " ++ benchname ++ " normalized to time " ++ show basetime) $ Opts.deflt) plots+ where + benchname = name $ head $ head io + plots = foldl1 mappend (map persched io ++ map persched pure)+ basetime = foldl1 min $ map tmed $+ filter ((== 0) . threads) $+ (concat io ++ concat pure)+ persched :: [Entry] -> Plot2D.T+ persched dat = + let + schd = sched$ head dat+ var = variant$ head dat+ mins = map tmin dat+ meds = map tmed dat+ maxs = map tmax dat+ --zip4 = map$ \ a b c d -> (a,b,c,d)+ zip4 s1 s2 s3 s4 = map (\ ((a,b), (c,d)) -> (a,b,c,d))+ (zip (zip s1 s2) (zip s3 s4))+ pairs = zip4 (map (fromIntegral . threads) dat) + (map (basetime / ) meds)+ (map (basetime / ) mins)+ (map (basetime / ) maxs)+ quads = map (\ (a,b,c,d) -> Mystr (show a ++" "++ show b ++" "++ show d ++" "++ show c))+ pairs + in + fmap (Graph2D.lineSpec $ + LineSpec.title (var ++"/"++ show schd) $ + LineSpec.lineWidth 3.0 $ + LineSpec.pointSize 3.0 $ + LineSpec.deflt) $ + fmap (Graph2D.typ Graph2D.linesPoints) $+ --Plot2D.path pairs+ --Plot2D.path (map ( \ (a,b,c,d) -> (a,b)) pairs)+ --fmap (Graph2D.typ Graph2D.errorBars) $+ Plot2D.list quads+-}++-- Name, Scheduler, Threads, BestTime, Speedup+data Best = Best (String, String, String, Int, Double, Double)++-- Plot a single benchmark as a gnuplot script:+plot_benchmark2 root [io, pure] = + do action $ filter goodSched (io ++ pure)+ return$ Best (benchname, bestvariant, + bestsched, bestthreads, best, basetime / best)+ where + benchname = name $ head $ head io + -- What was the best single-threaded execution time across variants/schedulers:++ goodSched [] = error "Empty block of data entries..."+ goodSched (h:t) = not $ (sched h) `elem` scheduler_MASK++ cat = concat io ++ concat pure+ threads0 = filter ((== 0) . threads) cat+ threads1 = filter ((== 1) . threads) cat++ map_normalized_time = map (\x -> tmed x / normfactor x)++ times0 = map_normalized_time threads0+ times1 = map_normalized_time threads1++ basetime = if not$ null times0 + then foldl1 min times0+ else if not$ null times1 + then foldl1 min times1+ else error$ "\nFor benchmark "++ show benchname ++ " could not find either 1-thread or 0-thread run.\n" +++ --"ALL entries: "++ show (pPrint cat) ++"\n"+ "\nALL entries threads: "++ show (map threads cat)++ best = foldl1 min $ map_normalized_time cat+ Just best_index = elemIndex best $ map_normalized_time cat+ bestsched = sched$ cat !! best_index+ bestvariant = variant$ cat !! best_index+ bestthreads = threads$ cat !! best_index++ (filebase,_) = break (== '.') $ basename benchname ++ -- If all normfactors are the default 1.0 we print a different message:+ --let is_norm = not$ all (== 1.0) $ map normfactor ponits+ norms = map normfactor (concat io ++ concat pure)+ default_norms = all (== 1.0) $ norms+ max_norm = foldl1 max norms++ scrub '_' = ' '+ scrub x = x+ -- scrub [] = []+ -- scrub ('_':t) = "\\_"++ scrub t+ -- scrub (h:t) = h : scrub t++ action lines = + do + let scriptfile = root ++ filebase ++ ".gp"+ putStrLn$ " Dumping gnuplot script to: "++ scriptfile++ putStrLn$ " NORM FACTORS "++ show norms+++ runIO$ echo "set terminal postscript enhanced color\n" -|- appendTo scriptfile+ runIO$ echo ("set output \""++filebase++".eps\"\n") -|- appendTo scriptfile+ runIO$ echo ("set title \"Benchmark: "++ map scrub filebase +++ ", speedup relative to serial time " ++ show (round_2digits $ basetime * max_norm) ++" seconds "++ +-- "for input size " ++ show (round_2digits max_norm)+ (if default_norms then "" else "for input size " ++ show (round max_norm))+ --if is_norm then "normalized to work unit"+ --if default_norms then "" else " per unit benchmark input"+ ++"\"\n") -|- appendTo scriptfile+ runIO$ echo ("set xlabel \"Number of Threads\"\n") -|- appendTo scriptfile+ runIO$ echo ("set ylabel \"Parallel Speedup\"\n") -|- appendTo scriptfile+++ runIO$ echo ("set xrange [1:]\n") -|- appendTo scriptfile+ runIO$ echo ("set key left top\n") -|- appendTo scriptfile+ runIO$ echo ("plot \\\n") -|- appendTo scriptfile++ -- In this loop lets do the errorbars:+ forM_ (zip [1..] lines) $ \(i,points) -> do + let datfile = root ++ filebase ++ show i ++".dat"+ runIO$ echo (" \""++ basename datfile ++"\" using 1:2:3:4 with errorbars lt "+++ show (line_types !! i) + ++" title \"\", \\\n") -|- appendTo scriptfile++ -- Now a second loop for the lines themselves and to dump the actual data to the .dat file:+ forM_ (zip [1..] lines) $ \(i,points) -> do + let datfile = root ++ filebase ++ show i ++".dat" + let schd = sched$ head points -- should be the same across all point+ let var = variant$ head points -- should be the same across all point+ let nickname = var ++"/"++ schd+ runIO$ echo ("# Data for variant "++ nickname ++"\n") -|- appendTo datfile+ forM_ points $ \x -> do ++ -- Here we print a line of output:+ runIO$ echo (show (fromIntegral (threads x)) ++" "+++ show (basetime / (tmed x / normfactor x)) ++" "+++ show (basetime / (tmax x / normfactor x)) ++" "++ + show (basetime / (tmin x / normfactor x)) ++" \n") -|- appendTo datfile++ let comma = if i == length lines then "" else ",\\"+ runIO$ echo (" \""++ basename datfile +++ "\" using 1:2 with lines linewidth "++linewidth++" lt "++ + show (line_types !! i) ++" title \""++nickname++"\" "++comma++"\n")+ -|- appendTo scriptfile++ --putStrLn$ "Finally, running gnuplot..."+ --runIO$ "(cd "++root++"; gnuplot "++basename scriptfile++")"+ --runIO$ "(cd "++root++"; ps2pdf "++ filebase ++".eps )"+++--plot_benchmark2 root ls = putStrLn$ "plot_benchmark2: Unexpected input, list len: "++ show (length ls)+plot_benchmark2 root [io] = plot_benchmark2 root [io,[]]++++isMatch rg str = case matchRegex rg str of { Nothing -> False; _ -> True }++main = do + args <- getArgs + let file = case args of + [f] -> f + [] -> "results.dat"+ dat <- run$ catFrom [file] -|- remComments "#" ++ let parsed = map (parse . filter (not . (== "")) . splitRegex (mkRegex "[ \t]+")) + (filter (not . isMatch (mkRegex "ERR")) $+ filter (not . isMatch (mkRegex "TIMEOUT")) $+ filter (not . null) dat)+ let organized = organize_data$ + -- filter ((`elem` ["io","pure"]) . variant) parsed+ parsed++ putStrLn$ "Parsed "++show (length parsed)++" lines containing data."+ print organized++ let root = "./" ++ dropExtension file ++ "_graphs/"+ -- For hygiene, completely anhilate output directory:+ system$ "rm -rf " ++root ++"/"+ system$ "mkdir -p "++root+ bests <- + forM organized $ \ perbenchmark -> do + best <- plot_benchmark2 root perbenchmark+ forM_ perbenchmark $ \ pervariant -> + forM_ pervariant $ \ persched -> + do let mins = map tmin persched+ let pairs = (zip (map (fromIntegral . threads) persched) mins)+ --putStrLn$ show pairs+ --plot Graphics.Gnuplot.Terminal.X11.cons (path pairs)+ --System.exitWith ExitSuccess+ --plot x11 (path pairs)+ return ()++ return best++ putStrLn$ "Now generating final plot files...\n\n"++ let summarize hnd = do + hPutStrLn hnd $ "# Benchmark, scheduler, best #threads, best median time, max parallel speedup: "+ hPutStrLn hnd $ "# Summary for " ++ file++ let pads n s = take (n - length s) $ repeat ' '+ let pad n x = " " ++ (pads n (show x))++ forM_ bests $ \ (Best(name, variant, sched, threads, best, speed)) ->+ hPutStrLn hnd$ " "++ name++ (pad 25 name) +++ show variant++ (pad 10 variant)+++ show sched++ (pad 5 sched) +++ show threads++ (pad 5 threads)++ + show best ++ (pad 15 best) +++ show speed + hPutStrLn hnd$ "\n\n"++ putStrLn$ "Done."+ summarize stdout+ withFile (dropExtension file `addExtension` "summary") WriteMode $ summarize +
+ examples/primes.hs view
@@ -0,0 +1,52 @@++++-- This is a simplistic benchmark but is included just for comparison with Haskell CnC++-- Author: Ryan Newton ++import System.Environment+import Control.Monad.Par+import Control.Monad.Par.AList as A+import Debug.Trace+++-- First a naive serial test for primality:+isPrime :: Int -> Bool+isPrime 2 = True+isPrime n = (prmlp 3 == n)+ where prmlp :: Int -> Int+ prmlp i = if (rem n i) == 0+ then i else prmlp (i + 2)++----------------------------------------++-- Next, a CnC program that calls the serial test in parallel.++primes :: Int -> Int -> Par (AList Int)+primes start end = +-- parMapReduceRange (InclusiveRange start end)+ parMapReduceRangeThresh 100 (InclusiveRange start end)+ (\n -> if + -- TEMP: Need a strided range here:+ (rem n 2 /= 0) && isPrime n + then return$ singleton n+ else return$ empty)+ (\ a b -> return (append a b))+ empty++-- This version never builds up the list, it simply counts:+-- countprimes :: Int -> Int -> Par Int+-- countprimes start end = + ++main = do args <- getArgs + let size = case args of + [] -> 1000 -- Should output 168+ [n] -> (read n)++ ls = runPar $ primes 3 size+ +-- putStrLn (show ls)+ putStrLn (show (1 + A.length ls)) -- Add one to include '2'.+ return ()
+ examples/queens.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE BangPatterns #-}+import System.Environment+import Control.Monad+import Control.Seq++import Control.Monad.Par+-- import Control.Monad.Par_Strawman++nqueens :: Int -> Par [[Int]]+nqueens nq = step 0 []+ where+ threshold = 5++ step :: Int -> [Int] -> Par [[Int]]+ step !n b+ | n >= threshold = return (iterate gen [b] !! (nq - n))+ | otherwise = do+ rs <- parMapM (step (n+1)) (gen [b])+ return (concat rs)++ safe :: Int -> Int -> [Int] -> Bool+ safe x d [] = True+ safe x d (q:l) = x /= q && x /= q+d && x /= q-d && safe x (d+1) l++ gen :: [[Int]] -> [[Int]]+ gen bs = [ (q:b) | b <- bs, q <- [1..nq], safe q 1 b ]+++main = do+ args <- fmap (fmap read) getArgs+ let n = case args of [] -> 8; [n] -> n+ print (length (runPar (nqueens n)))
+ examples/run_tests.sh view
@@ -0,0 +1,19 @@+#!/bin/bash++# set -e +# set -o errexit++for file in "$@"; do+ echo Running test $file+ ./$file &> $file".out"+# echo "Return code: $?"+ code=$?+ if [ "$code" != 0 ]; then + echo+ echo " ERROR, output was:"+ cat $file".out"+ echo+ echo " ERROR: exit code $code"+ exit $code+ fi+done
+ examples/stream/DEVLOG.txt view
@@ -0,0 +1,141 @@++Notes on development of monad-par streaming framework and benchmarks.+---------------------------------------------------------------------++[2011.03.19] Right now I'm seeing a weird behavior where when run+-threaded it prints many of the messages before "new"' in the filter+stage, but it doesn't print the messages after "put" in that same+stage.++This system allows self-stealing, correct? ++[2011.03.19] ++ Quick measurements on wasp:+ ---------------------------+ Throughput of just countupWindowed + measureRate ...+ 2 threads is 8600 * 1024 = 8,806,400 = 8.8mHz.++ * With -N4 it uses ~234% CPU and gets sligthly confused, lowering+ throughput to 5800-6100 windows/sec from 8600++ * It actually does work (e.g. doesn't deadlock) to run it with -N1+ because there's only one kernel. The throughput is much more+ variable. From 4800-8500 win/sec. GC time is tiny in this+ case, 0.5%.+ ---------------------------+ Throughput of a single amap (+100) kernel = ++ * Gets stuck waiting for first kernel -N1 as expected (and fills memory).++ * on -N2 it gets a rate of between 7937 and 8200 wins/sec but then+ it gets stuck after about 10 seconds. I don't fully understand+ this. The two threads should be enough for the two kernels+ right? Currently Par.hs forks a "replacement thread" to continue+ working on the queue when runParAsync returns. Therefore there+ should be enough haskell threads, even if there are only two Par+ scheduler threads. Those two par workers should be preemptable by+ the measureRate thread....++ * on -N3 it works, and gives 6200-7100 wins/sec throughput. Uses+ ~245% CPU. Presumably the two par worker threads are hammering+ away and the measureRate one is less busy. But if I leave it+ running for a while it grew up to 79% (of 16gb) mem usage.+ Strange, -s claims the following. How can max resdency be so low!?++ 2,993,287,338,808 bytes allocated in the heap+ 17,134,304,736 bytes copied during GC+ 3,744,408 bytes maximum residency (152145 sample(s))+ 1,870,240 bytes maximum slop+ 14 MB total memory in use (3 MB lost due to fragmentation)++ Generation 0: 4961153 collections, 4961152 parallel, 696.02s, 63.29s elapsed+ Generation 1: 152145 collections, 152145 parallel, 115.00s, 22.66s elapsed++ Parallel GC work balance: 1.08 (2102121164 / 1946757116, ideal 3)++ MUT time (elapsed) GC time (elapsed)+ Task 0 (worker) : 0.02s ( 0.00s) 0.00s ( 0.00s)+ Task 1 (worker) : 1927.40s (742.55s) 0.00s ( 0.00s)+ Task 2 (worker) : 1927.40s (742.55s) 0.00s ( 0.00s)+ Task 3 (worker) : 1928.34s (743.40s) 0.00s ( 0.00s)+ Task 4 (worker) : 1928.34s (743.40s) 0.00s ( 0.00s)+ Task 5 (bound) : 0.00s ( 0.00s) 0.11s ( 0.02s)+ Task 6 (worker) : 1928.34s (743.40s) 0.00s ( 0.00s)+ Task 7 (worker) : 1117.43s (743.40s) 810.91s ( 85.93s)++ SPARKS: 0 (0 converted, 0 pruned)++ INIT time 0.00s ( 0.00s elapsed)+ MUT time 1117.32s (743.40s elapsed)+ GC time 811.02s ( 85.95s elapsed)+ EXIT time 0.00s ( 0.01s elapsed)+ Total time 1928.34s (829.36s elapsed)++ %GC time 42.1% (10.4% elapsed)++ Alloc rate 2,678,988,417 bytes per MUT second++ Productivity 57.9% of total user, 134.7% of total elapsed++ gc_alloc_block_sync: 6092257+ whitehole_spin: 0+ gen[0].sync_large_objects: 190255+ gen[1].sync_large_objects: 267++ Oh, maybe because of the CArray's all the real storage is outside haskell's heap.++ There must be a memory leak in streamMap. Trying to fix it:++ (1) Factored out 'loop'. I need to try to ensure that no closure+ holds onto the original head of the stream. Wow! That+ lowered throughput a lot (-N3) and drove cpu usage up! 3500+ wins/sec declining to 300. And it still leaks.+ The key difference seems to be passing the extra "fn" argument to loop.++ (2) Hmm... I went back to what I *thought* was the previous form+ above (that leaked). But now it's getting the good >6000+ throughput and doesn't seem to be leaking. It gives memory+ back to the system and goes up and down in mem footprint.+ But now it uses 300% cpu. The only difference I can see is+ that I changed the module export decl. How could this matter+ if compiling into an executable? Nevertheless maybe this+ helps it inline.... Now I can run it for 10 min with minimal+ memory usage.++ -qa seems to help the variance on -N4, i.e. with more workers+ than kernels.++ ---------------------------+ Throughput of a single FFT kernel.++ * Oops, maybe this accounts for the difference above between+ leaking/non-leaking. The FFT version maintains a high >7000+ wins/sec throughput. But it leaks memory. Maybe it's not+ really doing the FFT and is leaking suspensions?++ * Nope... I tried forcing the FFT by inspecting one element of the+ output. Still leaks. Well, the answer is simple. It just+ can't keep up with a source that has no backpressure. To+ confirm this hypothesis, I ran it with -N1 (with the new+ yielding source operator). NOPE, it still leaks.+++[2011.03.20] {Added disjoint_working_sets_pipeline}++Ok, first try. Not only has this not demonstrated the benefit of+pipeline parallelism, right now it isn't showing much of a speedup at+all. Right now I'm running with default parameters (4 256 10 20000)++Running with "-N4 -qa" I see large variance. Between 1.0 and 3.3+seconds. Seeing the same without -qa:++Running without no extra runtime flags (no -qa):+ nothreads: 2.18s+ 1thread: 2.3s+ 4threads: 1-3 seconds.++The big difference is running with N>1 it can spend a lot of time in+GC (e.g. 84%!!). But I need to stop running on wasp for actual+parallel speedup measurements -- I seem to have problems using wasp+for this purpose.
+ examples/stream/Makefile view
@@ -0,0 +1,32 @@+include ../common.mk++SRC= simple1_measureSrc.hs \+ disjoint_working_sets_pipeline.hs \+ fft_pipeline.hs+EXES= $(SRC:.hs=.exe)++NOTHREAD= $(SRC:.hs=.nothread.exe)++# Par source code with relative paths updated for this deeper directory:+RELPARSRC= $(subst ../,../../,$(ALLPARSRC))++all: $(EXES)++%.exe : %.hs $(RELPARSRC)+ $(GHC) -O2 --make -i../../ $< -o $@ -threaded -rtsopts+++#------------------------------------------------------------+# Build the non-threaded versions.++nothread: $(NOTHREAD)++%.nothread.exe: %.hs $(RELPARSRC)+ $(GHC) -O2 --make -i../../ $< -o $@ -rtsopts++#------------------------------------------------------------+runtests: + ../run_tests.sh $(EXES) ++clean:+ rm -f $(EXES) *.o *.hi
+ examples/stream/disjoint_working_sets_pipeline.hs view
@@ -0,0 +1,276 @@+{-# LANGUAGE BangPatterns, ScopedTypeVariables, CPP #-}+{-# OPTIONS_GHC -fwarn-unused-imports #-}++-- The goal of this benchmark is to demonstrate kernels that have private+-- state which has to be read from memory on each invocation. Further,+-- the state forms the majority of the working set -- it's larger than+-- the streaming input.++-- In theory this means that keeping a kernel on one core and+-- exploiting pipeline parallelism is better than following the data+-- through the stream graph in a depth first traversal.+++--module Main(main) where+module Main where++import Control.Monad as C+import Control.Monad.Par +import Control.Monad.Par.Stream as S+import Control.Monad.Par.OpenList+import Control.DeepSeq+import Control.Exception+import Control.Parallel.Strategies as Strat++-- import Data.Array.Unboxed as U+import Data.Complex+import Data.Int+import Data.Word+import Data.List (intersperse) +import Data.List.Split (chunk)++import Prelude as P+import System.Environment+import System.Exit+import System.CPUTime+import System.CPUTime.Rdtsc+import GHC.Conc as Conc+import GHC.IO (unsafePerformIO, unsafeDupablePerformIO, unsafeInterleaveIO)++import Debug.Trace+import Control.Monad.Par.Logging++import qualified Data.Vector.Unboxed as UV+import Data.Vector.Unboxed hiding ((++))++-- Performs some (presently meaningless) computation on a state & a+-- window (stream element) to compute a new state and new window.+--+-- Assumes statesize is a multiple of bufsize:+statefulKern :: Vector Double -> Vector Double -> (Vector Double, Vector Double)+statefulKern state buf = (newstate, newelem)+ where + -- We could probably test the memory behavior we're interested in+ -- better with inplace update here... but for now, this:+ newstate = UV.map (\d -> d/sum + 2) state+ newelem = UV.map (+sum) buf++ sum = P.sum partialSums+ partialSums = [ sumslice (cutslice n) | n <- [0..factor-1] ] ++ cutslice n = UV.slice (n*blen) blen state+ sumslice slce = UV.sum (UV.zipWith (+) buf slce)++ factor = slen `quot` blen+ slen = UV.length state+ blen = UV.length buf++--------------------------------------------------------------------------------++monadpar_version (_,numfilters, bufsize, statecoef, numwins) = do + putStrLn$ "Running monad-par version."++ let statesize = bufsize * statecoef+ results <- evaluate $ runPar$ do + strm1 :: Stream (UV.Vector Double) <- S.generate numwins (\n -> UV.replicate bufsize 0)+ -- Make a pipeline of numfilters stages:+ let initstate = UV.generate statesize fromIntegral+ pipe_end <- C.foldM (\s _ -> streamScan statefulKern initstate s) strm1 [1..numfilters]++ sums <- streamMap UV.sum pipe_end+#if 0+ return sums++ -- This is tricky, but two different consumers shouldn't prevent+ -- garbage collection.+ ls <- toListSpin results+-- Just (Cons h _) <- pollIVar results+ putStrLn$ "Sum of first window: " ++ show (P.head ls)+ forkIO$ measureRateList ls+ putStrLn$ "Final sum = "++ show (P.sum ls)+#else++ streamFold (+) 0 sums++ putStrLn$ "Final sum = "++ show results+#endif+++--------------------------------------------------------------------------------++sparks_version (_,numfilters, bufsize, statecoef, numwins) = do + putStrLn$ "Running sparks version."++ -- Here we represent the stream as a plain list.+ let + statesize = bufsize * statecoef+ strm1 :: [UV.Vector Double] = P.replicate numwins $ UV.replicate bufsize 0+ initstate = UV.generate statesize fromIntegral+ applyKern = scan statefulKern initstate++-- This one has the problem that it fully evaluates the stream for the+-- first kernel before moving on to the second:+-- strm_last = (parRepeatFun numfilters applyKern) strm1++ pipe_end = applyNKernels statefulKern numfilters initstate strm1++ sums = P.map UV.sum pipe_end+-- #define SERIAL+#ifndef SERIAL+ `using` (Strat.parBuffer numCapabilities rwhnf) +#endif++ putStrLn$ "Sum of first window: "++ show (P.head sums)+ measureRateList (sums)+-- measureRateList (strm_last)+-- measureRateList (forceList strm_last)+ putStrLn$ "Final Sum = " ++ show (P.sum sums)++-- Make sure the cars of a list are evaluated before following each cdr:+forceList [] = []+forceList (h:t) = rnf h `seq` forceList t++-- A slightly different version of Data.List.scanl+scan :: (a -> b -> (a,c)) -> a -> [b] -> [c]+scan f q [] = []+scan f q (h:t) = h' : scan f q t+ where + (q',h') = f q h++type StatefulKernel s a b = s -> a -> (s,b)++-- applyNKernels _ _ _ [] = []+applyNKernels :: NFData a => StatefulKernel s a a -> Int -> s -> [a] -> [a]+applyNKernels _ 0 _ ls = ls+applyNKernels kern n init ls = + applyNKernels kern (n-1) init (loop init ls)+ where + loop st [] = []+ loop st (h:t) = + let (st', x) = kern st h in+#ifndef SERIAL+ rnf x `par` +#endif+ x : loop st' t+ +-- Compose two stateful kernels in parallel.+composeStatefulKernels :: (NFData b, NFData s1) => + StatefulKernel s1 a b -> StatefulKernel s2 b c + -> StatefulKernel (s1,s2) a c+-- composeStatefulKernels (f1,f2) (s1,s2) x = +composeStatefulKernels f1 f2 (s1,s2) x = + rnf pr1 `par` (newstate, snd pr2)+ where + pr1 = f1 s1 x+ pr2 = f2 s2 (snd pr1)+ newstate = (fst pr1, fst pr2)+++parRepeatFun n f = +-- P.foldr (.) id (P.replicate n f)+ P.foldr (.|| rdeepseq) id (P.replicate n f)+++--------------------------------------------------------------------------------+-- Main script++default_version = "monad"+default_numfilters = 4+default_bufsize = 256+default_statecoef = 10 -- in MULTIPLES of bufsize+default_numwins = 10 * 1000+++main = do+ args <- getArgs+ arg_tup@(version,_,_,_,_) <- + case args of + [] -> return (default_version, default_numfilters, default_bufsize, default_statecoef, default_numwins)+ [a,b,c,d,e] -> return (a, read b, read c, read d, read e)+ _ -> do + putStrLn$ "ERROR: Invalid arguments, must take 0 or 5 args."+ putStrLn$ " Expected args: (version='monad'|'sparks' #filters, bufsize, stateSizeMultiplier, #bufsToProcess)"+ putStrLn$ " Received args: "++ show args+ exitFailure ++ putStrLn$ "numCapabilities: "++ show numCapabilities+ putStrLn$ " Frequency in measurable ticks: "++ commaint one_second ++ "\n"++ case version of + "monad" -> monadpar_version arg_tup+ "sparks" -> sparks_version arg_tup+ _ -> error$ "unknown version: "++version++ putStrLn$ "Finally, dumping all logs:"+ printAllLogs++++-- It is not necessary to evaluate every element in the case of an unboxed vector.+instance NFData a => NFData (UV.Vector a) where+ rnf !vec = ()+++print_ msg = trace msg $ return ()++-- work pop 1 peek N push 1 +-- float->float filter +-- firFilter n coefs = +-- {++-- float sum = 0;+-- for (int i = 0; i < N; i++)+-- sum += peek(i) * COEFF[N-1-i];+-- pop();+-- push(sum);+-- }+-- }+++{- ++Here's what cachegrind says (on 4 core nehalem):++ $ valgrind --tool=cachegrind ./stream/disjoint_working_sets_pipeline monad 4 768 10 1000 +RTS -N4+ .....+ [measureRate] current rate: 58 Total elems&time 916 181,988,055,721+ [measureRate] Hit end of stream after 1000 elements.+ Final sum = 1.560518243231086e22+ ==21202== + ==21202== I refs: 7,111,462,273+ ==21202== I1 misses: 374,190+ ==21202== L2i misses: 298,364+ ==21202== I1 miss rate: 0.00%+ ==21202== L2i miss rate: 0.00%+ ==21202== + ==21202== D refs: 3,882,935,974 (3,542,949,529 rd + 339,986,445 wr)+ ==21202== D1 misses: 14,606,684 ( 9,824,455 rd + 4,782,229 wr)+ ==21202== L2d misses: 6,774,479 ( 2,088,565 rd + 4,685,914 wr)+ ==21202== D1 miss rate: 0.3% ( 0.2% + 1.4% )+ ==21202== L2d miss rate: 0.1% ( 0.0% + 1.3% )+ ==21202== + ==21202== L2 refs: 14,980,874 ( 10,198,645 rd + 4,782,229 wr)+ ==21202== L2 misses: 7,072,843 ( 2,386,929 rd + 4,685,914 wr)+ ==21202== L2 miss rate: 0.0% ( 0.0% + 1.3% )+++Sparks version:+ Final Sum = 1.560518243231086e22+ ==21226== + ==21226== I refs: 5,898,314,238+ ==21226== I1 misses: 291,271+ ==21226== L2i misses: 246,518+ ==21226== I1 miss rate: 0.00%+ ==21226== L2i miss rate: 0.00%+ ==21226== + ==21226== D refs: 3,264,359,909 (3,206,394,437 rd + 57,965,472 wr)+ ==21226== D1 misses: 16,003,068 ( 10,905,138 rd + 5,097,930 wr)+ ==21226== L2d misses: 9,177,043 ( 4,207,106 rd + 4,969,937 wr)+ ==21226== D1 miss rate: 0.4% ( 0.3% + 8.7% )+ ==21226== L2d miss rate: 0.2% ( 0.1% + 8.5% )+ ==21226== + ==21226== L2 refs: 16,294,339 ( 11,196,409 rd + 5,097,930 wr)+ ==21226== L2 misses: 9,423,561 ( 4,453,624 rd + 4,969,937 wr)+ ==21226== L2 miss rate: 0.1% ( 0.0% + 8.5% )++ -}
+ examples/stream/fft_pipeline.hs view
@@ -0,0 +1,75 @@+{-# OPTIONS_GHC -fwarn-unused-imports #-}++module Main(main) where++import Control.Monad.Par +import Control.Monad.Par.Stream as S+import Control.Exception+import Data.Complex+import GHC.Conc as Conc+import Debug.Trace+import Math.FFT (dft)++type Elt = Complex Double++fft_kern :: Window Elt -> Window Elt+fft_kern arr = dft arr++-- -- TEMP, evaluate one element to make sure the fft really gets called:+-- -- trace ("One elt sample: "++ show (arr!10)) $+-- case arr2 ! 10 of _ -> arr2+-- where arr2 = dft arr++--------------------------------------------------------------------------------+-- Main script++-- target = maxBound+target = 10 * 1000 * 1000+bufsize = 1024++main = do+ putStrLn$ "numCapabilities: "++ show numCapabilities+ putStrLn$ " Frequency in measurable ticks: "++ commaint one_second ++ "\n"+++ putStrLn$ "Performing FFT of "++ commaint target ++" numbers windowed into buffers of size "++ show bufsize ++"\n"++ results <- evaluate $ runParAsync$ do ++ strm1 <- countupWin bufsize target :: Par (WStream Elt)++ print_$ "\n Next, applying FFT filter... "+ strm2 <- streamMap fft_kern strm1 ++-- Make a pipeline of 10 stages:+-- strm2 <- foldl (\ s _ -> streamMap kern0) strm1 [1..10]++ print_$ "\n Stream graph constructed, returning from Par computation... "+ return strm2++ measureRate results+ putStrLn$ "End of stream reached. All done."+++print_ msg = trace msg $ return ()++-- work pop 1 peek N push 1 +-- float->float filter +-- firFilter n coefs = +-- {++-- float sum = 0;+-- for (int i = 0; i < N; i++)+-- sum += peek(i) * COEFF[N-1-i];+-- pop();+-- push(sum);+-- }+-- }+++{-+ Notes:++++ -}
+ examples/stream/simple1_measureSrc.hs view
@@ -0,0 +1,35 @@+{-# OPTIONS_GHC -fwarn-unused-imports #-}++module Main(main) where++import Control.Monad+import Control.Monad.Par +import Control.Monad.Par.Stream as S+import Control.Monad.Par.OpenList+import Control.DeepSeq+import Control.Exception++-- import Data.Array.Unboxed as U+import Data.Array.CArray as C+import Data.Complex+import Data.Int+import Data.Word+import Data.List (intersperse)+import Data.List.Split (chunk)++import System.CPUTime+import System.CPUTime.Rdtsc+import GHC.Conc as Conc+import GHC.IO (unsafePerformIO, unsafeDupablePerformIO, unsafeInterleaveIO)+import Debug.Trace++--------------------------------------------------------------------------------+-- Main script++main = do++ -- Generate 20 million elements:+ let s = countupWin 1024 (20 * 1000 * 1000) :: Par (WStream Int)+ measureRate $ runParAsync s+ + putStrLn$ "Done with 5 million elements."
+ examples/sumeuler/ListAux.hs view
@@ -0,0 +1,41 @@+module ListAux where++import Data.List+++-- splitting into n parts, and its inverse:++splitIntoN :: Int -> [a] -> [[a]]+splitIntoN n xs = takeIter parts xs+ where l = length xs+ parts = zipWith (+) ((replicate (l `mod` n) 1) ++ repeat 0)+ (replicate n (l `div` n))+takeIter :: [Int] -> [a] -> [[a]]+takeIter [] [] = []+takeIter [] _ = error "elements left over"+takeIter (t:ts) xs = hs : takeIter ts rest+ where (hs,rest) = splitAt t xs++unSplit :: [[a]] -> [a]+unSplit = concat++-- splitting into parts of same size. Inverse is concat again.++splitAtN :: Int -> [a] -> [[a]]+splitAtN n [] = []+splitAtN n xs = ys : splitAtN n zs+ where (ys,zs) = splitAt n xs++----------------------------------------++-- splitting round-robin until list runs empty, and its inverse:++unshuffle :: Int -> [a] -> [[a]]+unshuffle n xs = [takeEach n (drop i xs) | i <- [0..n-1]]+ where takeEach n [] = []+ takeEach n (x:xs) = x : takeEach n (drop (n-1) xs)++-- inverse to unshuffle+shuffle :: [[a]] -> [a]+shuffle = concat . transpose+
+ examples/sumeuler/Makefile view
@@ -0,0 +1,7 @@+include ../common.mk++sumeuler.exe : $(wildcard *.hs) ../../Control/Monad/Par.hs+ $(GHC) -O2 -cpp --make -i../.. SumEuler.hs -o $@ -threaded -rtsopts++clean:+ rm -f *.exe *.hi *.o
+ examples/sumeuler/SumEuler.hs view
@@ -0,0 +1,287 @@+{-# OPTIONS -Wall #-}+--+-- Euler totient function (strategic version).+-- Orig taken from "Research Directions in Parallel Functional Programming",+-- Chapter "Performance Monitoring", Nathan Charles and Colin Runciman.+--+-- (c) 2001 Hans-Wolfgang Loidl+--+-- modifications by Jost Berthold, 07/2008:+-- ported to current GHC = hierarchical libraries+-- removed some dead (unused) code+-- simplified/secured usage+-- included a reference computation (using prime numbers)+-- tested best version (JFP_Final) against two "equivalents" using+-- strategies+--+---------------------------------------------------------------------------++module Main where++import System.Environment (getArgs)++import Control.Monad.Par++import Control.Monad (when)++import ListAux -- split/join functions, put in new module+import SumEulerPrimes++---------------------------------------------------------------------------+-- Generic clustering routines++-- Classes+-- maybe: class (Functor c) => MMonad c where { ... mmap = fmap } +class MMonad c where+ munit :: a -> c a+ mjoin :: c (c a) -> c a+ mmap :: (a -> b) -> c a -> c b++class (MMonad c) => MMonadPlus c where+ mzero :: c a+ mplus :: c a -> c a -> c a++class (MMonad c) => Cluster c where+ cluster :: Int -> c a -> c (c a)+ decluster :: c (c a) -> c a+ lift :: (c a -> b) -> (c (c a) -> (c b))+ -- default defs+ --cluster = ???+ decluster = mjoin+ lift = mmap++-- Instances+instance MMonad [] where+ munit x = [x]+ mjoin = concat+ mmap = map++instance Cluster [] where+ cluster = splitAtN++---------------------------------------------------------------------------++usage :: String+usage = "Usage: <program> version size chunksize"+ ++"\nFor versions see source code."++main :: IO ()+main = do args <- getArgs+ let + lenArgs = length args+ when (lenArgs < 3) + (putStrLn (usage ++ "\n(using defaults: 38,5000,100)"))+ let + argDef :: Read a => Int -> a -> a+ argDef m defVal | m < lenArgs = read (args!!m)+ | otherwise = defVal+ x, n, c :: Int+ x = argDef 0 38 -- which sumEuler to use+ n = argDef 1 5000 -- size of the interval+ c = argDef 2 100 -- chunksize+ -- parallel computation+ (res, _str) = case x of++ _ -> (sumEuler_monadpar c n, "monad-par version")+#if 0+ ------------------+ -- BEST VERSION:+ 38 -> (sumEulerJFP_Final c n, "JFP_Final paper version (splitAtN)")+ -- VERSIONS TO TEST ADDITIONALLY:+-- 48 -> (sumEulerS8 c n, "parallel w/ parChunkFoldMap strategy")+-- 58 -> (sumEulerS8' c n, "parallel w/ parChunkFold'Map strategy") + 8 -> (sumEulerJFP c n, "JFP paper version (splitAtN)")+ ------------------+ 0 -> (sumEuler_seq n, "sequential")+ 1 -> (sumEulerS1 n, "parallel w/ parList strategy")+ -- not bad:+ 2 -> (sumEulerS2 c n, "parallel w/ parListChunk")+ 3 -> (sumEulerChunk c n,"parallel w/ chunkify")+ 4 -> (sumEulerShuffle c n,"parallel w/ shuffle")+ 5 -> (sumEulerCluster c n,"parallel w/ generic clustering")+ -- not bad:+ 6 -> (sumEulerS6 c n, "parallel w/ parListChunk over reversed list")+-- 7 -> (sumEulerS7 c n, "parallel w/ parChunkFoldMap strategy")+ 18 -> (sumEulerJFP1 c n, "JFP1 paper version (splitIntoChunks)")+ 28 -> (sumEulerJFP0 c n, "JFP0 paper version (explicit list comprh)")+-- 9 -> (sumEulerStepList c n, "parallel w/ seqStepList for strategic shuffling")+ _ -> error "undefined version."+#endif++ putStrLn ("sumEuler [" ++ show base ++ ".." ++ show (base+n) ++ "] = " ++ show res)++ -- reference implementation (which is rather fast)+ let expected = sumPhi n+ when False $ putStrLn ("Expected result: " ++ show expected)++---------------------------------------------------------------------------+-- main computation function in many variants++-- HERE: best versions in contrast++#if 0+sumEulerJFP :: Int -> Int -> Int+sumEulerJFP c n = sum (map (sum . map euler) (splitAtN c (mkList n))+ `using` parList rdeepseq) ++sumEulerJFP_Final :: Int -> Int -> Int+sumEulerJFP_Final c n = sum ([(sum . map euler) x | x <- splitAtN c [n,n-1..0]]+ `using` parList rdeepseq) +#endif++sumEuler_monadpar :: Int -> Int -> Int+sumEuler_monadpar c n = runPar $+-- sum `fmap` parMap (sum . map euler) (splitAtN c [n,n-1..0])+ sum `fmap` parMap euler [n,n-1..0]+++-- -- using a fold-of-map strategy w/ folding inside a chunk+-- sumEulerS8 :: Int -> Int -> Int+-- sumEulerS8 c n = parChunkFoldMap c rnf (+) euler (mkList n)+-- +-- -- using a fold-of-map strategy w/ STRICT LEFT-folding inside a chunk+-- sumEulerS8' :: Int -> Int -> Int+-- sumEulerS8' c n = parChunkFoldMap' c rnf (+) euler (mkList n)+-- +-- -- parallel fold-of-map with chunking over fold and map+-- parChunkFoldMap :: (NFData b) => Int -> Strategy b -> +-- (b -> b -> b) -> (a -> b) -> [a] -> b+-- parChunkFoldMap c s f g xs = foldl1 f (map (foldl1 f . map g) +-- (splitAtN c xs)+-- `using` parList s) +-- +-- -- parallel fold-of-map with chunking over fold and map+-- parChunkFoldMap' :: (NFData b) => Int -> Strategy b -> +-- (b -> b -> b) -> (a -> b) -> [a] -> b+-- parChunkFoldMap' c s f g xs = foldl1' f (map (foldl1' f . map g) +-- (splitAtN c xs)+-- `using` parList s) ++#if 0+-----------------------------------------------------------------------+-- OTHER VARIANTS++-- strategic function application+sumEulerS1 :: Int -> Int+sumEulerS1 n = sum ( map euler (mkList n)+ `using` + parList rdeepseq )++-- NUKED:+-- sumEulerS1 c n = sum $|| (parListChunk c rnf) $ map euler $ mkList $ n++-- naive parallel version w/ parList+sumEulerS2 :: Int -> Int -> Int+sumEulerS2 c n = sum ( map euler (mkList n)+ `using` + parListChunk c rdeepseq )++-- using a parallel fold over a chunkified list+sumEulerS6 :: Int -> Int -> Int+sumEulerS6 c n = sum (map (sum . map euler) (splitAtN c (mkList n))+ `using` parList rdeepseq) ++-- -- using a fold-of-map strategy over a chunkified list+-- sumEulerS7 :: Int -> Int -> Int+-- sumEulerS7 c n = parFoldChunkMap c rnf (+) euler (mkList n)++-- explicit restructuring+sumEulerChunk :: Int -> Int -> Int+sumEulerChunk c n = sum (parMap rdeepseq ( \ xs -> sum (map euler xs)) + (splitAtN c (mkList n)))++-- using generic clustering functions+sumEulerCluster :: Int -> Int -> Int+sumEulerCluster c n = sum ((lift worker) (cluster c (mkList n)) + `using` parList rdeepseq)+ where worker = sum . map euler++-- using a shuffling to improve load balance+sumEulerShuffle :: Int -> Int -> Int+sumEulerShuffle c n = sum ((map worker) (unshuffle (noFromSize c n) (mkList n))+ `using` parList rdeepseq)+ where worker = sum . map euler++noFromSize :: Int -> Int -> Int+noFromSize c n | n `mod` c == 0 = n `div` c + | otherwise = n `div` c + 1++-- -- Evaluates every n-th element in the list starting with the first elem+-- seqStepList :: Int -> Strategy a -> Strategy [a]+-- seqStepList _ _strat [] = ()+-- seqStepList n strat (x:xs) = strat x `pseq` (seqStepList n strat (drop (n-1) xs))+-- +-- seqStepList' :: Int -> Strategy a -> Strategy [a]+-- -- seqStepList' _ strat [] = ()+-- seqStepList' n strat xs = parList (\ i -> seqStepList n strat (drop i xs)) [0..n-1]+-- +-- sumEulerStepList :: Int -> Int -> Int+-- sumEulerStepList c n = sum ( map euler (mkList n)+-- `using` +-- seqStepList' n' rnf )+-- where --worker = sum . map euler+-- n' = if n `mod` c == 0 then n `div` c else (n `div` c)+1++-- ---------------------------------------------------------------------------+-- Variants of the code for the JFP paper+-- ---------------------------------------------------------------------------++sumEulerJFP0 :: Int -> Int -> Int+sumEulerJFP0 c n = sum ([ (sum . map euler) [ c*i+j | j <- [0..c-1], c*i+j<=n ]+ | i <- [0..(n+c-1) `div` c - 1] ]+ `using` parList rdeepseq) ++sumEulerJFP1 :: Int -> Int -> Int+sumEulerJFP1 c n = sum (map (sum . map euler) (splitIntoChunks c n)+ `using` parList rdeepseq) ++#endif++splitIntoChunks :: Int -> Int -> [[Int]]+splitIntoChunks c n = [ [ c*i+j | j <- [0..c-1], c*i+j<=n ]+ | i <- [0..(n+c-1) `div` c - 1] ]++-- boring sequential version+sumEuler_seq :: Int -> Int+sumEuler_seq = sum . map euler . mkList ++---------------------------------------------------------------------------+-- smallest input for euler+base :: Int+base = 0++-- produce a list of input values+mkList :: Int -> [Int]+mkList = reverse . enumFromTo base . (+ base)+-- random numbers+-- mkList seed n = take n (randoms seed)++---------------------------------------------------------------------------+-- main fct++euler :: Int -> Int+euler n = length (filter (relprime n) [1..(n-1)])++---------------------------------------------------------------------------+-- orig code from Nathan+{-+euler :: Int -> Int+euler n = let+ relPrimes = let+ numbers = [1..(n-1)]+ in+ numbers `par` (filter (relprime n) numbers)+ in+ (spine relPrimes) `par` (length relPrimes)+-}++---------------------------------------------------------------------------+-- aux fcts++hcf :: Int -> Int -> Int+hcf x 0 = x+hcf x y = hcf y (rem x y)++relprime :: Int -> Int -> Bool+relprime x y = hcf x y == 1+
+ examples/sumeuler/SumEulerPrimes.hs view
@@ -0,0 +1,36 @@+module SumEulerPrimes where++import Data.List++sumPhi n = sum (map phiOpt [1..n])++phiOpt :: Int -> Int+phiOpt 1 = 0+phiOpt n = foldl (*) 1 [ (p-1)*p^(k-1)+ | (p,k) <- primefactors n ]++-- factorise n to a list of (prime, multiplicity)+primefactors :: Int -> [(Int,Int)]+primefactors n | n <= 1 = []+ | otherwise = primeList (primesIn primes n)++-- gather identical primes in the list+primeList :: [Int] -> [(Int,Int)]+primeList ps = [ (x, length (filter (==x) ps))+ | x <- nub ps ]++-- brute-force factorisation, using precomputed prime list+primesIn :: [Int] -> Int -> [Int]+primesIn [] _ = error "no primes left!"+primesIn ps@(p:rest) n | p > n = []+ | n `mod` p == 0 = p:primesIn ps (n `div` p)+ | otherwise = primesIn rest n++-- prime numbers, by sieve of Eratosthenes+primes :: [Int]+primes = sieve [2..]+sieve :: [Int] -> [Int]+sieve [] = []+sieve (x:xs) = x: (sieve (filter (not . multiple) xs))+ where multiple y = rem y x == 0+
+ examples/timeout.sh view
@@ -0,0 +1,91 @@+#!/bin/bash+#+# The Bash shell script executes a command with a time-out.+# Upon time-out expiration SIGTERM (15) is sent to the process. If the signal+# is blocked, then the subsequent SIGKILL (9) terminates it.+#+# Based on the Bash documentation example.++# Hello Chet,+# please find attached a "little easier" :-) to comprehend+# time-out example. If you find it suitable, feel free to include+# anywhere: the very same logic as in the original examples/scripts, a+# little more transparent implementation to my taste.+#+# Dmitry V Golovashkin <Dmitry.Golovashkin@sas.com>++scriptName="${0##*/}"++declare -i DEFAULT_TIMEOUT=9+declare -i DEFAULT_INTERVAL=1+declare -i DEFAULT_DELAY=1++# Timeout.+declare -i timeout=DEFAULT_TIMEOUT+# Interval between checks if the process is still alive.+declare -i interval=DEFAULT_INTERVAL+# Delay between posting the SIGTERM signal and destroying the process by SIGKILL.+declare -i delay=DEFAULT_DELAY++function printUsage() {+ cat <<EOF++Synopsis+ $scriptName [-t timeout] [-i interval] [-d delay] command+ Execute a command with a time-out.+ Upon time-out expiration SIGTERM (15) is sent to the process. If SIGTERM+ signal is blocked, then the subsequent SIGKILL (9) terminates it.++ -t timeout+ Number of seconds to wait for command completion.+ Default value: $DEFAULT_TIMEOUT seconds.++ -i interval+ Interval between checks if the process is still alive.+ Positive integer, default value: $DEFAULT_INTERVAL seconds.++ -d delay+ Delay between posting the SIGTERM signal and destroying the+ process by SIGKILL. Default value: $DEFAULT_DELAY seconds.++As of today, Bash does not support floating point arithmetic (sleep does),+therefore all delay/time values must be integers.+EOF+}++# Options.+while getopts ":t:i:d:" option; do+ case "$option" in+ t) timeout=$OPTARG ;;+ i) interval=$OPTARG ;;+ d) delay=$OPTARG ;;+ *) printUsage; exit 1 ;;+ esac+done+shift $((OPTIND - 1))++# $# should be at least 1 (the command to execute), however it may be strictly+# greater than 1 if the command itself has options.+if (($# == 0 || interval <= 0)); then+ printUsage+ exit 1+fi++# kill -0 pid Exit code indicates if a signal may be sent to $pid process.+(+ ((t = timeout))++ while ((t > 0)); do+ sleep $interval+ kill -0 $$ || exit 0+ ((t -= interval))+ done++ # Be nice, post SIGTERM first.+ # The 'exit 0' below will be executed if any preceeding command fails.+ kill -s SIGTERM $$ && kill -0 $$ || exit 0+ sleep $delay+ kill -s SIGKILL $$+) 2> /dev/null &++exec "$@"
+ monad-par.cabal view
@@ -0,0 +1,93 @@+Name: monad-par+Version: 0.1+Synopsis: A library for parallel programming based on a monad++Description: This library offers an alternative parallel programming+ API to that provided by the @parallel@ package.++ The 'Par' monad allows the simple description of+ parallel computations, and can be used to add+ parallelism to pure Haskell code. The basic API+ is straightforward: the monad supports forking+ and simple communication in terms of 'IVar's.++ The library comes with an efficient work-stealing+ implementation, but the internals are also+ exposed so that you can build your own scheduler+ if necessary.++ Examples of use can be found in the examples/ directory+ of the source package.++Homepage: https://github.com/simonmar/monad-par+License: BSD3+License-file: LICENSE+Author: Simon Marlow+Maintainer: Simon Marlow <marlowsd@gmail.com>+Copyright: (c) Simon Marlow 2011+Stability: Experimental+Category: Parallelism+Build-type: Simple+Cabal-version: >=1.2++extra-source-files:+ examples/benchlist.txt+ examples/benchmark.sh+ examples/blackscholes_data.hs+ examples/blackscholes.hs+ examples/cholesky.hs+ examples/cholesky_matrix6.dat+ examples/coins.hs+ examples/common.mk+ examples/get_cholesky_data.sh+ examples/Makefile+ examples/mandel.hs+ examples/matmult/ListAux.hs+ examples/matmult/Makefile+ examples/matmult/MatMult.hs+ examples/matmult/matmult.stdout+ examples/minimax/Board.hs+ examples/minimax/Game.hs+ examples/minimax/Main.hs+ examples/minimax/Makefile+ examples/minimax/minimax.stdout+ examples/minimax/Prog.hs+ examples/minimax/Tree.hs+ examples/minimax/Wins.hs+ examples/nbody.hs+ examples/ntimes+ examples/ntimes_minmedmax+ examples/parfib.hs+ examples/partree/Makefile+ examples/partree/partree.hs+ examples/partree/Tree.hs+ examples/plot_scaling.hs+ examples/PortablePixmap.lhs+ examples/primes.hs+ examples/queens.hs+ examples/run_tests.sh+ examples/stream/DEVLOG.txt+ examples/stream/disjoint_working_sets_pipeline.hs+ examples/stream/fft_pipeline.hs+ examples/stream/Makefile+ examples/stream/simple1_measureSrc.hs+ examples/sumeuler/ListAux.hs+ examples/sumeuler/Makefile+ examples/sumeuler/SumEuler.hs+ examples/sumeuler/SumEulerPrimes.hs+ examples/timeout.sh+ tests/AListTest.hs+ tests/Test.hs+ Control/Monad/Par/Stream.hs++Library+ Exposed-modules: Control.Monad.Par+ , Control.Monad.Par.OpenList+ , Control.Monad.Par.AList+ , Control.Monad.Par.IList+ , Control.Monad.Par.Internal+ Build-depends: base >= 4 && < 5,+ deepseq >= 1.1 && < 1.2,+ HUnit >= 1.2+ ghc-options: -O2+ Other-modules:
+ tests/AListTest.hs view
@@ -0,0 +1,37 @@++import Control.Monad.Par.AList++--------------------------------------------------------------------------------+-- Testing++-- For testing:+bintree 0 x = x+bintree n x = Append sub sub+ where sub = bintree (n-1) x++showDbg ANil = "_"+showDbg (ASing x) = show x+showDbg (Append l r) = "("++showDbg l++" | "++showDbg r++")"+showDbg (AList l) = show l++alist_tests :: Test+alist_tests = + TestList + [++ 8 ~=? (length$ tail$ tail$ fromList [1..10])+ , 1 ~=? (length$ tail$tail$ cons 1$ cons 2$ cons 3 empty)++ , 253 ~=? (length$ tail$tail$tail$ bintree 8 $ singleton 'a')+ , 0 ~=? (length$ bintree 8 $ empty)++ , "((1 | 1) | (1 | 1))" ~=? (showDbg$ bintree 2 $ singleton 1)+ , "((_ | 1) | (1 | 1))" ~=? (showDbg$ tail$ bintree 2 $ singleton 1)+ , "(_ | (1 | 1))" ~=? (showDbg$ tail$tail$ bintree 2 $ singleton 1)++ ]++t = runTestTT alist_tests+++-- TODO: Quickcheck.
+ tests/Test.hs view
@@ -0,0 +1,74 @@+module Main where++import Test.HUnit++-- -----------------------------------------------------------------------------++-- Testing++_test :: IO ()+_test = do+ print ((runPar $ return 3) :: Int)+ print (runPar $ do r <- new; put r (3 :: Int); get r)+ print (runPar $ do r <- new; fork (put r (3::Int)); get r)+ print ((runPar $ do r <- new; get r) :: Int)++_test2 :: Int+_test2 = runPar $ do+ [a,b,c,d] <- sequence [new,new,new,new]+ fork $ do x <- get a; put b (x+1)+ fork $ do x <- get a; put c (x+2)+ fork $ do x <- get b; y <- get c; put d (x+y)+ fork $ do put a 3+ get d++_test3 :: Int+_test3 = runPar $ do+ a <- new+ put a (3::Int)+ both (return 1) (return 2)++-- is there a standard lib thing for this?++_test_pmrr1 :: Int+_test_pmrr1 = runPar$ parMapReduceRangeThresh 1 (InclusiveRange 1 100) + (return) (return `bincomp` (+)) 0+ where bincomp unary bin a b = unary (bin a b)++_unsafeio :: IO a -> Par a+_unsafeio io = let x = unsafePerformIO io in+ x `seq` return x++_print :: String -> Par ()+_print = _unsafeio . putStrLn++_waste_time :: Int -> Double+_waste_time n = loop n 1.00111+ where + loop 0 !x = x+ loop !n !x | x > 100.0 = loop (n-1) (x / 2)+ loop !n !x = loop (n-1) (x + x * 0.5011)+++_async_test1 = do -- A D B <pause> C E + putStrLn "A"+ evaluate$ runPar $+ do + fork $ do _print "B"+ _print$ "C "++ show (_waste_time 300000000)+ _print "D"+ putStrLn$ "E"++_async_test2 = do -- A D E or A D B E but no C+ putStrLn "A"+ evaluate$ runParAsync $+ do + fork $ do _print "B"+ _print$ "C "++ show (_waste_time 300000000)+ _print "D"+ putStrLn$ "E"+++-- TODO: add the async_tests above to the test list.+_par_tests :: Test+_par_tests = TestList []