<commit_before>{-# LANGUAGE CPP #-}
-- |
-- Module      : Data.Array.Accelerate.CUDA
-- Copyright   : [2008..2010] <NAME>, <NAME>, <NAME>, <NAME>
-- License     : BSD3
--
-- Maintainer  : <NAME> <<EMAIL>>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--
-- This module is the CUDA backend for the embedded array language.
--

module Data.Array.Accelerate.CUDA (

    -- * Generate and execute CUDA code for an array expression
    Arrays, precompile, run, stream

  ) where

import Prelude hiding (catch)
import Control.Exception
import System.IO.Unsafe

import Foreign.CUDA.Driver.Error

import Data.Array.Accelerate.AST
import Data.Array.Accelerate.CUDA.State
import Data.Array.Accelerate.CUDA.Compile
import Data.Array.Accelerate.CUDA.Execute
import Data.Array.Accelerate.CUDA.Array.Device
import qualified Data.Array.Accelerate.CUDA.Smart as Sugar

#include "accelerate.h"


-- Accelerate: CUDA
-- ~~~~~~~~~~~~~~~~

-- | Compile and run a complete embedded array program using the CUDA backend
--
{-# NOINLINE run #-}
run :: Arrays a => Sugar.Acc a -> a
run acc
  = unsafePerformIO
  $ evalCUDA (execute (Sugar.convertAcc acc) >>= collect)
             `catch`
             \e -> INTERNAL_ERROR(error) "unhandled" (show (e :: CUDAException))

execute :: Arrays a => Acc a -> CIO a
execute acc = compileAcc acc >> executeAcc acc


-- | Stream a lazily read list of input arrays through the given program,
-- collecting results as we go
--
-- TODO:
--  * avoid re-analysing the array code in the frontend
--  * overlap host-device & device->host transfers, as well as computation
--
{-# NOINLINE stream #-}
stream :: (Arrays a, Arrays b) => (a -> Sugar.Acc b) -> [a] -> [b]
stream acc as
  = unsafePerformIO
  $ sequence' . flip map as
  $ \s -> evalCUDA (execute (Sugar.convertAcc (acc s)) >>= collect)
                   `catch`
                   \e -> INTERNAL_ERROR(error) "unhandled" (show (e :: CUDAException))

-- A lazier version of Control.Monad.sequence
--
sequence' :: [IO a] -> IO [a]
sequence' ms = foldr k (return []) ms
    where k m m' = do { x <- m; xs <- unsafeInterleaveIO m'; return (x:xs) }


-- | Populate the internal cache with the compiled functions required to execute
-- the given array program. This is the same as 'run', except that (1) no data
-- is transferred to the device, and (2) the generated code is not invoked.
--

-- TODO: we would like the following to hold, but falls over in 
-- D.A.A.Array.Sugar.arrayType
--
-- Note that it is not necessary to create an unused array argument. For
-- example:
--
-- > dotp :: Vector a -> Vector a -> Acc (Scalar a)
-- > dotp xs ys = fold (+) 0 $ zipWith (*) (use xs) (use ys)
--
-- It is sufficient to:
--
-- > precompile (dotp undefined undefined :: Acc (Scalar Float))
--
{-# NOINLINE precompile #-}
precompile :: Arrays a => Sugar.Acc a -> ()
precompile acc
  = unsafePerformIO
  $ evalCUDA (precompileAcc (Sugar.convertAcc acc) >> return ())<commit_msg>clean up run/stream a bit<commit_after>{-# LANGUAGE CPP #-}
-- |
-- Module      : Data.Array.Accelerate.CUDA
-- Copyright   : [2008..2010] <NAME>, <NAME>, <NAME>, <NAME>
-- License     : BSD3
--
-- Maintainer  : <NAME> <<EMAIL>>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--
-- This module is the CUDA backend for the embedded array language.
--

module Data.Array.Accelerate.CUDA (

    -- * Generate and execute CUDA code for an array expression
    Arrays, run, stream, precompile

  ) where

import Prelude hiding (catch)
import Control.Exception
import System.IO.Unsafe

import Foreign.CUDA.Driver.Error

import Data.Array.Accelerate.CUDA.State
import Data.Array.Accelerate.CUDA.Compile
import Data.Array.Accelerate.CUDA.Execute
import Data.Array.Accelerate.CUDA.Array.Device
import qualified Data.Array.Accelerate.CUDA.Smart as Sugar

#include "accelerate.h"


-- Accelerate: CUDA
-- ~~~~~~~~~~~~~~~~

-- | Compile and run a complete embedded array program using the CUDA backend
--
{-# NOINLINE run #-}
run :: Arrays a => Sugar.Acc a -> a
run = unsafePerformIO . execute

-- | Stream a lazily read list of input arrays through the given program,
-- collecting results as we go
--

-- TODO:
--  * avoid re-analysing the array code in the frontend
--  * overlap host-device & device->host transfers, as well as computation
--
{-# NOINLINE stream #-}
stream :: (Arrays a, Arrays b) => (a -> Sugar.Acc b) -> [a] -> [b]
stream acc = unsafePerformIO . sequence' . map (execute . acc)


execute :: Arrays a => Sugar.Acc a -> IO a
execute a =
  let acc = Sugar.convertAcc a
  in  evalCUDA (compileAcc acc >> executeAcc acc >>= collect)
      `catch`
      \e -> INTERNAL_ERROR(error) "unhandled" (show (e :: CUDAException))

sequence' :: [IO a] -> IO [a]
sequence' ms = foldr k (return []) ms
    where k m m' = do { x <- m; xs <- unsafeInterleaveIO m'; return (x:xs) }


-- | Populate the internal cache with the compiled functions required to execute
-- the given array program. This is the same as 'run', except that (1) no data
-- is transferred to the device, and (2) the generated code is not invoked.
--

-- TODO: we would like the following to hold, but falls over in 
-- D.A.A.Array.Sugar.arrayType
--
-- Note that it is not necessary to create an unused array argument. For
-- example:
--
-- > dotp :: Vector a -> Vector a -> Acc (Scalar a)
-- > dotp xs ys = fold (+) 0 $ zipWith (*) (use xs) (use ys)
--
-- It is sufficient to:
--
-- > precompile (dotp undefined undefined :: Acc (Scalar Float))
--
{-# NOINLINE precompile #-}
precompile :: Arrays a => Sugar.Acc a -> ()
precompile acc
  = unsafePerformIO
  $ evalCUDA (precompileAcc (Sugar.convertAcc acc) >> return ())
{'fraction_non_alphanumeric': 0.1400668660918529, 'fraction_numerical': 0.0042231215907091325, 'mean_word_length': 3.0340667139815474, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 69, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4599163', 'n_tokens_mistral': 1867, 'n_tokens_neox': 1799, 'n_words': 648}