FAI (empty) → 0.1.0.10
raw patch · 10 files changed
+769/−0 lines, 10 filesdep +FAIdep +basedep +hspecsetup-changed
Dependencies added: FAI, base, hspec, inline-c
Files
- ChangeLog.md +5/−0
- FAI.cabal +59/−0
- LICENSE +165/−0
- Setup.hs +2/−0
- src/Foreign/FAI/Platform/CUDA.hs +145/−0
- src/Foreign/FAI/Platform/Host.hs +111/−0
- src/Foreign/FAI/Types.hs +175/−0
- test/Foreign/FAI/Platform/CUDASpec.hs +52/−0
- test/Foreign/FAI/Platform/HostSpec.hs +54/−0
- test/Spec.hs +1/−0
+ ChangeLog.md view
@@ -0,0 +1,5 @@+# Revision history for FAI + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world.
+ FAI.cabal view
@@ -0,0 +1,59 @@+-- Initial FAI.cabal generated by cabal init. For further documentation, +-- see http://haskell.org/cabal/users-guide/ + +name: FAI +version: 0.1.0.10 +synopsis: Haskell Foreign Accelerate Interface +description: The haskell interface for foreign accelerate framework. +homepage: https://github.com/Qinka/HaskellFAI +license: LGPL-3 +license-file: LICENSE +author: Johann Lee +maintainer: me@qinka.pro +copyright: (C) 2018 Johann Lee <me@qinka.pro> +category: Accelerate +build-type: Simple +extra-source-files: ChangeLog.md +cabal-version: >=1.21 + +flag enable-cuda + default: True + description: Enable the Nvidia's CUDA platform. + +library + exposed-modules: Foreign.FAI.Types + , Foreign.FAI.Platform.Host + -- other-modules: + other-extensions: MultiParamTypeClasses + , GADTs + , TypeFamilies + , QuasiQuotes + , TemplateHaskell + reexported-modules: Language.C.Inline + build-depends: base >= 4 && < 5 + , inline-c >= 0.6 + hs-source-dirs: src + default-language: Haskell2010 + + if(flag(enable-cuda)) + extra-libraries: cudart + exposed-modules: Foreign.FAI.Platform.CUDA + + +test-suite spec + type: exitcode-stdio-1.0 + main-is: Spec.hs + hs-source-dirs: test + ghc-options: -Wall + build-depends: base + , FAI + , inline-c + , hspec + other-modules: Foreign.FAI.Platform.HostSpec + , Foreign.FAI.Platform.CUDASpec + other-extensions: CPP + , TypeFamilies + + default-language: Haskell2010 + if(flag(enable-cuda)) + cpp-options: -DENABLE_CUDA
+ LICENSE view
@@ -0,0 +1,165 @@+ GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple +main = defaultMain
+ src/Foreign/FAI/Platform/CUDA.hs view
@@ -0,0 +1,145 @@+{- + +Copyright (C) 2018 Johann Lee <mer@qinka.pro> + +This fiel is part of HaskellFAI + +HaskellFAI is free software: you can redistribute it and/or modify +it under the terms of the GNU Less General Public License as published by +the Free Software Foundation, either version 3 of the License, +or (at your option) any later version. + +Haskell is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warrenty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Less General Public License for more details. + +You should have received a copy of the GNU Less General Public License +along with HaskellFAI. If not, see <http://www.gnu.org/licenses/>. + +-} + +{-| +Module: Foreign.FAI.Platform.CUDA +Description: The CUDA platform instance. +Copyright: (C) 2018 Johann Lee <me@qinka.pro> +License: LGPL3 +Maintainer: me@qinka.pro +Stability: experimental +Portability: unknown + +The CUDA platform instance. +-} + +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeFamilies #-} + + +module Foreign.FAI.Platform.CUDA + ( CUDA(..) + , Pf(..) + ) where + +import Control.Monad +import Foreign.C.Types +import Foreign.FAI.Platform.Host (Host) +import Foreign.FAI.Types +import Foreign.ForeignPtr +import Foreign.Ptr +import qualified Language.C.Inline as C + +C.include "<cuda_runtime.h>" +C.include "<stdio.h>" + +data CUDA = CUDA + +type instance Pf CUDA Float = Float +type instance Pf CUDA Double = Double +type instance Pf CUDA Int = Int +type instance Pf CUDA Word = Word + +cudaMemAllocate :: CInt -> IO (Ptr a) +cudaMemAllocate n = + castPtr <$> [C.block| void* { + void * ptr = 0; + cudaError_t err = cudaMalloc((void*)&ptr, $(int n)); + if (err != cudaSuccess) { + printf("Failed to allocate memory, %d", err); + ptr = 0; + } + return ptr;}|] + +cudaMemRelease :: Ptr a -> IO () +cudaMemRelease n' = [C.exp| void { cudaFree($(void *n)) }|] + where n = castPtr n' + +cudaMemReleaseP :: IO (FinalizerPtr a) +cudaMemReleaseP = castPtrToFunPtr <$> [C.exp| void* {*cudaFree}|] + +cudaMemCopy :: (Ptr () -> Ptr () -> CInt -> IO CInt) + -> ForeignPtr a -> ForeignPtr b -> CInt -> IO () +cudaMemCopy doCopy fdst fsrc size = + withForeignPtr fdst $ \dst' -> + withForeignPtr fsrc $ \src' -> + let dst = castPtr dst' + src = castPtr src' + in do + rt <- doCopy dst src size + when (rt /= 0) $ error "Fail to copy." + +doCopyHC :: Ptr () -> Ptr () -> CInt -> IO CInt +doCopyHC dst src size = + [C.block| int { + cudaError_t err = cudaMemcpy($(void *dst), $(void *src), + $(int size), cudaMemcpyHostToDevice); + if(err != cudaSuccess) { + printf("Failed to copy memory(HC), %d", err); + return -1; + } + return 0;}|] + +doCopyCH :: Ptr () -> Ptr () -> CInt -> IO CInt +doCopyCH dst src size = + [C.block| int { + cudaError_t err = cudaMemcpy($(void *dst), $(void *src), + $(int size), cudaMemcpyDeviceToHost); + if(err != cudaSuccess) { + printf("Failed to copy memory(HC), %d", err); + return -1; + } + return 0;}|] + +doCopyCC :: Ptr () -> Ptr () -> CInt -> IO CInt +doCopyCC dst src size = + [C.block| int { + cudaError_t err = cudaMemcpy($(void *dst), $(void *src), + $(int size), cudaMemcpyDeviceToDevice); + if(err != cudaSuccess) { + printf("Failed to copy memory(HC), %d", err); + return -1; + } + return 0;}|] + + +instance FAI CUDA where + faiMemAllocate _ = cudaMemAllocate . fromIntegral + faiMemRelease _ = cudaMemRelease + faiMemReleaseP _ = Right <$> cudaMemReleaseP + +instance FAICopy Host CUDA where + faiMemCopy dst src = do + when (bufSize dst /= bufSize src) $ error "Different size." + cudaMemCopy doCopyHC (bufPtr dst) (bufPtr src) $ fromIntegral $ bufSize dst + +instance FAICopy CUDA Host where + faiMemCopy dst src = do + when (bufSize dst /= bufSize src) $ error "Different size." + cudaMemCopy doCopyCH (bufPtr dst) (bufPtr src) $ fromIntegral $ bufSize dst + +instance FAICopy CUDA CUDA where + faiMemCopy dst src = do + when (bufSize dst /= bufSize src) $ error "Different size." + cudaMemCopy doCopyCC (bufPtr dst) (bufPtr src) $ fromIntegral $ bufSize dst +
+ src/Foreign/FAI/Platform/Host.hs view
@@ -0,0 +1,111 @@+{- + +Copyright (C) 2018 Johann Lee <mer@qinka.pro> + +This fiel is part of HaskellFAI + +HaskellFAI is free software: you can redistribute it and/or modify +it under the terms of the GNU Less General Public License as published by +the Free Software Foundation, either version 3 of the License, +or (at your option) any later version. + +Haskell is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warrenty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Less General Public License for more details. + +You should have received a copy of the GNU Less General Public License +along with HaskellFAI. If not, see <http://www.gnu.org/licenses/>. + +-} + +{-| +Module: Foreign.FAI.Platform.Host +Description: The host platform instance. +Copyright: (C) 2018 Johann Lee <me@qinka.pro> +License: LGPL3 +Maintainer: me@qinka.pro +Stability: experimental +Portability: unknown + +The host platform instance. +-} + +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE QuasiQuotes #-} +{-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE TypeFamilies #-} + + +module Foreign.FAI.Platform.Host + ( Host(..) + , Pf(..) + , bufFromList + , bufToList + ) where + +import Control.Monad +import Foreign.C.Types +import Foreign.FAI.Types +import Foreign.ForeignPtr +import Foreign.Marshal.Array +import Foreign.Ptr +import Foreign.Storable +import qualified Language.C.Inline as C +import System.IO.Unsafe + +C.include "<string.h>" +C.include "<stdlib.h>" + +data Host = Host + +type instance Pf Host Float = Float +type instance Pf Host Double = Double +type instance Pf Host Int = Int +type instance Pf Host Word = Word + +hostMemAllocate :: CInt -> IO (Ptr a) +hostMemAllocate n = castPtr <$> [C.exp| void* { malloc($(int n))}|] + +hostMemRelease :: Ptr a -> IO () +hostMemRelease n' = [C.exp| void { free($(void *n)) }|] + where n = castPtr n' + +hostMemReleaseP :: IO (FinalizerPtr a) +hostMemReleaseP = castPtrToFunPtr <$> [C.exp| void* {*free}|] + +hostMemCopy :: ForeignPtr a -> ForeignPtr a -> CInt -> IO () +hostMemCopy fdst fsrc size = + withForeignPtr fdst $ \dst' -> + withForeignPtr fsrc $ \src' -> + let dst = castPtr dst' + src = castPtr src' + in void $ [C.exp| void* {memcpy($(void *dst), $(void *src), $(int size))} |] + +instance FAI Host where + faiMemAllocate _ = hostMemAllocate . fromIntegral + faiMemRelease _ = hostMemRelease + faiMemReleaseP _ = Right <$> hostMemReleaseP + +instance FAICopy Host Host where + faiMemCopy dst src = do + when (bufSize dst /= bufSize src) $ error "Different size." + hostMemCopy (bufPtr dst) (bufPtr src) $ fromIntegral $ bufSize dst + + +hostAccReturn :: a -> Accelerate Host a +hostAccReturn = return + +bufFromList :: (Storable b, Pf Host a ~ b) => [b] -> Buffer Host a +bufFromList ls = unsafePerformIO $ do + bf <- fst <$> doAccelerate (hostAccReturn () >> newBuffer (length ls)) undefined + withForeignPtr (bufPtr bf) $ \ptr -> + pokeArray ptr ls + return bf + +bufToList :: (Storable b, Pf Host a ~ b) => Buffer Host a -> [b] +bufToList bf = unsafePerformIO $ + withForeignPtr (bufPtr bf) $ \ptr -> + peekBuf undefined ptr + where peekBuf :: Storable a => a -> Ptr a -> IO [a] + peekBuf = peekArray . (bufSize bf `div`) . sizeOf
+ src/Foreign/FAI/Types.hs view
@@ -0,0 +1,175 @@+{- + +Copyright (C) 2018 Johann Lee <mer@qinka.pro> + +This fiel is part of HaskellFAI + +HaskellFAI is free software: you can redistribute it and/or modify +it under the terms of the GNU Less General Public License as published by +the Free Software Foundation, either version 3 of the License, +or (at your option) any later version. + +Haskell is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warrenty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Less General Public License for more details. + +You should have received a copy of the GNU Less General Public License +along with HaskellFAI. If not, see <http://www.gnu.org/licenses/>. + +-} + +{-| +Module: Foreign.FAI.Types +Description: The types and the class of FAI +Copyright: (C) 2018 Johann Lee <me@qinka.pro> +License: LGPL3 +Maintainer: me@qinka.pro +Stability: experimental +Portability: unknown + +The types and the class of FAI. +-} + +{-# LANGUAGE GADTs #-} +{-# LANGUAGE MultiParamTypeClasses #-} +{-# LANGUAGE TypeFamilies #-} + +module Foreign.FAI.Types + ( Pf(..) + , Buffer(..) + , Context(..) + , Accelerate(..) + , FAI(..) + , FAICopy(..) + , newBuffer + , dupBuffer + , dupBufferD + , liftIO + , accelerate + ) where + +import Control.Monad +import Control.Monad.IO.Class (MonadIO (..)) +import Foreign.ForeignPtr +import Foreign.Ptr +import Foreign.Storable + +type family Pf p t :: * + +data Buffer p a = Buffer + { bufPtr :: ForeignPtr (Pf p a) -- ^ pointer + , bufSize :: Int -- ^ number of size + } + deriving (Show, Eq) + +newtype Context p = Context + { unContextPtr :: Ptr (Context p) + } + deriving (Show, Eq) + +newtype Accelerate p a = Accelerate + { doAccelerate :: Context p -> IO (a, Context p) + } + +accelerate :: Context p -> Accelerate p a -> IO a +accelerate cc = (fst <$>) . flip doAccelerate cc + +class FAI p where + faiMemAllocate :: Context p + -> Int -- ^ size + -> IO (Ptr a) -- ^ Pointer + faiMemRelease :: Context p + -> Ptr a -- ^ Pointer + -> IO () + faiMemReleaseP :: Context p + -> IO (Either + (FinalizerEnvPtr (Context p) a) + (FinalizerPtr a)) + -- ^ pointer of the function + -- of release the pointer + +class (FAI p1, FAI p2) => FAICopy p1 p2 where + faiMemCopy :: (Storable b, (Pf p1 a) ~ b, Storable c, (Pf p2 a) ~ c) + => Buffer p2 a -- ^ Destination + -> Buffer p1 a -- ^ Source + -> IO () + +instance Functor (Accelerate p) where + fmap f (Accelerate a) = Accelerate $ \c -> do + (r,c') <- a c + return (f r, c') + +instance Applicative (Accelerate p) where + pure x = Accelerate $ \c -> return (x, c) + (<*>) (Accelerate ff) (Accelerate fa) = Accelerate $ \c1 -> do + (r1,c2) <- fa c1 + (r2,c3) <- ff c2 + return (r2 r1, c3) + +instance Monad (Accelerate p) where + (>>=) (Accelerate a) mf = Accelerate $ \c1 -> do + (r1, c2) <- a c1 + let (Accelerate m) = mf r1 + m c2 + +instance MonadIO (Accelerate p) where + liftIO m = Accelerate $ \c -> (\r -> (r,c)) <$> m + +autoNewForeignPtr :: Either + (FinalizerEnvPtr (Context p) (Pf p a)) + (FinalizerPtr (Pf p a)) + -> Context p + -> Ptr (Pf p a) + -> Int + -> IO (Buffer p a) +autoNewForeignPtr fin cc ptr size = fmap (`Buffer` size) $ case fin of + Left f -> newForeignPtrEnv f (unContextPtr cc) ptr + Right f -> newForeignPtr f ptr + +newBuffer :: (FAI p, Storable b, (Pf p a) ~ b) + => Int -- ^ number of items + -> Accelerate p (Buffer p a) +newBuffer n = Accelerate $ \cc -> do + fin <- faiMemReleaseP cc + (ptr, size) <- alloc cc undefined + when (nullPtr == ptr) $ error "Can not allocate memory." + buf <- autoNewForeignPtr fin cc ptr size + return (buf, cc) + where alloc :: (FAI p, Storable b) => Context p -> b -> IO (Ptr b, Int) + alloc cc u = + let size = n * sizeOf u + in (\p -> (p, size)) <$> faiMemAllocate cc (n * sizeOf u) + +-- | without copy things +dupBuffer :: ( FAICopy p1 p2, FAI p1, FAI p2 + , Storable b, Pf p2 a ~ b, Pf p1 a ~ b) + => Bool + -> Buffer p1 a + -> Accelerate p2 (Buffer p2 a) +dupBuffer is buf = Accelerate $ \cc -> dup cc is buf + +dupBufferD :: ( FAICopy p2 p1, FAI p1, FAI p2 + , Storable b, Pf p2 a ~ b, Pf p1 a ~ b) + => Bool + -> Buffer p2 a + -> Accelerate p2 (Buffer p1 a) +dupBufferD is buf = Accelerate $ \cc -> replaceContext cc <$> dup undefined is buf + +replaceContext :: Context p2 -> (a, Context p1) -> (a, Context p2) +replaceContext cc (a, _) = (a, cc) + +dup :: ( FAICopy p1 p2, FAI p1, FAI p2 + , Storable b, Pf p2 a ~ b, Pf p1 a ~ b) + => Context p2 + -> Bool + -> Buffer p1 a + -> IO (Buffer p2 a, Context p2) +dup cc is buf = do + fin <- faiMemReleaseP cc + let size = bufSize buf + ptr <- faiMemAllocate cc size + bDst <- autoNewForeignPtr fin cc ptr size + when is $ faiMemCopy bDst buf + return (bDst, cc) +
+ test/Foreign/FAI/Platform/CUDASpec.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE CPP #-} +{-# LANGUAGE TypeFamilies #-} + +module Foreign.FAI.Platform.CUDASpec + ( spec + ) where + + +import Test.Hspec + +#ifdef ENABLE_CUDA + +import Foreign.FAI.Platform.CUDA +import Foreign.FAI.Platform.Host +import Foreign.FAI.Types +import Foreign.ForeignPtr +import Foreign.Marshal.Array +import Foreign.Ptr +import Foreign.Storable + +peekBuffer :: (Storable b, Pf Host a ~ b) => Buffer Host a -> IO [b] +peekBuffer (Buffer fp len) = withForeignPtr fp $ \p -> peekArray len p + +peekBufferA :: (Storable b, Pf Host a ~ b, Pf CUDA a ~ b) => Buffer CUDA a -> Accelerate CUDA [b] +peekBufferA b = do + hostBuffer <- dupBufferD True b + liftIO $ peekBuffer hostBuffer + + +spec :: Spec +spec = do + describe "Test CUDA" $ do + it "copy and same" $ do + let acc = accelerate cc $ do + let arr1 = [1..100] :: [Float] + b1 = bufFromList arr1 :: Buffer Host Float + liftIO $ print b1 + b2 <- dupBuffer True b1 :: Accelerate CUDA (Buffer CUDA Float) + liftIO $ print b2 + b3 <- dupBufferD True b2 + liftIO $ print b3 + let arr2 = bufToList b3 + return (arr1, arr2) + (arr1, arr2) <- acc + arr1 `shouldBe` arr2 + +cc = Context nullPtr + +#else +spec = describe "Skip CUDA Test" $ it "Do nothing" $ putStrLn "Skip." +-- ENABLE_CUDA +#endif
+ test/Foreign/FAI/Platform/HostSpec.hs view
@@ -0,0 +1,54 @@+{-# LANGUAGE TypeFamilies #-} + +module Foreign.FAI.Platform.HostSpec + ( spec + ) where + + +import Foreign.FAI.Types +import Foreign.FAI.Platform.Host +import Test.Hspec +import Foreign.Ptr +import Foreign.ForeignPtr +import Foreign.Marshal.Array +import Foreign.Storable + +peekBuffer :: (Storable b, Pf Host a ~ b) => Buffer Host a -> IO [b] +peekBuffer (Buffer fp len) = withForeignPtr fp $ \p -> peek undefined p len + where peek :: (Storable b) => b -> Ptr b-> Int -> IO [b] + peek u ptr i = peekArray (i `div` sizeOf u) ptr + +peekBufferA :: (Storable b, Pf Host a ~ b) => Buffer Host a -> Accelerate Host [b] +peekBufferA b = liftIO $ peekBuffer b + + +spec :: Spec +spec = do + describe "Allocate buffer" $ do + it "newBuffer" $ do + let acc = accelerate cc $ do + b <- newBuffer 20 :: Accelerate Host (Buffer Host Float) + liftIO $ print b + peekBufferA b >>= liftIO. print + return () + acc `shouldReturn` () + it "dupBuffer" $ do + let acc = accelerate cc $ do + b1 <- newBuffer 20 :: Accelerate Host (Buffer Host Float) + peekBufferA b1 >>= liftIO . print + b2 <- dupBuffer False b1 + peekBufferA b2 >>= liftIO . print + return () + acc `shouldReturn` () + describe "Test host" $ do + it "copy and same" $ do + let acc = accelerate cc $ do + let arr1 = [1..100] :: [Float] + b1 = bufFromList arr1 :: Buffer Host Float + b2 <- dupBuffer True b1 :: Accelerate Host (Buffer Host Float) + let arr2 = bufToList b2 + return (arr1, arr2) + (arr1, arr2) <- acc + arr1 `shouldBe` arr2 + +cc = Context nullPtr
+ test/Spec.hs view
@@ -0,0 +1,1 @@+{-# OPTIONS_GHC -F -pgmF hspec-discover #-}