accelerate-cuda-0.17.0.0: Data/Array/Accelerate/CUDA/Debug.hs
{-# LANGUAGE CPP #-}
{-# OPTIONS -fno-warn-unused-binds #-}
{-# OPTIONS -fno-warn-unused-imports #-}
-- |
-- Module : Data.Array.Accelerate.CUDA.Debug
-- Copyright : [2008..2014] Manuel M T Chakravarty, Gabriele Keller
-- [2009..2014] Trevor L. McDonell
-- License : BSD3
--
-- Maintainer : Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>
-- Stability : experimental
-- Portability : non-portable (GHC extensions)
--
-- Hijack some command line arguments to pass runtime debugging options. This
-- might cause problems for users of the library...
--
module Data.Array.Accelerate.CUDA.Debug (
module Data.Array.Accelerate.Debug,
module Data.Array.Accelerate.CUDA.Debug,
) where
import Data.Array.Accelerate.Debug hiding ( timed, elapsed )
import Control.Concurrent ( forkIO )
import Control.Monad ( void )
import Control.Monad.IO.Class ( liftIO, MonadIO )
import GHC.Float ( float2Double )
import System.CPUTime
import System.IO.Unsafe
import Foreign.CUDA.Driver.Stream ( Stream )
import qualified Foreign.CUDA.Driver.Event as Event
-- | Execute an action and time the results. The second argument specifies how
-- to format the output string given elapsed GPU and CPU time respectively
--
timed :: Mode -> (Double -> Double -> String) -> Maybe Stream -> IO () -> IO ()
#ifdef ACCELERATE_DEBUG
{-# NOINLINE timed #-}
timed f fmt stream action = do
enabled <- queryFlag f
if enabled
then do
gpuBegin <- Event.create []
gpuEnd <- Event.create []
cpuBegin <- getCPUTime
Event.record gpuBegin stream
action
Event.record gpuEnd stream
cpuEnd <- getCPUTime
-- Wait for the GPU to finish executing then display the timing execution
-- message. Do this in a separate thread so that the remaining kernels can
-- be queued asynchronously.
--
void . forkIO $ do
Event.block gpuEnd
diff <- Event.elapsedTime gpuBegin gpuEnd
let gpuTime = float2Double $ diff * 1E-3 -- milliseconds
cpuTime = fromIntegral (cpuEnd - cpuBegin) * 1E-12 :: Double -- picoseconds
Event.destroy gpuBegin
Event.destroy gpuEnd
--
traceIO f (fmt gpuTime cpuTime)
else
action
#else
{-# INLINE timed #-}
timed _ _ _ action = action
#endif
{-# INLINE elapsed #-}
elapsed :: Double -> Double -> String
elapsed gpuTime cpuTime
= "gpu: " ++ showFFloatSIBase (Just 3) 1000 gpuTime "s, " ++
"cpu: " ++ showFFloatSIBase (Just 3) 1000 cpuTime "s"