packages feed

haskell-cnc 0.1.2 → 0.1.3

raw patch · 23 files changed

+558/−153 lines, 23 filesdep +HSHdep +MissingHdep −QuickCheckPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: HSH, MissingH

Dependencies removed: QuickCheck

API changes (from Hackage documentation)

- Intel.Cnc: instance Show (IO a)
- Intel.Cnc: instance Show (IORef a)
- Intel.Cnc: instance Show HiddenState5
- Intel.Cnc5: instance Show (IO a)
- Intel.Cnc5: instance Show (IORef a)
- Intel.Cnc5: instance Show HiddenState5
- Intel.Cnc6: instance Show (IO a)
- Intel.Cnc6: instance Show (IORef a)
- Intel.Cnc6: instance Show HiddenState5
- Intel.Cnc8: instance Exception EscapeStep
- Intel.Cnc8: instance Show EscapeStep
- Intel.Cnc8: instance Typeable EscapeStep
+ Intel.Cnc: cncFor :: Int -> Int -> (Int -> StepCode ()) -> StepCode ()
+ Intel.Cnc: cncFor2D :: (Int, Int) -> (Int, Int) -> (Int -> Int -> StepCode ()) -> StepCode ()
+ Intel.Cnc: instance [overlap ok] Show (IO a)
+ Intel.Cnc: instance [overlap ok] Show (IORef a)
+ Intel.Cnc: instance [overlap ok] Show HiddenState5
+ Intel.Cnc: itemsToList :: (Eq tag, Ord tag, Show tag) => ItemCol tag b -> StepCode [(tag, b)]
+ Intel.Cnc3: cncFor :: Int -> Int -> (Int -> StepCode ()) -> StepCode ()
+ Intel.Cnc3: cncFor2D :: (Int, Int) -> (Int, Int) -> (Int -> Int -> StepCode ()) -> StepCode ()
+ Intel.Cnc3: itemsToList :: (Eq tag, Ord tag, Show tag) => ItemCol tag b -> StepCode [(tag, b)]
+ Intel.Cnc5: cncFor :: Int -> Int -> (Int -> StepCode ()) -> StepCode ()
+ Intel.Cnc5: cncFor2D :: (Int, Int) -> (Int, Int) -> (Int -> Int -> StepCode ()) -> StepCode ()
+ Intel.Cnc5: instance [overlap ok] Show (IO a)
+ Intel.Cnc5: instance [overlap ok] Show (IORef a)
+ Intel.Cnc5: instance [overlap ok] Show HiddenState5
+ Intel.Cnc5: itemsToList :: (Eq tag, Ord tag, Show tag) => ItemCol tag b -> StepCode [(tag, b)]
+ Intel.Cnc6: cncFor :: Int -> Int -> (Int -> StepCode ()) -> StepCode ()
+ Intel.Cnc6: cncFor2D :: (Int, Int) -> (Int, Int) -> (Int -> Int -> StepCode ()) -> StepCode ()
+ Intel.Cnc6: instance [overlap ok] Show (IO a)
+ Intel.Cnc6: instance [overlap ok] Show (IORef a)
+ Intel.Cnc6: instance [overlap ok] Show HiddenState5
+ Intel.Cnc6: itemsToList :: (Eq tag, Ord tag, Show tag) => ItemCol tag b -> StepCode [(tag, b)]
+ Intel.Cnc8: cncFor :: Int -> Int -> (Int -> StepCode ()) -> StepCode ()
+ Intel.Cnc8: cncFor2D :: (Int, Int) -> (Int, Int) -> (Int -> Int -> StepCode ()) -> StepCode ()
+ Intel.Cnc8: instance [overlap ok] Exception EscapeStep
+ Intel.Cnc8: instance [overlap ok] Show EscapeStep
+ Intel.Cnc8: instance [overlap ok] Typeable EscapeStep
+ Intel.Cnc8: itemsToList :: (Eq tag, Ord tag, Show tag) => ItemCol tag b -> StepCode [(tag, b)]

Files

Intel/Cnc.Header.hs view
@@ -2,6 +2,9 @@   , BangPatterns   , MagicHash    , ScopedTypeVariables+  , TypeFamilies +  , UndecidableInstances+  , OverlappingInstances   , DeriveDataTypeable   , MultiParamTypeClasses   #-}@@ -35,18 +38,20 @@ {-|   This module implements the Intel Concurrent Collections (CnC) programming model.   The variations of this module ("Intel.Cnc3", "Intel.Cnc5", "Intel.Cnc6", and "Intel.Cnc8")-  each implement the same programming model using different schedulers.+  each implement the same programming model using different runtime schedulers.   All of them internally use the IO monad but expose a pure interface.   (The module "Intel.CncPure" is an alternative implementation that   exposes the same interface as this module but is internally pure.)     CnC is a data-flow like deterministic parallel programming model.-  To use it, one constructs a /CnC graph/ of computation steps. -  Edges in the graph are control and data relationships, which are +  To use it, one constructs a /CnC graph/ of computation steps.  +  Steps are arbitrary Haskell functions (which may themselves expose+  parallelism through 'GHC.Conc.par').+  Edges in the graph are control and data relationships,    implemented by  /tag/ and /item/ collections respectively. -  A brief introduction to CnC using this module can be found at <http://software.intel.com/foobar>.+  A brief introduction to CnC using this module can be found at <http://software.intel.com/en-us/blogs/2010/05/27/announcing-intel-concurrent-collections-for-haskell-01/>.   General documentation on the CnC model can be found at     <http://software.intel.com/en-us/articles/intel-concurrent-collections-for-cc/>. @@ -61,13 +66,16 @@                   -- running inside individual nodes of CnC graphs (in parallel).		       		  StepCode(..),  		  newItemCol, newTagCol, prescribe, -		  putt, put, get,+		  putt, put, get,  		  initialize, finalize,-                   runGraph, ++                  itemsToList, 		  stepPutStr, cncPutStr, cncVariant, +                  -- Undocumented experimental features:                   Item, newItem, readItem, putItem,+                  cncFor, cncFor2D,                    tests,  -- * Example Program@@ -86,7 +94,7 @@ cncGraph =    do tags  <- 'newTagCol'      items <- 'newItemCol'-     'prescribe' tags (mystep items)+     'prescribe' tags (myStep items)      'initialize' $         do 'put' items \"left\"  \"hello \"            'put' items \"right\" \"world \"@@ -119,9 +127,9 @@   undesirable, option.)   -} -import Data.Set as Set-import Data.HashTable as HT-import Data.Map as Map+import qualified Data.Set as Set+import qualified Data.HashTable as HT+import qualified Data.Map as Map import Data.Int import Data.IORef import Data.Word@@ -143,7 +151,12 @@  import Test.HUnit +-- Inline the utility library as well:+#ifndef INCLUDEMETHOD import Intel.CncUtil as GM hiding (tests)+#else+#include "CncUtil.hs"+#endif  ------------------------------------------------------------ -- Configuration Toggles:@@ -158,12 +171,14 @@  #ifdef HASHTABLE_TEST #define ITEMPREREQS (Eq tag, Ord tag, Hashable tag, Show tag)-#elif USE_GMAP+#else +#ifdef USE_GMAP -- #define ITEMPREREQS (Ord tag, Eq tag, GMapKey tag, Show tag) #define ITEMPREREQS (GMapKey tag) #else #define ITEMPREREQS (Eq tag, Ord tag, Show tag) #endif+#endif  ------------------------------------------------------------ -- Type signatures for the primary API operations:@@ -195,6 +210,11 @@ -- |Construct a new item collection. newItemCol :: ITEMPREREQS => GraphCode (ItemCol tag val) +-- |Convert an entire item collection into an association list.  In+-- general, this can only be done from the 'finalize' step and+-- requires selecting a runtime scheduler which supports /quiescence/, that is,+-- a scheduler that waits for all active steps to complete before executing 'finalize'.+-- (Currently, all schedulers but version 3 support quiescence.) itemsToList :: ITEMPREREQS => ItemCol tag b -> StepCode [(tag,b)]  -- |Steps are functions that take a single 'tag' as input and perform@@ -206,8 +226,6 @@ --                             Implementation                                 -- -------------------------------------------------------------------------------- -cncVariant="io/" ++ show (CNC_SCHEDULER :: Int)- -- These 'new' functions need an argument if we don't want to run in -- to the monomorphism restriction (-fno-monomorphism-restriction) #ifndef SUPPRESS_newItemCol@@ -251,12 +269,12 @@        steps <- STEPLIFT readIORef _steps --       if memoize  --        then +--        else  #ifdef MEMOIZE        if Set.member tag set         then return ()         else STEPLIFT writeIORef _set (Set.insert tag set) #else---        else         return () #endif        action steps tag@@ -280,7 +298,7 @@ initialize x = x #endif --- | Construct a CnC graph and execute it to completion.  Completion+-- |Construct a CnC graph and execute it to completion.  Completion --   is defined as the 'finalize' action having completed. runGraph :: GraphCode a -> a #ifndef SUPPRESS_runGraph@@ -299,8 +317,30 @@  -- |An informal identifier of the CnC version presently in use (for example, identifying a scheduler implementation). cncVariant :: String---cncVariant="io/" ++ show (CNC_SCHEDULER :: Int)+cncVariant ="io-based, scheduler " ++ show (CNC_SCHEDULER :: Int)  +#ifdef USE_GMAP+       ++ ", gmap enabled"+#else +       ++ ", gmap disabled"+#endif+#ifdef MEMOIZE+       ++ ", memoize enabled"+#else +       ++ ", memoize disabled"+#endif+#ifdef INCLUDEMETHOD+       ++ ", #include method"+#endif+#ifdef REPEAT_PUT_ALLOWED+       ++ ", repeated identical puts permitted"+#endif+#ifdef DEBUG_HASKELL_CNC+       ++ ", DEBUG enabled"+#endif +++ -------------------------------------------------------------------------------- --  Testing --------------------------------------------------------------------------------@@ -346,9 +386,10 @@ 	     c <- itemsToList d3 	     return (a,b,c) +#ifndef INCLUDEMETHOD tests :: Test tests = TestList [ smalltest ]-+#endif  -------------------------------------------------------------------------------- -- EXPERIMENTAL:@@ -366,34 +407,64 @@ putItem  = error "putItem not implemented under this scheduler" #endif --------------------------------------------------------------------------------- ----------------------------------------------------------------Version 1: Serial--- (This version has been disabled/removed.)+-- Internal function. We may allow extending the graph from within a+-- step.  I'm not sure what the best name for this is.  +graphInStep :: GraphCode a -> StepCode a+#ifndef SUPPRESS_graphInStep+-- Default is to assume the monads are the same:+graphInStep x = x+#endif --- Version 2: --- (This version has been disabled/removed.) --- Here we do the tail call optimization for the common case of a single prescribed step.+#ifndef SUPPRESS_cncFor+-- | \"@cncFor start end body@\" runs @body@ in parallel over the inclusive range @[start..end]@.+-- +-- Frequently, CnC graphs are serial within steps but parallel at the+-- level of the graph.  In contrast, 'cncFor' exposes parallelism+-- /within a step/.  Whether the body of the parallel for is doing+-- work, or just spawning work via 'putt', 'cncFor' can help+-- distribute the work more efficiently.+cncFor :: Int -> Int -> (Int -> StepCode ()) -> StepCode ()+-- Parallel for and tag-ranges can make things much more efficient for+-- a common case. +-- +-- It may be nice under some schedulers to use forkOnIO to explicitly+-- disseminate the ranges to processors.  This alas wouldn't work well+-- with nested cncFor loops.  But if we disencourage those and+-- explicitly provide cncFor2D etc...+-- +cncFor start end body = + do ts <- graphInStep newTagCol+    --stepPutStr$ "Performing cncFor on range " ++ show (start,end) ++ "\n"+    graphInStep$ prescribe ts$ \(x,y) -> +      do --stepPutStr$ "  Executing range segment: "++ show (x,y) ++ "\n"+         for_ x (y+1) body+    --stepPutStr$ "Desired segments "++ show (4*numCapabilities) ++ " putting first segment...\n"+    let range_segments = splitInclusiveRange (4*numCapabilities) (start,end)+    --stepPutStr$ "PUTTING RANGES "++ show (length range_segments) ++" "++ show range_segments ++"\n"+    forM_ range_segments (putt ts)+#endif +#ifndef SUPPRESS_cncFor2D+-- | A two dimensional loop.+{-# INLINE cncFor2D #-}+cncFor2D :: (Int,Int) -> (Int,Int) -> (Int -> Int -> StepCode ()) -> StepCode ()+-- In this version we don't do anything special for 2D loops:+cncFor2D (s1,s2) (e1,e2) body =+  cncFor s1 e1 $ \ i ->  +   cncFor s2 e2 (body i) ---------------------------------------------------------------- TODO  TODO TODO TODO TODO TODO TODO TODO TODO TODO  -- -------------------------------------------------------------+-- Stripe distribution -- only parallelize the outer loop.+-- (Tiles would be better but slightly more complex.)+-- Oddly... this doesn't do better in any scheduler on the current benchmark...+-- cncFor2D (s1,s2) (e1,e2) body =+--   cncFor s1 e1 $ \ i ->  +--    for_ s2 (e2+1) (body i)+#endif --- [2010.02.11] I need to look at unecessary control-flow--- back-and-forth.  Currently, because of this "depth-first"--- optimization, I will call down to a child and then probably return--- (unless GHC manages to turn it into a tail call, maybe it does).  I--- could help out GHC by just queueing a list of spawned downstream--- tasks as I go through a step.  When the step is done, the list can--- be spawned.  At that point if there is only one downstream it can--- definitely be a tail call.  ----------------------------------------------------------------------------------   -- <eof> *** This file will be included into the per-scheduler implementations. *** 
Intel/Cnc.hs view
@@ -2,6 +2,9 @@   , BangPatterns   , MagicHash    , ScopedTypeVariables+  , TypeFamilies +  , UndecidableInstances+  , OverlappingInstances   , DeriveDataTypeable   , MultiParamTypeClasses   #-}
Intel/Cnc3.hs view
@@ -2,6 +2,9 @@   , BangPatterns   , MagicHash    , ScopedTypeVariables+  , TypeFamilies +  , UndecidableInstances+  , OverlappingInstances   , DeriveDataTypeable   , MultiParamTypeClasses   #-}@@ -13,9 +16,11 @@ #define CNC_SCHEDULER 3 #define STEPLIFT  id$ #define GRAPHLIFT id$+-- #define SUPPRESS_cncFor+-- #define SUPPRESS_cncFor2D #include "Cnc.Header.hs" -type TagCol  a   = (IORef (Set a), IORef [Step a])+type TagCol  a   = (IORef (Set.Set a), IORef [Step a]) type ItemCol a b = MutableMap a b  type StepCode  = IO @@ -58,8 +63,8 @@ -------------------------------------------------------------------------------- -- EXPERIMENTAL: ----------------------------------------------------------------------------------- This is a proposed addition for manipulating items outside of item collections. +-- This is a proposed addition for manipulating items outside of item collections. type Item = MVar newItem  = newEmptyMVar readItem = readMVar@@ -67,3 +72,37 @@   do b <- tryPutMVar mv x      if b then return () 	  else error "Violation of single assignment rule; second put on Item!"++#ifdef SUPPRESS_cncFor+#warning "Selecting specialized version of cncFor for Scheduler 3"+-- Because this scheduler doesn't have the *nested* structure that,+-- say, scheduler 8 does, the default definition of cncFor will not+-- provide much benefit.  Instead, we try one that uses explicit+-- placement of threads.+cncFor start end body = + -- With this version we don't create any additional graph nodes.+ -- Instead, we create additional IO threads.+ do --stepPutStr$ "FORKING THREADS FOR CNCFOR!! Ranges: "++ show ranges++"\n"+    forM_ [0..numthreads-1] fork_thread      + where +    splitfactor = 1 -- TBB uses 4, but IO threads have more overhead...+    numthreads = numCapabilities * splitfactor+    ranges = splitInclusiveRange numthreads (start,end)+    fork_thread i = +     -- Assign the IO thread to a particular CPU:+     forkOnIO (i `quot` splitfactor) $ +       let (x,y) = ranges !! i in+       for_ x (y+1) body+#endif++#ifdef SUPPRESS_cncFor2D+-- cncFor2D (s1,s2) (e1,e2) body =+--   cncFor s1 e1 $ \ i ->  +--    cncFor s2 e2 (body i)++-- When using the default cncFor his one does vastly worse.  But with+-- the custom cncFor above, it is better.+cncFor2D (s1,s2) (e1,e2) body =+  cncFor s1 e1 $ \ i ->  +    for_ s2 (e2+1) (body i)+#endif
Intel/Cnc5.hs view
@@ -2,9 +2,11 @@   , BangPatterns   , MagicHash    , ScopedTypeVariables+  , TypeFamilies +  , UndecidableInstances+  , OverlappingInstances   , DeriveDataTypeable   , MultiParamTypeClasses-  , CPP   #-} -- State monad transformer is needed for both step & graph: #ifndef MODNAME@@ -55,3 +57,4 @@   do b <- STEPLIFT tryPutMVar mv x      if b then return () 	  else error "Violation of single assignment rule; second put on Item!"+
Intel/Cnc6.hs view
@@ -2,6 +2,9 @@   , BangPatterns   , MagicHash    , ScopedTypeVariables+  , TypeFamilies +  , UndecidableInstances+  , OverlappingInstances   , DeriveDataTypeable   , MultiParamTypeClasses   #-}
Intel/Cnc8.hs view
@@ -2,6 +2,9 @@   , BangPatterns   , MagicHash    , ScopedTypeVariables+  , TypeFamilies +  , UndecidableInstances+  , OverlappingInstances   , DeriveDataTypeable   , MultiParamTypeClasses   #-}@@ -16,6 +19,7 @@ #define SUPPRESS_newItemCol #define SUPPRESS_initialize #define SUPPRESS_itemsToList+#define SUPPRESS_graphInStep #include "Cnc.Header.hs"  --------------------------------------------------------------------@@ -36,7 +40,10 @@ -- escape a step's execution upon a failed get.  An alternative is to -- use the ContT monad transformer. -type TagCol a   = (IORef (Set a), IORef [Step a])+-- TODO: The Cilk-like functionality could be factored into its own+-- reusable module.++type TagCol a   = (IORef (Set.Set a), IORef [Step a]) --type ItemCol a b = MutableMap a b  -- Here the hidden state keeps track of @@ -50,7 +57,7 @@ newtype HiddenState8 = HiddenState8 (StepCode (), [()])  -- In this version we don't use MVars because gets don't block:-newtype ItemCol a b = ItemCol (IORef (Map a ((Maybe b), WaitingSteps)))+newtype ItemCol a b = ItemCol (IORef (Map.Map a ((Maybe b), WaitingSteps))) type WaitingSteps = [StepCode ()]  data EscapeStep = EscapeStep  deriving (Show, Typeable)@@ -82,8 +89,6 @@ -- the end of the step with a sync.  It needs a retry action to tuck -- into the state so that the step can store it if it needs to escape -- with an exception.--- --- DESIGN DECISION:  try_stepcode :: StepCode () -> StepCode a -> IO (Maybe a) try_stepcode retry m = wrapped  where@@ -216,6 +221,9 @@      fil (key, (Nothing, _)) = False      fil _                   = True ++-- To execute graph code inside a step we just need to lift it into the monad transformer:+graphInStep = S.lift  quiescence_support=True ; 
Intel/CncPure.hs view
@@ -723,7 +723,7 @@ 	     then putStr "EMPTIED\n" 	     else threadloop worldref blockedref newprimed (fresh ++ intags) -}-            return undefined+            return (error "CncPure distScheduler not complete yet")  -------------------------------------------------------------------------------- -- Run some steps, accumulate output, and then return to synchronize/schedule.@@ -988,6 +988,17 @@ 	  it = (IntMap.!) imap num       in (Just (finalmagic id (Map.toList it)), 	  Done tags items)++-- This is just a serial loop for now:+cncFor :: Int -> Int -> (Int -> StepCode ()) -> StepCode ()+cncFor start end body = for_ start (end+1) body++cncFor2D :: (Int,Int) -> (Int,Int) -> (Int -> Int -> StepCode ()) -> StepCode ()+cncFor2D (s1,s2) (e1,e2) body =+  cncFor s1 e1 $ \ i ->  +   cncFor s2 e2 (body i)++  -------------------------------------------------------------------------------- -- Testing:
Intel/CncUtil.hs view
@@ -30,7 +30,7 @@ -- |An internal utility module that supports the CnC implementations. #ifndef INCLUDEMETHOD module Intel.CncUtil (-		      foldRange, for_, splitN, forkJoin, +		      foldRange, for_, splitN, splitInclusiveRange, forkJoin,  		      doTrials, FitInWord (..),  		      GMapKey (..),  		      Hashable (..),@@ -43,6 +43,8 @@  		      ) where+#else+#warning "Loading CncUtil.hs through include method..." #endif  import GHC.Conc@@ -61,7 +63,7 @@ import Debug.Trace  import Test.HUnit-import Test.QuickCheck (quickCheck, (==>))+-- import Test.QuickCheck (quickCheck, (==>))  -------------------------------------------------------------------------------- -- Miscellaneous Utilities@@ -69,6 +71,7 @@  -- |A simple loop construct to use if you don't trust rewrite based deforestation. -- Usage foldRange start end acc, where start is inclusive, end uninclusive.+{-# INLINE foldRange #-} foldRange start end acc fn = loop start acc  where   loop !i !acc@@ -77,6 +80,7 @@  -- |My own forM, again, less trusting of optimizations. -- Inclusive start, exclusive end.+{-# INLINE for_ #-} for_ start end fn | start > end = error "for_: start is greater than end" for_ start end fn = loop start   where @@ -94,8 +98,33 @@     loop n ls = hd : loop (n-1) tl        where (hd,tl) = splitAt sz ls +-- Similar to splitN but for a (start,end) range not an actual list.+-- The first segment gets the extras and the rest are evenly sized:+-- splitInclusiveRange pieces (start,end) = +--   (start, start + portion - 1 + remain) : map fn [1 .. pieces-1]+--  where 	+--    len = end - start + 1 -- inclusive [start,end]+--    (portion, remain) = len `quotRem` pieces+--    fn i = let nextstart = start + i * portion + remain+--           in (nextstart, nextstart + portion - 1)  +-- Instead of having one oversized piece, spread the remainder one per+-- segment:+{-# INLINE splitInclusiveRange #-}+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) + -- |Run IO threads in parallel and wait till they're done. forkJoin actions =  -- I'm amazed this is not built-in.@@ -141,7 +170,8 @@ mmToList = HT.toList #warning "Enabling HashTable item collections.  These are not truly thread safe (yet)." -#elif USE_GMAP+#else +#ifdef USE_GMAP #warning "Using experimental indexed type family GMap implementation..." -- Trying to use GMaps: type MutableMap a b = IORef (GMap a (MVar b))@@ -190,6 +220,7 @@     do map <- readIORef col         return (DM.toList map) #endif+#endif  ------------------------------------------------------------ -- Hot Atomic Words operations@@ -322,15 +353,20 @@ #endif  -- Pairs can fit in words too!--- TODO: Use some code generation method to generate instances for all+-- FIXME TODO: Use some code generation method to generate instances for all -- combinations of small words/ints that fit in a machine word (a lot). instance FitInWord (Word16,Word16) where   toWord (a,b) = shiftL (fromIntegral a) 16 + (fromIntegral b)   fromWord n = (fromIntegral$ shiftR n 16,  		fromIntegral$ n .&. 0xFFFF) +instance FitInWord (Int16,Int16) where+  toWord (a,b) = shiftL (fromIntegral a) 16 + (fromIntegral b)+  fromWord n = (fromIntegral$ shiftR n 16, +		fromIntegral$ n .&. 0xFFFF)  + -------------------------------------------------------------------------------- -- ADT definition for generic Maps: --------------------------------------------------------------------------------@@ -348,16 +384,13 @@  -------------------------------------------------------------------------------- +-- What problems was I running into here:+-- It's hard to avoid conflicting instances, for example with the tuple instance.+-- I think I may need a NotFitInWord class constraint.. #if 0 instance FitInWord t => GMapKey t where-  -- data GMap t v            = GMapWord (GMap t v) deriving Show-  -- empty                    = GMapWord empty-  -- lookup k    (GMapWord m) = lookup (ord k) m-  -- insert k v  (GMapWord m) = GMapWord (insert (ord k) v m)-  -- alter  fn k (GMapWord m) = GMapWord (alter fn (ord k) m)-  -- toList      (GMapWord m) = map (\ (i,v) -> (chr i,v)) (toList m)   data GMap t v           = GMapInt (DI.IntMap v) deriving Show-  --empty                   = trace "\n <<<<< Empty FitInWord Gmap... >>>>\n"$ GMapInt DI.empty+  --empty                   = trace "\n <<<<< FitInWord Gmap... >>>>\n"$ GMapInt DI.empty   empty                   = GMapInt DI.empty   lookup k    (GMapInt m) = DI.lookup (wordToInt$ toWord k) m   insert k v  (GMapInt m) = GMapInt (DI.insert (wordToInt$ toWord k) v m)@@ -365,9 +398,44 @@   toList      (GMapInt m) = map (\ (i,v) -> (fromWord$ intToWord i, v)) $  			    DI.toList m - #else +-- Unit and Bool can have specialized implementations, but because+-- they also "FitInWord", these result in conflicts.+------------------------------------------------------------+instance GMapKey () where+  data GMap () v           = GMapUnit (Maybe v)+  empty                    = GMapUnit Nothing+  lookup ()   (GMapUnit v) = v+  insert () v (GMapUnit _) = GMapUnit $ Just v+  alter fn () (GMapUnit v) = GMapUnit $ fn v+  toList (GMapUnit Nothing) = []+  toList (GMapUnit (Just v)) = [((),v)]+instance GMapKey Bool where+  data GMap Bool v              = GMapBool (Maybe v) (Maybe v)+  empty                       = GMapBool Nothing Nothing+  lookup True  (GMapBool v _) = v+  lookup False (GMapBool _ v) = v+  insert True v  (GMapBool a b) = GMapBool (Just v) b+  insert False v (GMapBool a b) = GMapBool a (Just v)+  alter fn True  (GMapBool a b) = GMapBool (fn a) b+  alter fn False (GMapBool a b) = GMapBool a (fn b)+  toList (GMapBool Nothing Nothing)   = []+  toList (GMapBool (Just a) Nothing)  = [(True,a)]+  toList (GMapBool Nothing (Just b))  = [(False,b)]+  toList (GMapBool (Just a) (Just b)) = [(True,a),(False,b)]+------------------------------------------------------------++-- GMaps on Int keys become Data.IntMaps:+instance GMapKey Int where+  data GMap Int v         = GMapInt (DI.IntMap v) deriving Show+  empty                   = GMapInt DI.empty+  lookup k    (GMapInt m) = DI.lookup k m+  insert k v  (GMapInt m) = GMapInt (DI.insert k v m)+  alter  fn k (GMapInt m) = GMapInt (DI.alter fn k m)+  toList      (GMapInt m) = DI.toList m++-- Then other scalar keys can be converted to Ints: -- CODE DUPLICATION instance GMapKey Char where   data GMap Char v         = GMapChar (GMap Int v) deriving Show@@ -401,14 +469,6 @@   alter  fn k (GMapWord m) = GMapWord (alter fn (fromIntegral k) m)   toList      (GMapWord m) = map (\ (i,v) -> (fromIntegral i,v)) (toList m) -instance GMapKey Int where-  data GMap Int v         = GMapInt (DI.IntMap v) deriving Show-  empty                   = GMapInt DI.empty-  lookup k    (GMapInt m) = DI.lookup k m-  insert k v  (GMapInt m) = GMapInt (DI.insert k v m)-  alter  fn k (GMapInt m) = GMapInt (DI.alter fn k m)-  toList      (GMapInt m) = DI.toList m- instance GMapKey Int8 where   data GMap Int8 v        = GMapInt8 (GMap Int v) deriving Show   empty                    = GMapInt8 empty@@ -426,40 +486,28 @@   toList      (GMapInt16 m) = map (\ (i,v) -> (fromIntegral i,v)) (toList m)  -- TODO IFDEF 64 BIT THEN WE CAN FIT AN INT64 AND WORD64 TOO!!-#endif +-- Can't get past the "Conflicting family instance declarations"+-- instance GMapKey (Int16, Int16) where+--   data GMap (Int16,Int16) v         = GMapInt16Pair (GMap Int v) deriving Show+--   empty                     = trace "<<< Constructing Double-Int16 GMAP (Intmap) >>>> " $ +-- 			      GMapInt16Pair empty+--   lookup k (GMapInt16Pair m)    = lookup (fromIntegral k) m+--   insert k v (GMapInt16Pair m)  = GMapInt16Pair (insert (fromIntegral k) v m)+--   alter  fn k (GMapInt16Pair m) = GMapInt16Pair (alter fn (fromIntegral k) m)+--   toList      (GMapInt16Pair m) = map (\ (i,v) -> (fromIntegral i,v)) (toList m) --------------------------------------------------------------------------------- +#endif -instance GMapKey () where-  data GMap () v           = GMapUnit (Maybe v)-  empty                    = GMapUnit Nothing-  lookup ()   (GMapUnit v) = v-  insert () v (GMapUnit _) = GMapUnit $ Just v-  alter fn () (GMapUnit v) = GMapUnit $ fn v-  toList (GMapUnit Nothing) = []-  toList (GMapUnit (Just v)) = [((),v)] -instance GMapKey Bool where-  data GMap Bool v              = GMapBool (Maybe v) (Maybe v)-  empty                       = GMapBool Nothing Nothing-  lookup True  (GMapBool v _) = v-  lookup False (GMapBool _ v) = v-  insert True v  (GMapBool a b) = GMapBool (Just v) b-  insert False v (GMapBool a b) = GMapBool a (Just v)-  alter fn True  (GMapBool a b) = GMapBool (fn a) b-  alter fn False (GMapBool a b) = GMapBool a (fn b)-  toList (GMapBool Nothing Nothing)   = []-  toList (GMapBool (Just a) Nothing)  = [(True,a)]-  toList (GMapBool Nothing (Just b))  = [(False,b)]-  toList (GMapBool (Just a) (Just b)) = [(True,a),(False,b)]-+--------------------------------------------------------------------------------  -- |GMaps over pairs are implemented by nested GMaps. instance (GMapKey a, GMapKey b) => GMapKey (a, b) where   data GMap (a, b) v            = GMapPair (GMap a (GMap b v))-  empty		                = GMapPair empty+  empty		                = --trace "CONSTRUCTED GMAP USING NESTED MAPS!"$ +                                  GMapPair empty   lookup (a, b) (GMapPair gm)   = lookup a gm >>= lookup b    insert (a, b) v (GMapPair gm) = GMapPair $ case lookup a gm of 				    Nothing  -> insert a (insert b v empty) gm@@ -542,6 +590,8 @@ -- We also switch to a mutable data structure here: -------------------------------------------------------------------------------- +-- UNFINISHED:+ -- A key/value pair that works inside a GMap2. class GMapKeyVal k v where   data GMap2 k v :: *@@ -604,8 +654,13 @@ testCase str io = TestLabel str $ TestCase$ do putStrLn$ "\n *** Running unit test: "++str; io; putStrLn ""  test1 = testCase "Spot check list lengths"$ assertEqual "splitN" [[1,2], [3,4,5]] (splitN 2 [1..5]) -test2 = testCase "Quickcheck splitN - varying split size"$ -	quickCheck$ (\ (n::Int) -> n>0 ==> -		     (\ (l::[Int]) -> concat (splitN n l) == l))  -tests = TestList [test1, test2]++-- [2010.05.31] I don't have quickcheck working under 6.13.xx+-- test2 = testCase "Quickcheck splitN - varying split size"$ +-- 	quickCheck$ (\ (n::Int) -> n>0 ==> +-- 		     (\ (l::[Int]) -> concat (splitN n l) == l)) ++-- tests = TestList [test1, test2]++tests = TestList [test1]
Intel/shared_5_6.hs view
@@ -2,7 +2,7 @@ -- Pieces that are common to version 5 and 6 ------------------------------------------------------------ -type TagCol a   = (IORef (Set a), IORef [Step a])+type TagCol a   = (IORef (Set.Set a), IORef [Step a]) type ItemCol a b = MutableMap a b  -- Here the hidden state keeps track of a pointer to the work-sharing@@ -17,7 +17,7 @@ --   (2) the number of workers for this graph --   (3) the "make worker" function to spawn new threads --   (4) the set of "mortal threads"-newtype HiddenState5 = HiddenState5 (HotVar [StepCode ()], HotVar Int, IO (), HotVar (Set ThreadId))+newtype HiddenState5 = HiddenState5 (HotVar [StepCode ()], HotVar Int, IO (), HotVar (Set.Set ThreadId))   deriving Show  instance Show (IORef a) where @@ -83,11 +83,10 @@ --ver5_6_core_finalize :: Chan a -> IO b -> IO () -> StepCode b ver5_6_core_finalize :: Chan a -> StepCode b -> StepCode () -> GraphCode b ver5_6_core_finalize joiner finalAction worker = -    do (HiddenState5 (stack, numworkers, _, _)) <- S.get-       --state <- S.get +    do (HiddenState5 (stack, numworkers, _, mortal)) <- S.get        --GRAPHLIFT writeIORef global_makeworker makeworker        let mkwrkr = do S.runStateT worker state2; return ()-           state2 = HiddenState5 (stack, numworkers, mkwrkr, undefined)+           state2 = HiddenState5 (stack, numworkers, mkwrkr, mortal)         GRAPHLIFT atomicModifyIORef numworkers (\n -> (n + numCapabilities, ()))        -- Fork one worker per thread:@@ -122,5 +121,5 @@     do hv  <- newHotVar []        hv2 <- newHotVar 0        hv3 <- newHotVar Set.empty-       (a,_) <- S.runStateT x (HiddenState5 (hv,hv2, undefined, hv3))+       (a,_) <- S.runStateT x (HiddenState5 (hv,hv2, error "Intel.Cnc6 internal error: makeworker thunk used before initalized", hv3))        return a
Makefile view
@@ -5,6 +5,7 @@ default:          # This target builds CnC as precompiled modules:         # Pick default schedulers as well:+	ghc --make -c -cpp                   Intel/CncUtil.hs 	ghc --make -c -cpp -DCNC_SCHEDULER=2 Intel/CncPure.hs 	ghc --make -c -cpp -DCNC_SCHEDULER=5 Intel/Cnc.hs @@ -24,7 +25,7 @@ 	THREADS=1 ./run_all_tests.sh  longtest: -	NONSTRICT=1 LONGRUN=1 THREADSETTINGS="0 1 2 3 4 8" ./run_all_tests.sh | tee all_tests.log+	NONSTRICT=1 LONGRUN=1 THREADSETTINGS="0 1 2 3 4 8" ./run_all_tests.sh &> /dev/stdout | tee all_tests.log #	LONGRUN=1 THREADSETTINGS="0 1 2 3 4 8" ./run_all_tests.sh &> /dev/stdout | tee all_tests.log  distro: pkg @@ -46,7 +47,15 @@  clean: 	rm -f Intel/*.o Intel/*.hi Intel/*~ +	rm -f *.aux little*.log  	(cd examples; $(MAKE) clean)  distclean: clean 	rm -rf distro_20*+# DO NOT DELETE: Beginning of Haskell dependencies+Intel/CncUtil.o : Intel/CncUtil.hs+Intel/Cnc3.o : Intel/Cnc3.hs+Intel/Cnc3.o : Intel/CncUtil.hi+examples/test_parfor.o : examples/test_parfor.hs+examples/test_parfor.o : Intel/Cnc3.hi+# DO NOT DELETE: End of Haskell dependencies
default_opt_settings.sh view
@@ -6,8 +6,14 @@  # -fvia-C #GHC_DEFAULT_FLAGS=" -fasm -O2"-#GHC_DEFAULT_FLAGS=" -rtsopts -O2"-GHC_DEFAULT_FLAGS=" -O2"++# For 6.13:++if [ "`ghc -V`" == "The Glorious Glasgow Haskell Compilation System, version 6.12.1" ];+then GHC_DEFAULT_FLAGS=" -O2"+#then GHC_DEFAULT_FLAGS=" "+else GHC_DEFAULT_FLAGS=" -rtsopts -O2"+fi   # Affinity is pretty much always good. GHC_DEFAULT_RTS="  -qa " 
examples/embarrassingly_par.hs view
@@ -29,7 +29,6 @@ import Debug.Trace import Control.Monad import System.Environment-import Intel.CncUtil  import qualified  Control.Monad.State.Strict as S  @@ -85,4 +84,4 @@        case args of  	   []  -> runit $ 50*1000*1000 	   [n] -> runit $ round (10 ** read n)-	   [trials, n] -> doTrials (read trials) (loop [n])+--	   [trials, n] -> doTrials (read trials) (loop [n])
examples/fib.hs view
@@ -20,11 +20,10 @@  import System.Environment import Data.Int-import Intel.CncUtil+import Control.Monad  #include "haskell_cnc.h" - run n = runGraph $          do tags  :: TagCol  Int       <- newTagCol 	  items :: ItemCol Int Int64 <- newItemCol@@ -35,8 +34,8 @@ 	  initialize $  	     do put items 0 0 		 		put items 1 1 -		for_ 2 (n+1) (putt tags)-		--forM_ [2..n] (putt tags)+		--for_ 2 (n+1) (putt tags)+		forM_ [2..n] (putt tags) 		--forM_ (reverse [2..n]) (putt tags)  	  finalize $  	     do get items n
examples/mandel.hs view
@@ -19,9 +19,11 @@ -- Author: Ryan Newton   import Data.Complex-import Data.Word+import Data.Int import System.Environment+import Control.Monad +-- #define USE_GMAP -- #define MEMOIZE #include <haskell_cnc.h> @@ -34,7 +36,8 @@     | fn(z) >= 2.0   = count      | otherwise      = loop (i+1) (z*z + c) (count+1) -type Pair = (Word16, Word16)+-- A pair will fit in a word:+type Pair = (Int16, Int16)  mandelProg :: Int -> Int -> Int -> GraphCode Int mandelProg max_row max_col max_depth = @@ -48,33 +51,32 @@         prescribe position mandelStep  ---        gcPrintWorld "1"+        initialize $ -        for_ 0 max_row $ \i -> -         for_ 0 max_col $ \j ->+        forM_ [0..max_row] $ \i -> +         forM_ [0..max_col] $ \j ->           let (_i,_j) = (fromIntegral i, fromIntegral j) 	      z = (r_scale * (fromIntegral j) + r_origin) :+    		  (c_scale * (fromIntegral i) + c_origin) in 	  do put dat (_i,_j) z 	     putt position (_i,_j)---        gcPrintWorld "2"         -- Final result, count coordinates of the  pixels with a certain value:        finalize $ -	foldRange 0 max_row (return 0) $ \acc i -> -	 foldRange 0 max_col acc $ \acc j -> -	   do cnt <- acc-	      p <- get pixel (fromIntegral i, fromIntegral j)-	      if p == max_depth-   	       then return (cnt + (i*max_col + j))-   	       else return cnt+	foldM (\acc i -> +          foldM (\acc j -> +	           do p <- get pixel (fromIntegral i, fromIntegral j)+		      if p == max_depth+   		       then return (acc + (i*max_col + j))+   		       else return acc)+	        acc [0..max_col]+              ) 0 [0..max_row]             where      r_origin = -2                            :: Double     r_scale  = 4.0 / (fromIntegral max_row)  :: Double     c_origin = -2.0                          :: Double     c_scale = 4.0 / (fromIntegral max_col)   :: Double-   runMandel a b c = 
+ examples/mandel_opt.hs view
@@ -0,0 +1,110 @@+-- Author: Ryan Newton ++-- In this version we flatten our (x,y) positions into a single integer.+-- To that end, we FIX the grid size statically to 300x300.+++-- In this improved version, we look at three different optimizations.+--   First: enable GMaps and pack +--   Second: use cncFor to structure the spewing of the inital workload.+--   Third: do the work *inside* a cncFor and thereby drastically reduce the step count.++-- Set the environment variable MANDELOPT to {1,2,3} to add each of these optimizations.++import Data.Complex+import Data.Word+import System.Environment+import Control.Monad+import Data.Bits++-- #define MEMOIZE+#define USE_GMAP+#include <haskell_cnc.h>++-- Here we manually pack our pairs into scalars.+-- In the future the ItemCol data type may do this for us auto-magically.+type Pair = (Word16, Word16)+pack   :: Pair -> Int+unpack :: Int -> Pair+pack (a,b) = shiftL (fromIntegral a) 16 + (fromIntegral b)+unpack n   = (fromIntegral$ shiftR n 16, fromIntegral$ n .&. 0xFFFF)++mandel :: Int -> Complex Double -> Int+mandel max_depth c = loop 0 0 0+  where   +   fn = magnitude+   loop i z count+    | i == max_depth = count+    | fn(z) >= 2.0   = count +    | otherwise      = loop (i+1) (z*z + c) (count+1)++mandelProg :: Int -> Int -> Int -> Int -> GraphCode Int+mandelProg optlvl max_row max_col max_depth = +    do position :: TagCol  Int                  <- newTagCol+       dat      :: ItemCol Int (Complex Double) <- newItemCol+       pixel    :: ItemCol Int Int              <- newItemCol+       +       let mandelStep tag = +	    do cplx <- get dat tag+	       put pixel tag (mandel max_depth cplx)++       prescribe position mandelStep ++       let packit i j = (pack (_i,_j), z)+             where (_i,_j) = (fromIntegral i, fromIntegral j)+       	           z = (r_scale * (fromIntegral j) + r_origin) :++       		       (c_scale * (fromIntegral i) + c_origin)++       let kernel i j = do let (packed,z) = packit i j + 		       	   put  dat packed z+       	                   putt position packed++       let init1 = forM_ [0..max_row] $ \i -> +                     forM_ [0..max_col] $ \j ->+  	               kernel i j ++       -- This version uses cncFor to structure the work spawning.+       let init2 = +                 do stepPutStr "mandel_opt: Using cncFor implementation...\n"+                    cncFor2D (0,0) (max_row, max_col)  $ \ i j ->+		       kernel i j			  ++       -- This version uses cncFor to do the actual work.+       let init3 = do stepPutStr "mandel_opt: Using even better cncFor method...\n"+       		      cncFor2D (0,0) (max_row, max_col)  $ \ i j ->+			 do let (packed,z) = packit i j+       	                    put pixel packed (mandel max_depth z)++       initialize $ +        case optlvl of +	 1 -> init1+	 2 -> init2 +	 3 -> init3++       -- Final result, count coordinates of the  pixels with a certain value:+       finalize $ +	foldM (\acc i -> +          foldM (\acc j -> +	           do p <- get pixel (pack (fromIntegral i, fromIntegral j))+		      if p == max_depth+   		       then return (acc + (i*max_col + j))+   		       else return acc)+	        acc [0..max_col]+              ) 0 [0..max_row] +       +   where +    r_origin = -2                            :: Double+    r_scale  = 4.0 / (fromIntegral max_row)  :: Double+    c_origin = -2.0                          :: Double+    c_scale = 4.0 / (fromIntegral max_col)   :: Double+++runMandel optlvl a b c = +	do putStrLn$ "Running mandel with opt level: "++ show optlvl+	   let check = runGraph $ mandelProg optlvl a b c +	   putStrLn ("Mandel check " ++ show check)++main = do args <- getArgs  +	  case args of+	   []         -> runMandel 1 3 3 3   -- Should output 24.+	   [o, a,b,c] -> runMandel (read o) (read a) (read b) (read c)
examples/nbody.hs view
@@ -31,7 +31,6 @@    import System.Environment import Data.Int-import Intel.CncUtil import Data.List  #include "haskell_cnc.h"
haskell-cnc.cabal view
@@ -1,5 +1,5 @@ Name:           haskell-cnc-Version:        0.1.2+Version:        0.1.3 License: LGPL License-file:   LICENSE Stability: Beta@@ -13,19 +13,27 @@  stream-processing but in which nodes in the computation graph share data in tables.  Category: system, concurrent-Cabal-Version: >=1.2.3+Cabal-Version: >=1.6  build-type: Simple +source-repository head+  type:     darcs+  location: http://darcs.haskell.org/haskell-cnc/++--Data-Files: ntimes ntimes_minmedmax README.txt haskell_cnc.h Makefile install_environment_vars.sh + library-  build-depends:  base, mtl, containers, time, random, array, ghc-prim, extensible-exceptions, HUnit, QuickCheck+  build-depends:  base, mtl, containers, time, random, array, ghc-prim, extensible-exceptions, HUnit, MissingH, HSH+  -- QuickCheck -- I haven't got quickcheck working under 6.13.xx right now.   -- Needed for the scaling.hs plotting script:   --   HSH, gnuplot   -- , judy>=0.2.2 -  exposed-modules:  Intel.Cnc Intel.CncPure Intel.CncUtil+  exposed-modules:  Intel.Cnc Intel.CncPure  	            -- Various alternative schedulers:                     Intel.Cnc3 Intel.Cnc5 Intel.Cnc6 Intel.Cnc8+  other-modules: Intel.CncUtil   extensions: CPP,         -- These extensions are needed for Cnc.hs        FlexibleInstances, BangPatterns, MagicHash, ScopedTypeVariables, DeriveDataTypeable, MultiParamTypeClasses,@@ -37,13 +45,13 @@ -- -Wall    -- Unfortunately these go in the include/ subdirectory once cabal installs the package.   install-includes: ntimes ntimes_minmedmax README.txt haskell_cnc.h Makefile install_environment_vars.sh -                    default_opt_settings.sh runcnc run_all_examples.sh scaling.hs -                    examples/hello_world.hs examples/mandel.hs examples/primes.hs examples/primes2.hs +                    default_opt_settings.sh runcnc run_all_examples.sh scaling.hs timeout.hs+                    examples/hello_world.hs examples/mandel.hs examples/mandel_opt.hs examples/primes.hs examples/primes2.hs                      examples/sched_tree.hs examples/threadring_onestep.hs examples/threadring.hs                      examples/embarrassingly_par.hs examples/fib.hs examples/nbody.hs                     Intel/Cnc.Header.hs Intel/shared_5_6.hs -		    --Intel/CncUtil.hs-                    --Intel/Cnc.hs Intel/CncPure.hs Intel/Cnc3.hs Intel/Cnc5.hs Intel/Cnc6.hs Intel/Cnc8.hs+                    Intel/CncUtil.hs+                    Intel/Cnc.hs Intel/CncPure.hs Intel/Cnc3.hs Intel/Cnc5.hs Intel/Cnc6.hs Intel/Cnc8.hs    -- This seems to be completly ignored by cabal currently:   -- Test testit@@ -57,4 +65,3 @@   extensions: CPP   GHC-Options: -O2 -threaded  --  cpp-options: -DUSE_GMAP--- Intel.CncUtil
haskell_cnc.h view
@@ -24,7 +24,7 @@ #warning "Loading CNC as a separately compiled module"  -- This is here to test the efficiency of the normal module include method: import Intel.Cnc-import Intel.CncUtil+-- import Intel.CncUtil  #undef INCLUDEMETHOD 
ntimes view
@@ -80,7 +80,9 @@  # [2009.12.17] I need to get a good cross-platform process time-out system:     if [ -e ./timeout ];-    then TIMEOUTRUN="./timeout -t $TIMEOUT"+    # [2010.06.03] --RTS is a hack for working around a problem with +RTS flags:+    then TIMEOUTRUN="./timeout $TIMEOUT --RTS "+    #then TIMEOUTRUN="./timeout -t $TIMEOUT"     else TIMEOUTRUN=     fi 
runAllTests.hs view
@@ -3,12 +3,13 @@ import qualified Intel.Cnc import qualified Intel.CncPure import qualified Intel.CncUtil- import System.Cmd(system)  import System.Exit +import HSH import Test.HUnit +import Data.String.Utils -- from MissingH package  main = do  	  cd <- getCurrentDirectory@@ -38,11 +39,19 @@ 	  putStrLn$ "Finally running system tests in all configurations (example programs):" 	  putStrLn$ "================================================================================\n" -          b <- doesFileExist "run_all_examples.sh"-          if not b-           then error$ "Uh oh, the script run_all_examples.sh doesn't exist in this directory.\n"++-		       "  If cabal installed the package you may find it in your ~/.cabal/lib directory."-	   else return ()   +          b1 <- doesFileExist "run_all_examples.sh"+          if b1+           then putStrLn "!!! run_all_examples.sh found in current directory, using that!\n\n"+           else do [ver] <- run "ghc-pkg latest haskell-cnc"+                   dir <- run$ ("ghc-pkg field "++ver++" include-dirs ") -|- replace "include-dirs:" ""+                   putStrLn$ "Switching to directory: " ++ show (strip dir)+                   setCurrentDirectory (strip dir)+	   +                   b2 <- doesFileExist "run_all_examples.sh"+                   if not b2+                    then error$ "Uh oh, the script run_all_examples.sh doesn't exist in this directory.\n"+    -- 		             "  If cabal installed the package you may find it in your ~/.cabal/lib directory."+    	            else return ()               -- I have problems with cabal sdist not preserving executable flags.           system "chmod +x ./runcnc" 
run_all_examples.sh view
@@ -41,14 +41,18 @@  #export GHC=ghc-6.13.20100511  #export GHC=~/bin/Linux-i686/bin/ghc-6.13.20100511+unset HASKELLCNC +   # Which subset of schedures should we test: PURESCHEDS="2"-#IOSCHEDS="8 6 5 3"-IOSCHEDS="3 5 8"-#IOSCHEDS="3 5 6 8"+#IOSCHEDS="3"+IOSCHEDS="3 5 6 8" -#THREADSETTINGS="0 1 2 3 4 7 8"+if [ "$THREADSETTINGS" == "" ] +then THREADSETTINGS="4"+#then THREADSETTINGS="0 1 2 3 4"+fi  source default_opt_settings.sh @@ -62,7 +66,7 @@  # How many times to run a process before taking the best time: if [ "$TRIALS" == "" ]; then -  TRIALS=5+  TRIALS=1 fi  # Determine number of hardware threads on the machine:@@ -85,6 +89,9 @@ # ================================================================================ echo "# TestName Variant Scheduler NumThreads HashHackEnabled 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_DEFAULT_FLAGS" >> $RESULTS echo "#  ... with default runtime options: $GHC_DEFAULT_RTS" >> $RESULTS@@ -131,7 +138,7 @@   CODE=$?   check_error $CODE "ERROR: compilation failed." -  echo "Executing ./examples/$test.exe $ARGS +RTS $RTS "+  echo "Executing ./ntimes_minmedmax "$TRIALS" ./examples/$test.exe $ARGS +RTS $RTS -RTS "   if [ "$LONGRUN" == "" ]; then export HIDEOUTPUT=1; fi   times=`./ntimes_minmedmax "$TRIALS" ./examples/$test.exe $ARGS +RTS $RTS -RTS`   CODE=$?@@ -151,11 +158,24 @@ echo "Running all tests, for THREADSETTINGS in {$THREADSETTINGS}" echo +# Build the timeout script if it hasn't been already:+if ! [ -e ./timeout ]; then +  ghc --make timeout.hs -threaded+  if [ "$?" != "0" ];+  then echo "GHC build of timeout.hs returned error."+       exit 1+  fi+fi++# Hygiene:+rm -f examples/*.exe+ # This specifies the list of tests and their arguments for a "long" run:-for line in "embarrassingly_par 9.2" "threadring 50000000 503" "sched_tree 18" "mandel 300 300 4000" "primes2 200000" "fib 20000"; do-#for line in "mandel 300 300 4000" "primes2 200000" ; do-#for line in "fib 20000"  "nbody 2000" ; do +#for line in "mandel_opt 1 300 300 4000" "mandel_opt 2 300 300 4000" "mandel_opt 3 300 300 4000" "mandel 300 300 4000"; do++for line in "embarrassingly_par 9.2" "threadring 50000000 503" "sched_tree 18" "primes2 200000" "fib 20000" "mandel 300 300 4000" "mandel_opt 1 300 300 4000"; do+   set -- $line   test=$1; shift @@ -170,6 +190,8 @@   echo "                           Running Test: $test.exe $ARGS                        "   echo "================================================================================" +  echo "# *** Config [$cnt ..], testing with command/args: $test.exe $ARGS " >> $RESULTS+  export CNC_VARIANT=pure  # Currently running the pure scheduler only in single threaded mode:  export NUMTHREADS=0@@ -197,8 +219,8 @@  # Finally, run once through separately compiled modules to compare performance (and make sure they build).  # This will basically use the IO based implementation with the default scheduler.  export CNC_VARIANT=separatemodule_io- export CNC_SCHEDULER=8- export NUMTHREADS=$MAXTHREADS+ export CNC_SCHEDULER=6+ export NUMTHREADS=4  runit   echo >> $RESULTS;
runcnc view
@@ -58,7 +58,7 @@ #EXTENSIONS="-fglasgow-exts" # -feager-blackholing TEMPEXT="-XFlexibleContexts -XTypeSynonymInstances"-EXTENSIONS=" -XExistentialQuantification -XScopedTypeVariables -XBangPatterns -XNamedFieldPuns -XRecordWildCards -XFlexibleInstances -XDeriveDataTypeable $TEMPEXT"+EXTENSIONS=" -XExistentialQuantification -XScopedTypeVariables -XBangPatterns -XNamedFieldPuns -XRecordWildCards -XFlexibleInstances -XDeriveDataTypeable -XTypeFamilies -XUndecidableInstances -XOverlappingInstances -XMultiParamTypeClasses $TEMPEXT" # MagicHash   # If the user has not set $HASKELLCNC we try the current directory.
+ timeout.hs view
@@ -0,0 +1,49 @@+#!/usr/bin/env runhaskell++import Data.List+import Data.IORef+import System.Exit+import System.Process+import System.Environment+import System.Posix.Unistd++import Control.Concurrent++polltime = 2 -- in seconds++main = +    do args <- getArgs +       -- A flag for completion:+       ref <- newIORef False+       case args of +        time:rest -> +	    let timeout = read time +		cmd = concat $ intersperse " " rest+            in+	    do putStrLn$ "++ Running command with timeout = "++ show timeout ++" seconds:\n  " ++ cmd+	       pid <- runCommand  cmd++               sync <- newEmptyMVar++	       let loop acc = +		    if acc > (timeout :: Int)+		    then do putStrLn$ "\nERROR: TIMED OUT!"+	 		    exitWith (ExitFailure 88)+	 	    else do sleep polltime+			    x <- getProcessExitCode pid+			    case x of +	                      Nothing -> do putStrLn$ "++ Polling, approximately "++ +						      show (acc+polltime) ++" seconds have elapsed..."+				            loop (acc+polltime)+			      Just code -> putMVar sync code+	       let poll_thread = loop 0+	       let wait_thread = +                        do waitForProcess pid+			   writeIORef ref True+			   putStrLn "++ Command completed without timing out."+			   putMVar sync ExitSuccess+	       forkIO wait_thread+	       forkIO poll_thread+	       final <- readMVar sync+	       exitWith final+