{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS_HADDOCK hide #-}
module Control.Parallel.Meta.Resource.Backoff (
mkResource,
defaultWorkSearch, mkWorkSearch,
) where
import Control.Concurrent
import Text.Printf
import Control.Parallel.Meta
import Control.Parallel.Meta.Worker
import Data.Primitive.MutVar
import Data.Range as R
import qualified Data.Vector as V
import qualified Data.Array.Accelerate.Debug as Debug
{-# INLINE mkResource #-}
mkResource :: Resource
mkResource = Resource defaultWorkSearch
{-# INLINE defaultWorkSearch #-}
defaultWorkSearch :: WorkSearch
defaultWorkSearch = mkWorkSearch 100 10000
{-# INLINE mkWorkSearch #-}
mkWorkSearch :: Int -> Int -> WorkSearch
mkWorkSearch _ 0 = WorkSearch $ \_ _ -> return Nothing
mkWorkSearch shortest longest = WorkSearch backoff
where
backoff :: Int -> Workers -> IO (Maybe Range)
backoff tid workers = do
let Worker{..} = V.unsafeIndex workers tid
failed <- readMutVar consecutiveFailures
let sleep = min longest (2 ^ failed)
if sleep >= shortest
then do
message workerId (printf "sleeping for %d µs" sleep)
threadDelay sleep
else do
message workerId "not sleeping"
return ()
return Nothing
{-# INLINE message #-}
message :: Int -> String -> IO ()
message tid msg
= Debug.when Debug.verbose
$ Debug.traceIO Debug.dump_sched (printf "sched/backoff: [%d] %s" tid msg)