cuda 0.8.0.1 → 0.9.0.0
raw patch · 10 files changed
+248/−25 lines, 10 files
Files
- CHANGELOG.markdown +12/−0
- cuda.cabal +2/−3
- examples/src/deviceQueryDrv/DeviceQuery.hs +2/−1
- src/Foreign/CUDA/Driver/Context/Peer.chs +44/−2
- src/Foreign/CUDA/Driver/Exec.chs +74/−0
- src/Foreign/CUDA/Driver/Module/Base.chs +2/−0
- src/Foreign/CUDA/Driver/Stream.chs +78/−15
- src/Foreign/CUDA/Driver/Utils.chs +10/−0
- src/Foreign/CUDA/Runtime/Utils.chs +10/−0
- src/Foreign/CUDA/Types.chs +14/−4
CHANGELOG.markdown view
@@ -4,6 +4,17 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/). +## [0.9.0.0] - 2017-11-15+### Fixed+ * Build fixes for CUDA-9++### Added+ * `Peer.getAttribute`+ * `Exec.launchKernelCooperative`++### Changed+ * Changed type of `Stream.wait` and `Stream.write` to support 64-bit values+ ## [0.8.0.1] - 2017-10-24 ### Fixed * [#50] Escape backslashes used in -D flags on Windows@@ -92,6 +103,7 @@ * Add functions from CUDA-6.5 +[0.9.0.0]: https://github.com/tmcdonell/cuda/compare/0.8.0.1...0.9.0.0 [0.8.0.1]: https://github.com/tmcdonell/cuda/compare/0.8.0.0...0.8.0.1 [0.8.0.0]: https://github.com/tmcdonell/cuda/compare/0.7.5.3...0.8.0.0 [0.7.5.3]: https://github.com/tmcdonell/cuda/compare/0.7.5.2...0.7.5.3
cuda.cabal view
@@ -1,5 +1,5 @@ Name: cuda-Version: 0.8.0.1+Version: 0.9.0.0 Synopsis: FFI binding to the CUDA interface for programming NVIDIA GPUs Description: The CUDA library provides a direct, general purpose C-like SPMD programming@@ -181,7 +181,6 @@ source-repository this type: git location: https://github.com/tmcdonell/cuda- tag: 0.8.0.1+ tag: 0.9.0.0 -- vim: nospell-
examples/src/deviceQueryDrv/DeviceQuery.hs view
@@ -13,9 +13,10 @@ main :: IO () main = do- version <- CUDA.driverVersion+ version <- CUDA.driverVersion printf "CUDA device query (Driver API, statically linked)\n" printf "CUDA driver version %d.%d\n" (version`div`1000) ((version`mod`100)`div`10)+ printf "CUDA API version %d.%d\n" (CUDA.libraryVersion`div`1000) ((CUDA.libraryVersion`mod`100)`div`10) CUDA.initialise [] numDevices <- CUDA.count
src/Foreign/CUDA/Driver/Context/Peer.chs view
@@ -21,8 +21,8 @@ module Foreign.CUDA.Driver.Context.Peer ( -- * Peer Access- PeerFlag,- accessible, add, remove,+ PeerFlag, PeerAttribute(..),+ accessible, add, remove, getAttribute, ) where @@ -55,6 +55,22 @@ #endif +-- | Peer-to-peer attributes+--+#if CUDA_VERSION < 8000+data PeerAttribute+instance Enum PeerAttribute where+#ifdef USE_EMPTY_CASE+ toEnum x = case x of {}+ fromEnum x = case x of {}+#endif+#else+{# enum CUdevice_P2PAttribute as PeerAttribute+ { underscoreToCase }+ with prefix="CU_DEVICE_P2P_ATTRIBUTE" deriving (Eq, Show) #}+#endif++ -------------------------------------------------------------------------------- -- Peer access --------------------------------------------------------------------------------@@ -127,5 +143,31 @@ {-# INLINE cuCtxDisablePeerAccess #-} {# fun unsafe cuCtxDisablePeerAccess { useContext `Context' } -> `Status' cToEnum #}+#endif+++-- |+-- Queries attributes of the link between two devices+--+-- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__PEER__ACCESS.html#group__CUDA__PEER__ACCESS_1g4c55c60508f8eba4546b51f2ee545393>+--+-- Requires CUDA-8.0+--+-- @since 0.9.0.0@+--+{-# INLINEABLE getAttribute #-}+getAttribute :: PeerAttribute -> Device -> Device -> IO Int+#if CUDA_VERSION < 8000+getAttribute _ _ _ = requireSDK 'getAttribute 8.0+#else+getAttribute attrib src dst = resultIfOk =<< cuDeviceGetP2PAttribute attrib src dst++{-# INLINE cuDeviceGetP2PAttribute #-}+{# fun unsafe cuDeviceGetP2PAttribute+ { alloca- `Int' peekIntConv*+ , cFromEnum `PeerAttribute'+ , useDevice `Device'+ , useDevice `Device'+ } -> `Status' cToEnum #} #endif
src/Foreign/CUDA/Driver/Exec.chs view
@@ -22,6 +22,7 @@ setCacheConfigFun, setSharedMemConfigFun, launchKernel, launchKernel',+ launchKernelCooperative, -- Deprecated since CUDA-4.0 setBlockShape, setSharedSize, setParams, launch,@@ -279,6 +280,79 @@ launchKernel' = launchKernel #endif ++-- |+-- Invoke a kernel on a @(gx * gy * gz)@ grid of blocks, where each block+-- contains @(tx * ty * tz)@ threads and has access to a given number of bytes+-- of shared memory. The launch may also be associated with a specific stream.+--+-- The thread blocks can cooperate and synchronise as they execute.+--+-- The device on which this kernel is invoked must have+-- 'Foreign.CUDA.Driver.Device.attribute'+-- 'Foreign.CUDA.Driver.Device.CooperativeLaunch'.+--+-- The total number of blocks launched can not exceed the maximum number of+-- active thread blocks per multiprocessor+-- ('Foreign.CUDA.Analysis.Device.threadBlocksPerMP'), multiplied by the number+-- of multiprocessors ('Foreign.CUDA.Analysis.Device.multiProcessorCount').+--+-- The kernel can not make use of dynamic parallelism.+--+-- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__EXEC.html#group__CUDA__EXEC_1g06d753134145c4584c0c62525c1894cb>+--+-- Requires CUDA-9.0+--+-- @since 0.9.0.0@+--+{-# INLINEABLE launchKernelCooperative #-}+launchKernelCooperative+ :: Fun -- ^ function to execute+ -> (Int,Int,Int) -- ^ block grid dimension+ -> (Int,Int,Int) -- ^ thread block shape+ -> Int -- ^ shared memory (bytes)+ -> Maybe Stream -- ^ (optional) stream to execute in+ -> [FunParam] -- ^ list of function parameters+ -> IO ()+#if CUDA_VERSION < 9000+launchKernelCooperative _ _ _ _ _ _ = requireSDK 'launchKernelCooperative 9.0+#else+launchKernelCooperative !fn (!gx,!gy,!gz) (!tx,!ty,!tz) !sm !mst !args+ = (=<<) nothingIfOk+ $ withMany withFP args+ $ \pa -> withArray pa+ $ \pp -> cuLaunchCooperativeKernel fn gx gy gz tx ty tz sm st pp+ where+ !st = fromMaybe defaultStream mst++ withFP :: FunParam -> (Ptr FunParam -> IO b) -> IO b+ withFP !p !f = case p of+ IArg v -> with' v (f . castPtr)+ FArg v -> with' v (f . castPtr)+ VArg v -> with' v (f . castPtr)++ -- can't use the standard 'with' because 'alloca' will pass an undefined+ -- dummy argument when determining 'sizeOf' and 'alignment', but sometimes+ -- instances in Accelerate need to evaluate this argument.+ --+ with' :: Storable a => a -> (Ptr a -> IO b) -> IO b+ with' !val !f =+ allocaBytes (sizeOf val) $ \ptr -> do+ poke ptr val+ f ptr++{-# INLINE cuLaunchCooperativeKernel #-}+{# fun unsafe cuLaunchCooperativeKernel+ { useFun `Fun'+ , `Int', `Int', `Int'+ , `Int', `Int', `Int'+ , `Int'+ , useStream `Stream'+ , castPtr `Ptr (Ptr FunParam)'+ } -> `Status' cToEnum #}+#endif++-- TODO: cuLaunchCooperativeKernelMultiDevice introduced CUDA-9.0 -------------------------------------------------------------------------------- -- Deprecated
src/Foreign/CUDA/Driver/Module/Base.chs view
@@ -278,10 +278,12 @@ {-# INLINE jitTargetOfCompute #-} jitTargetOfCompute :: Compute -> JITTarget+#if CUDA_VERSION < 9000 jitTargetOfCompute (Compute 1 0) = Compute10 jitTargetOfCompute (Compute 1 1) = Compute11 jitTargetOfCompute (Compute 1 2) = Compute12 jitTargetOfCompute (Compute 1 3) = Compute13+#endif jitTargetOfCompute (Compute 2 0) = Compute20 jitTargetOfCompute (Compute 2 1) = Compute21 #if CUDA_VERSION >= 5000
src/Foreign/CUDA/Driver/Stream.chs view
@@ -15,7 +15,7 @@ module Foreign.CUDA.Driver.Stream ( -- * Stream Management- Stream(..), StreamFlag, StreamWriteFlag(..), StreamWaitFlag(..),+ Stream(..), StreamFlag(..), StreamWriteFlag(..), StreamWaitFlag(..), create, createWithPriority, destroy, finished, block, getPriority, write, wait, @@ -27,15 +27,17 @@ {# context lib="cuda" #} -- Friends+import Foreign.CUDA.Ptr import Foreign.CUDA.Types import Foreign.CUDA.Driver.Error import Foreign.CUDA.Internal.C2HS -- System+import Control.Exception ( throwIO )+import Control.Monad ( liftM ) import Foreign import Foreign.C-import Control.Monad ( liftM )-import Control.Exception ( throwIO )+import Unsafe.Coerce --------------------------------------------------------------------------------@@ -187,20 +189,32 @@ -- -- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__EVENT.html#group__CUDA__EVENT_1g091455366d56dc2f1f69726aafa369b0> ----- Requires CUDA-8.0.+-- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__EVENT.html#group__CUDA__EVENT_1gc8af1e8b96d7561840affd5217dd6830> --+-- Requires CUDA-8.0 for 32-bit values.+--+-- Requires CUDA-9.0 for 64-bit values.+-- {-# INLINEABLE write #-}-write :: DevicePtr Int32 -> Int32 -> Stream -> [StreamWriteFlag] -> IO ()+write :: Storable a => DevicePtr a -> a -> Stream -> [StreamWriteFlag] -> IO ()+write ptr val stream flags =+ case sizeOf val of+ 4 -> write32 (castDevPtr ptr) (unsafeCoerce val) stream flags+ 8 -> write64 (castDevPtr ptr) (unsafeCoerce val) stream flags+ _ -> cudaError "Stream.write: can only write 32- and 64-bit values"++{-# INLINE write32 #-}+write32 :: DevicePtr Word32 -> Word32 -> Stream -> [StreamWriteFlag] -> IO () #if CUDA_VERSION < 8000-write _ _ _ _ = requireSDK 'write 8.0+write32 _ _ _ _ = requireSDK 'write32 8.0 #else-write ptr val stream flags = nothingIfOk =<< cuStreamWriteValue32 stream ptr val flags+write32 ptr val stream flags = nothingIfOk =<< cuStreamWriteValue32 stream ptr val flags {-# INLINE cuStreamWriteValue32 #-} {# fun unsafe cuStreamWriteValue32 { useStream `Stream'- , useDeviceHandle `DevicePtr Int32'- , `Int32'+ , useDeviceHandle `DevicePtr Word32'+ , `Word32' , combineBitMasks `[StreamWriteFlag]' } -> `Status' cToEnum #}@@ -208,26 +222,75 @@ useDeviceHandle = fromIntegral . ptrToIntPtr . useDevicePtr #endif +{-# INLINE write64 #-}+write64 :: DevicePtr Word64 -> Word64 -> Stream -> [StreamWriteFlag] -> IO ()+#if CUDA_VERSION < 9000+write64 _ _ _ _ = requireSDK 'write64 9.0+#else+write64 ptr val stream flags = nothingIfOk =<< cuStreamWriteValue64 stream ptr val flags +{-# INLINE cuStreamWriteValue64 #-}+{# fun unsafe cuStreamWriteValue64+ { useStream `Stream'+ , useDeviceHandle `DevicePtr Word64'+ , `Word64'+ , combineBitMasks `[StreamWriteFlag]'+ }+ -> `Status' cToEnum #}+ where+ useDeviceHandle = fromIntegral . ptrToIntPtr . useDevicePtr+#endif++ -- | Wait on a memory location. Work ordered after the operation will block -- until the given condition on the memory is satisfied. -- -- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__EVENT.html#group__CUDA__EVENT_1g629856339de7bc6606047385addbb398> ----- Requires CUDA-8.0.+-- <http://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__EVENT.html#group__CUDA__EVENT_1g6910c1258c5f15aa5d699f0fd60d6933> --+-- Requires CUDA-8.0 for 32-bit values.+--+-- Requires CUDA-9.0 for 64-bit values.+-- {-# INLINEABLE wait #-}-wait :: DevicePtr Int32 -> Int32 -> Stream -> [StreamWaitFlag] -> IO ()+wait :: Storable a => DevicePtr a -> a -> Stream -> [StreamWaitFlag] -> IO ()+wait ptr val stream flags =+ case sizeOf val of+ 4 -> wait32 (castDevPtr ptr) (unsafeCoerce val) stream flags+ 8 -> wait64 (castDevPtr ptr) (unsafeCoerce val) stream flags+ _ -> cudaError "Stream.wait: can only wait on 32- and 64-bit values"++{-# INLINE wait32 #-}+wait32 :: DevicePtr Word32 -> Word32 -> Stream -> [StreamWaitFlag] -> IO () #if CUDA_VERSION < 8000-wait _ _ _ _ = requireSDK 'wait 8.0+wait32 _ _ _ _ = requireSDK 'wait32 8.0 #else-wait ptr val stream flags = nothingIfOk =<< cuStreamWaitValue32 stream ptr val flags+wait32 ptr val stream flags = nothingIfOk =<< cuStreamWaitValue32 stream ptr val flags {-# INLINE cuStreamWaitValue32 #-} {# fun unsafe cuStreamWaitValue32 { useStream `Stream'- , useDeviceHandle `DevicePtr Int32'- , `Int32'+ , useDeviceHandle `DevicePtr Word32'+ , `Word32'+ , combineBitMasks `[StreamWaitFlag]'+ } -> `Status' cToEnum #}+ where+ useDeviceHandle = fromIntegral . ptrToIntPtr . useDevicePtr+#endif++{-# INLINE wait64 #-}+wait64 :: DevicePtr Word64 -> Word64 -> Stream -> [StreamWaitFlag] -> IO ()+#if CUDA_VERSION < 9000+wait64 _ _ _ _ = requireSDK 'wait64 9.0+#else+wait64 ptr val stream flags = nothingIfOk =<< cuStreamWaitValue64 stream ptr val flags++{-# INLINE cuStreamWaitValue64 #-}+{# fun unsafe cuStreamWaitValue64+ { useStream `Stream'+ , useDeviceHandle `DevicePtr Word64'+ , `Word64' , combineBitMasks `[StreamWaitFlag]' } -> `Status' cToEnum #} where
src/Foreign/CUDA/Driver/Utils.chs view
@@ -12,6 +12,7 @@ module Foreign.CUDA.Driver.Utils ( driverVersion,+ libraryVersion, ) where @@ -37,4 +38,13 @@ {-# INLINE cuDriverGetVersion #-} {# fun unsafe cuDriverGetVersion { alloca- `Int' peekIntConv* } -> `Status' cToEnum #}+++-- |+-- Return the version number of the CUDA library (API) that this package was+-- compiled against.+--+{-# INLINEABLE libraryVersion #-}+libraryVersion :: Int+libraryVersion = {#const CUDA_VERSION #}
src/Foreign/CUDA/Runtime/Utils.chs view
@@ -13,6 +13,7 @@ runtimeVersion, driverVersion,+ libraryVersion, ) where @@ -50,4 +51,13 @@ {-# INLINE cudaDriverGetVersion #-} {# fun unsafe cudaDriverGetVersion { alloca- `Int' peekIntConv* } -> `Status' cToEnum #}+++-- |+-- Return the version number of the CUDA library (API) that this package was+-- compiled against.+--+{-# INLINEABLE libraryVersion #-}+libraryVersion :: Int+libraryVersion = {#const CUDART_VERSION #}
src/Foreign/CUDA/Types.chs view
@@ -24,7 +24,7 @@ Event(..), EventFlag(..), WaitFlag, -- * Streams- Stream(..), StreamPriority, StreamFlag,+ Stream(..), StreamFlag(..), StreamPriority, defaultStream, ) where@@ -98,7 +98,9 @@ -- Event creation flags -- {# enum CUevent_flags as EventFlag- { underscoreToCase }+ { underscoreToCase+ , CU_EVENT_DEFAULT as EventDefault+ } with prefix="CU_EVENT" deriving (Eq, Show, Bounded) #} -- |@@ -135,15 +137,23 @@ type StreamPriority = Int -- |--- Possible option flags for stream initialisation. Dummy instance until the API--- exports actual option values.+-- Execution stream creation flags --+#if CUDA_VERSION < 7500 data StreamFlag instance Enum StreamFlag where #ifdef USE_EMPTY_CASE toEnum x = case x of {} fromEnum x = case x of {} #endif+#else+{# enum CUstream_flags as StreamFlag+ { underscoreToCase+ , CU_STREAM_DEFAULT as StreamDefault+ }+ with prefix="CU_STREAM" deriving (Eq, Show, Bounded) #}+#endif+ -- | -- The main execution stream. No operations overlap with operations in the