accelerate-examples 0.2.0.1 → 0.12.0.0
raw patch · 89 files changed
+5384/−2834 lines, 89 filesdep +QuickCheckdep +accelerate-cudadep +accelerate-iodep ~acceleratedep ~arraydep ~attoparsecnew-component:exe:accelerate-crystalnew-component:exe:accelerate-fluidnew-component:exe:accelerate-quickcheck
Dependencies added: QuickCheck, accelerate-cuda, accelerate-io, accelerate-opencl, bmp, cuda, fclabels, gloss, hashtables, random, test-framework, test-framework-quickcheck2
Dependency ranges changed: accelerate, array, attoparsec, bytestring, bytestring-lexing, cmdargs, criterion, deepseq, directory, filepath, mtl, mwc-random, pgm, pretty, vector, vector-algorithms
Files
- LICENSE +17/−24
- accelerate-examples.cabal +183/−69
- examples/crystal/Config.hs +89/−0
- examples/crystal/Main.hs +196/−0
- examples/fluid/src/Config.hs +164/−0
- examples/fluid/src/Event.hs +81/−0
- examples/fluid/src/Fluid.hs +169/−0
- examples/fluid/src/Main.hs +72/−0
- examples/fluid/src/Type.hs +67/−0
- examples/fluid/src/World.hs +198/−0
- examples/quickcheck/Arbitrary/Array.hs +78/−0
- examples/quickcheck/Arbitrary/Shape.hs +51/−0
- examples/quickcheck/Config.hs +150/−0
- examples/quickcheck/Main.hs +34/−0
- examples/quickcheck/Test/Base.hs +121/−0
- examples/quickcheck/Test/IndexSpace.hs +121/−0
- examples/quickcheck/Test/Mapping.hs +121/−0
- examples/quickcheck/Test/PrefixSum.hs +105/−0
- examples/quickcheck/Test/Reduction.hs +225/−0
- examples/tests/Benchmark.hs +58/−0
- examples/tests/Config.hs +191/−0
- examples/tests/Main.hs +78/−0
- examples/tests/Random.hs +73/−0
- examples/tests/Test.hs +237/−0
- examples/tests/Util.hs +20/−0
- examples/tests/Validate.hs +102/−0
- examples/tests/image-processing/Canny.hs +117/−0
- examples/tests/image-processing/IntegralImage.hs +49/−0
- examples/tests/image-processing/PGM.hs +32/−0
- examples/tests/io/BlockCopy.hs +91/−0
- examples/tests/io/VectorCopy.hs +74/−0
- examples/tests/io/fill_with_values.cpp +81/−0
- examples/tests/primitives/Backpermute.hs +70/−0
- examples/tests/primitives/Fold.hs +90/−0
- examples/tests/primitives/FoldSeg.hs +62/−0
- examples/tests/primitives/Gather.hs +73/−0
- examples/tests/primitives/Map.hs +52/−0
- examples/tests/primitives/Permute.hs +40/−0
- examples/tests/primitives/ScanSeg.hs +63/−0
- examples/tests/primitives/Scatter.hs +107/−0
- examples/tests/primitives/Stencil.hs +229/−0
- examples/tests/primitives/Stencil2.hs +109/−0
- examples/tests/primitives/Vector.hs +67/−0
- examples/tests/primitives/Zip.hs +35/−0
- examples/tests/primitives/ZipWith.hs +42/−0
- examples/tests/simple/BlackScholes.hs +88/−0
- examples/tests/simple/DotP.hs +44/−0
- examples/tests/simple/Filter.hs +55/−0
- examples/tests/simple/Radix.hs +90/−0
- examples/tests/simple/SASUM.hs +35/−0
- examples/tests/simple/SAXPY.hs +42/−0
- examples/tests/simple/SMVM.hs +78/−0
- examples/tests/simple/SMVM/Matrix.hs +75/−0
- examples/tests/simple/SMVM/MatrixMarket.hs +133/−0
- examples/tests/simple/SharingRecovery.hs +145/−0
- examples/tests/simple/SliceExamples.hs +115/−0
- src/Benchmark.hs +0/−58
- src/Config.hs +0/−135
- src/Main.hs +0/−74
- src/Random.hs +0/−72
- src/Test.hs +0/−234
- src/Util.hs +0/−17
- src/Validate.hs +0/−102
- tests/image-processing/Canny.hs +0/−117
- tests/image-processing/IntegralImage.hs +0/−49
- tests/image-processing/PGM.hs +0/−32
- tests/io/BlockCopy.hs +0/−90
- tests/io/Vector.hs +0/−75
- tests/io/fill_with_values.cpp +0/−81
- tests/primitives/Backpermute.hs +0/−69
- tests/primitives/Fold.hs +0/−84
- tests/primitives/Map.hs +0/−52
- tests/primitives/Permute.hs +0/−39
- tests/primitives/ScanSeg.hs +0/−58
- tests/primitives/Stencil.hs +0/−229
- tests/primitives/Stencil2.hs +0/−70
- tests/primitives/Zip.hs +0/−35
- tests/primitives/ZipWith.hs +0/−42
- tests/simple/BlackScholes.hs +0/−88
- tests/simple/DotP.hs +0/−44
- tests/simple/Filter.hs +0/−55
- tests/simple/Radix.hs +0/−86
- tests/simple/SASUM.hs +0/−35
- tests/simple/SAXPY.hs +0/−42
- tests/simple/SMVM.hs +0/−78
- tests/simple/SMVM/Matrix.hs +0/−75
- tests/simple/SMVM/MatrixMarket.hs +0/−133
- tests/simple/SharingRecovery.hs +0/−177
- tests/simple/SliceExamples.hs +0/−114
LICENSE view
@@ -1,30 +1,23 @@-Copyright (c)2011, Trevor L. McDonell--All rights reserved.+Copyright (c) [2007..2012] The Accelerate Team. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:- * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.-- * Redistributions in binary form must reproduce the above- copyright notice, this list of conditions and the following- disclaimer in the documentation and/or other materials provided- with the distribution.-- * Neither the name of Trevor L. McDonell nor the names of other- contributors may be used to endorse or promote products derived- from this software without specific prior written permission.+ * Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in the+ documentation and/or other materials provided with the distribution.+ * Neither the names of the contributors nor of their affiliations may + be used to endorse or promote products derived from this software + without specific prior written permission. -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
accelerate-examples.cabal view
@@ -1,69 +1,118 @@-Name: accelerate-examples-Version: 0.2.0.1-Synopsis: Examples using the Accelerate library-Description: Examples using the Accelerate library-License: BSD3-License-file: LICENSE-Author: The Accelerate Team-Maintainer: Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>-Category: Compilers/Interpreters,-Build-type: Simple-Cabal-version: >=1.6-Homepage: http://www.cse.unsw.edu.au/~chak/project/accelerate/--Category: Compilers/Interpreters, Concurrency, Data, Parallelism-Stability: Experimental+Name: accelerate-examples+Version: 0.12.0.0+License: BSD3+License-file: LICENSE+Author: The Accelerate Team+Maintainer: Trevor L. McDonell <tmcdonell@cse.unsw.edu.au>+Category: Compilers/Interpreters, Concurrency, Data, Parallelism+Stability: Experimental+Build-type: Simple+Cabal-version: >=1.6+Homepage: http://www.cse.unsw.edu.au/~chak/project/accelerate/ +Synopsis: Examples using the Accelerate library+Description: This package defines a number of example programs for verification and+ performance testing of the Accelerate language and associated backend+ implementations. By default the package attempts to build with all available+ backends, but this might not be desirable or even possible depending on your+ available hardware. To disable a specific component, install with the extra+ cabal flag(s):+ .+ . > cabal install accelerate-examples -f-opt+ .+ Where the available options are:+ .+ * cuda: A parallel CUDA backend for NVIDIA GPUs+ .+ * opencl: A parallel OpenCL backend+ .+ * io: Extra tests for reading and writing arrays in various formats+ . Flag cuda Description: Enable the CUDA parallel backend for NVIDIA GPUs Default: True +Flag opencl+ Description: Enable the OpenCL parallel backend+ Default: True+ Flag io Description: Provide access to the block copy I/O functionality- Default: False+ Default: True +-- Run some basic randomised tests of the primitive library operations, and unit+-- tests of known (hopefully prior) failures.+--+Executable accelerate-quickcheck+ Main-is: Main.hs+ hs-source-dirs: examples/quickcheck/++ other-modules: Config+ Arbitrary.Array+ Arbitrary.Shape+ Test.Base+ Test.IndexSpace+ Test.Mapping+ Test.PrefixSum+ Test.Reduction++ ghc-options: -Wall -O2+ -threaded+ -fpedantic-bottoms+ -fno-warn-orphans+ -fno-full-laziness+ -fno-excess-precision+ if impl(ghc >= 7.0)+ ghc-options: -rtsopts++ if flag(cuda)+ CPP-options: -DACCELERATE_CUDA_BACKEND+ build-depends: accelerate-cuda >= 0.12,+ cuda >= 0.4++ if flag(opencl)+ CPP-options: -DACCELERATE_OPENCL_BACKEND+ build-depends: accelerate-opencl == 0.1.*++ build-depends: accelerate >= 0.12,+ QuickCheck >= 2.0,+ test-framework >= 0.5,+ test-framework-quickcheck2 >= 0.2,+ random+++-- The main examples program including verification and timing tests for several+-- simple accelerate programs+-- Executable accelerate-examples Main-is: Main.hs- Other-modules: Benchmark- Test- Validate- Config- Random- Util- Canny- IntegralImage- PGM- BlockCopy- Vector- Backpermute- Map- ScanSeg- Stencil2- ZipWith- Fold- Permute- Stencil- Zip- BlackScholes- SASUM- SharingRecovery- DotP- SAXPY- SliceExamples- Filter- Radix- SMVM- SMVM.Matrix- SMVM.MatrixMarket- hs-source-dirs: src- tests/primitives- tests/simple- tests/image-processing- tests/io+ hs-source-dirs: examples/tests+ examples/tests/io+ examples/tests/image-processing+ examples/tests/primitives+ examples/tests/simple - c-sources: tests/io/fill_with_values.cpp+ other-modules: Benchmark, Config, Random, Test, Util, Validate,++ -- tests:+ -- image-processing+ Canny, IntegralImage, PGM,++ -- io+ BlockCopy, VectorCopy,++ -- primitives+ Backpermute, Fold, FoldSeg, Gather, Map, Permute, ScanSeg,+ Scatter, Stencil, Stencil2, Vector, Zip, ZipWith,++ -- simple+ BlackScholes, DotP, Filter, Radix, SASUM, SAXPY,+ SharingRecovery, SliceExamples, SMVM, SMVM.Matrix, SMVM.MatrixMarket+++ c-sources: examples/tests/io/fill_with_values.cpp extra-libraries: stdc++ ghc-options: -Wall -O2@@ -72,25 +121,90 @@ if flag(cuda) CPP-options: -DACCELERATE_CUDA_BACKEND+ build-depends: accelerate-cuda >= 0.12 + if flag(opencl)+ CPP-options: -DACCELERATE_OPENCL_BACKEND+ build-depends: accelerate-opencl == 0.1.*+ if flag(io) CPP-options: -DACCELERATE_IO+ build-depends: accelerate-io >= 0.12 - build-depends: accelerate == 0.10.*,- array >= 0.3 && < 0.5,- attoparsec == 0.8.*,+ build-depends: accelerate >= 0.12,+ array >= 0.3,+ attoparsec >= 0.10, base == 4.*,- bytestring == 0.9.*,- bytestring-lexing == 0.2.*,- cmdargs == 0.6.*,- criterion == 0.5.*,- deepseq >= 1.1 && < 1.4,- directory >= 1.0 && < 1.2,- filepath >= 1.0 && < 1.4,- mtl >= 1.1 && < 3.0,- mwc-random == 0.8.*,- pgm == 0.1.*,- pretty >= 1.0 && < 1.2,- vector == 0.7.*,- vector-algorithms == 0.4.*+ bytestring >= 0.9,+ bytestring-lexing >= 0.2,+ cmdargs >= 0.6,+ criterion >= 0.5,+ deepseq >= 1.1,+ directory >= 1.0,+ filepath >= 1.0,+ hashtables >= 1.0.1,+ mtl >= 1.1,+ mwc-random >= 0.8,+ pgm >= 0.1,+ pretty >= 1.0,+ vector >= 0.7,+ vector-algorithms >= 0.4 ++-- A quasicrystal demo as the sum of waves in a plane+--+Executable accelerate-crystal+ hs-source-dirs: examples/crystal+ Main-is: Main.hs+ other-modules: Config+ ghc-options: -O2 -Wall+ if impl(ghc >= 7.0)+ ghc-options: -rtsopts++ if flag(cuda)+ CPP-options: -DACCELERATE_CUDA_BACKEND+ build-depends: accelerate-cuda >= 0.12++ if flag(opencl)+ CPP-options: -DACCELERATE_OPENCL_BACKEND+ build-depends: accelerate-opencl == 0.1.*++ build-depends: accelerate >= 0.12,+ base == 4.*,+ criterion >= 0.5,+ fclabels >= 1.0,+ gloss >= 1.5+++-- A stable fluid simulation+--+Executable accelerate-fluid+ Main-is: Main.hs+ hs-source-dirs: examples/fluid/src+ other-modules: Config+ Event+ Fluid+ Type+ World++ ghc-options: -O2 -Wall++ if flag(cuda)+ cpp-options: -DACCELERATE_CUDA_BACKEND+ build-depends: accelerate-cuda >= 0.12++ Build-depends: accelerate >= 0.12,+ accelerate-io >= 0.12,+ base == 4.*,+ bmp >= 1.2,+ criterion >= 0.5,+ fclabels >= 1.0,+ gloss >= 1.7+++source-repository head+ type: git+ location: https://github.com/AccelerateHS/accelerate-examples++-- vim: nospell+--
+ examples/crystal/Config.hs view
@@ -0,0 +1,89 @@+{-# LANGUAGE CPP, TemplateHaskell, PatternGuards #-}++module Config (++ Options, optBackend, optSize, optZoom, optScale, optDegree, optBench,+ processArgs, run++) where++import Data.Label+import System.Exit+import System.Console.GetOpt+import Data.Array.Accelerate ( Arrays, Acc )+import qualified Data.Array.Accelerate.Interpreter as Interp+#ifdef ACCELERATE_CUDA_BACKEND+import qualified Data.Array.Accelerate.CUDA as CUDA+#endif++data Backend = Interpreter+#ifdef ACCELERATE_CUDA_BACKEND+ | CUDA+#endif+ deriving (Bounded, Show)++data Options = Options+ {+ _optBackend :: Backend+ , _optSize :: Int+ , _optZoom :: Int+ , _optScale :: Float+ , _optDegree :: Int+ , _optBench :: Bool+ , _optHelp :: Bool+ }+ deriving Show++$(mkLabels [''Options])++defaultOptions :: Options+defaultOptions = Options+ { _optBackend = maxBound+ , _optSize = 200+ , _optZoom = 3+ , _optScale = 30+ , _optDegree = 5+ , _optBench = False+ , _optHelp = False+ }+++run :: (Arrays a, Arrays b) => Options -> (Acc a -> Acc b) -> a -> b+run opts f = case _optBackend opts of+ Interpreter -> head . Interp.stream f . return+#ifdef ACCELERATE_CUDA_BACKEND+ CUDA -> CUDA.run1 f+#endif+++options :: [OptDescr (Options -> Options)]+options =+ [ Option [] ["interpreter"] (NoArg (set optBackend Interpreter)) "reference implementation (sequential)"+#ifdef ACCELERATE_CUDA_BACKEND+ , Option [] ["cuda"] (NoArg (set optBackend CUDA)) "implementation for NVIDIA GPUs (parallel)"+#endif+ , Option [] ["size"] (ReqArg (set optSize . read) "INT") "visualisation size (200)"+ , Option [] ["zoom"] (ReqArg (set optZoom . read) "INT") "pixel replication factor (3)"+ , Option [] ["scale"] (ReqArg (set optScale . read) "FLOAT") "feature size of visualisation (30)"+ , Option [] ["degree"] (ReqArg (set optDegree . read) "INT") "number of waves to sum for each point (5)"+ , Option [] ["benchmark"] (NoArg (set optBench True)) "benchmark instead of displaying animation (False)"+ , Option "h?" ["help"] (NoArg (set optHelp True)) "show help message"+ ]+++processArgs :: [String] -> IO (Options, [String])+processArgs argv =+ case getOpt' Permute options argv of+ (o,_,n,[]) -> case foldl (flip id) defaultOptions o of+ opts | False <- get optHelp opts -> return (opts, n)+ opts | True <- get optBench opts -> return (opts, "--help":n)+ _ -> putStrLn (helpMsg []) >> exitSuccess+ (_,_,_,err) -> error (helpMsg err)+ where+ helpMsg err = concat err ++ usageInfo header options+ header = unlines+ [ "accelerate-crystal (c) [2011..2012] The Accelerate Team"+ , ""+ , "Usage: accelerate-crystal [OPTIONS]"+ ]+
+ examples/crystal/Main.hs view
@@ -0,0 +1,196 @@+{-# LANGUAGE CPP #-}+-- Quasicrystals demo.+--+-- Based on code from:+-- http://hackage.haskell.org/package/repa-examples+-- http://mainisusuallyafunction.blogspot.com/2011/10/quasicrystals-as-sums-of-waves-in-plane.html+--++module Main where++import Config++import Data.Word+import Data.Label+import Foreign.Ptr+import Control.Monad+import Control.Exception+import Criterion.Main ( defaultMain, bench, whnf )+import Foreign.ForeignPtr+import System.Environment+import System.IO.Unsafe+import Data.Array.Accelerate ( Array, Scalar, Exp, Acc, DIM2, Z(..), (:.)(..) )+import qualified Data.Array.Accelerate as A+import qualified Graphics.Gloss as G++import Data.Array.Accelerate.Array.Data ( ptrsOfArrayData )+import Data.Array.Accelerate.Array.Sugar ( Array(..) )+++-- Types ----------------------------------------------------------------------+-- | Real value+type R = Float++-- | Point on the 2D plane.+type R2 = (R, R)++-- | Angle in radians.+type Angle = R++-- | Angle offset used for animation.+type Phi = Float++-- | Number of waves to sum for each pixel.+type Degree = Int++-- | Feature size of visualisation.+type Scale = Float++-- | Size of image to render.+type Size = Int++-- | How many times to duplicate each pixel / image zoom.+type Zoom = Int++-- | Type of the generated image data+type RGBA = Word32+type Bitmap = Array DIM2 RGBA++-- | Action to render a frame+type Render = Scalar Phi -> Bitmap+++-- Point ----------------------------------------------------------------------+-- | Compute a single point of the visualisation.+quasicrystal :: Size -> Scale -> Degree -> Acc (Scalar Phi) -> Exp DIM2 -> Exp R+quasicrystal size scale degree phi p+ = waves degree phi $ point size scale p+++-- | Sum up all the waves at a particular point.+waves :: Degree -> Acc (Scalar Phi) -> Exp R2 -> Exp R+waves degree phi x = wrap $ waver degree 0+ where+ waver :: Int -> Exp Float -> Exp Float+ waver n acc+ | n == 0 = acc+ | otherwise = waver (n - 1) (acc + wave (A.constant (fromIntegral n) * phi') x)++ phi'+ = A.the phi++ wrap n+ = let n_ = A.truncate n :: Exp Int+ n' = n - A.fromIntegral n_+ in+ (n_ `rem` 2 A./=* 0) A.? (1-n', n')+++-- | Generate the value for a single wave.+wave :: Exp Angle -> Exp R2 -> Exp R+wave th pt = (cos (cth*x + sth*y) + 1) / 2+ where+ (x,y) = A.unlift pt+ cth = cos th+ sth = sin th++-- | Convert an image point to a point on our wave plane.+point :: Size -> Scale -> Exp DIM2 -> Exp R2+point size scale ix = A.lift (adj x, adj y)+ where+ (Z:.x:.y) = A.unlift ix+ denom = A.constant (fromIntegral size - 1)+ adj n = A.constant scale * ((2 * A.fromIntegral n / denom) - 1)+++-- Computation ----------------------------------------------------------------+-- | Compute a single frame+makeImage :: Size -> Scale -> Degree -> Acc (Scalar Phi) -> Acc Bitmap+makeImage size scale degree phi = arrPixels+ where+ -- Compute values for the wave density at each point in the range [0..1]+ arrVals :: Acc (Array DIM2 Float)+ arrVals = A.generate+ (A.constant $ Z :. size :. size)+ (quasicrystal size scale degree phi)++ -- Convert the [0..1] values of wave density to an RGBA flat image+ arrPixels :: Acc Bitmap+ arrPixels = A.map rampColour arrVals+++-- | Colour ramp from red to white, convert into RGBA+rampColour :: Exp Float -> Exp RGBA+rampColour v = ra + g + b+ where+ u = 0 `A.max` v `A.min` 1+ ra = 0xFF0000FF+ g = A.truncate ((0.4 + (u * 0.6)) * 0xFF) * 0x10000+ b = A.truncate (u * 0xFF) * 0x100+++-- Rendering ------------------------------------------------------------------+-- | Compute a single frame of the animation as a Gloss picture.+--frame :: Size -> Scale -> Zoom -> Degree -> Float -> G.Picture++frame :: Render -> Size -> Zoom -> Float -> G.Picture+frame render size zoom time = G.scale zoom' zoom' pic+ where+ -- Scale the time to be the phi value of the animation. The action seems to+ -- slow down at increasing phi values, so we increase phi faster as time+ -- moves on.+ x = 1 + (time ** 1.5) * 0.005++ -- lift to a singleton array, else we would generate new code with the+ -- constant embedded at every frame+ phi = A.fromList Z [pi / x]++ -- Compute the image+ arrPixels = render phi++ -- Wrap the array data in a Foreign pointer and turn into a Gloss picture+ {-# NOINLINE rawData #-}+ rawData = let (Array _ adata) = arrPixels+ ((),ptr) = ptrsOfArrayData adata+ in+ unsafePerformIO $ newForeignPtr_ (castPtr ptr)++ pic = G.bitmapOfForeignPtr+ size size -- raw image size+ rawData -- the image data+ False -- don't cache this in texture memory++ -- Zoom the image so we get a bigger window.+ zoom' = fromIntegral zoom+++-- Main -----------------------------------------------------------------------+main :: IO ()+main+ = do (config, nops) <- processArgs =<< getArgs+ let size = get optSize config+ zoom = get optZoom config+ scale = get optScale config+ degree = get optDegree config+ render = run config $ makeImage size scale degree++ void . evaluate $ render (A.fromList Z [0])++ if get optBench config+ then withArgs nops $ defaultMain+ [ bench "crystal" $ whnf render (A.fromList Z [1.0]) ]++#if MIN_VERSION_gloss(1,6,0)+ else G.animate+ (G.InWindow "Quasicrystals" (size * zoom, size * zoom) (10, 10))+ (G.black)+ (frame render size zoom)+#else+ else G.animateInWindow+ "Quasicrystals"+ (size * zoom, size * zoom)+ (10, 10)+ (G.black)+ (frame render size zoom)+#endif+
+ examples/fluid/src/Config.hs view
@@ -0,0 +1,164 @@+{-# LANGUAGE CPP, TemplateHaskell, PatternGuards #-}+--+-- Configuration parameters+--++module Config (++ Options,+ viscosity, diffusion, densityBMP, velocityBMP, simulationWidth,+ simulationHeight, displayScale, displayFramerate, optBench,++ processArgs, run, run1++) where++import Data.Label+import System.Exit+import System.Console.GetOpt+import Data.Array.Accelerate ( Acc, Arrays )+import qualified Data.Array.Accelerate.Interpreter as I+#ifdef ACCELERATE_CUDA_BACKEND+import qualified Data.Array.Accelerate.CUDA as CUDA+#endif++data Backend+ = Interpreter+#ifdef ACCELERATE_CUDA_BACKEND+ | CUDA+#endif+ deriving (Show, Bounded)+++data Options = Options+ {+ -- simulation+ _viscosity :: Float+ , _diffusion :: Float++ -- visualisation+ , _densityBMP :: Maybe FilePath+ , _velocityBMP :: Maybe FilePath+ , _simulationWidth :: Int+ , _simulationHeight :: Int+ , _displayScale :: Int+ , _displayFramerate :: Int++ -- misc+ , _optBackend :: Backend+ , _optBench :: Bool+ , _optHelp :: Bool+ }+ deriving Show++$(mkLabels [''Options])++defaultOptions :: Options+defaultOptions = Options+ { _viscosity = 0+ , _diffusion = 0++ , _densityBMP = Nothing+ , _velocityBMP = Nothing+ , _simulationWidth = 250+ , _simulationHeight = 250+ , _displayScale = 2+ , _displayFramerate = 20++ , _optBackend = maxBound+ , _optBench = False+ , _optHelp = False+ }++-- Execute an Accelerate expression using the selected backend+--+run :: Arrays a => Options -> Acc a -> a+run opts = case _optBackend opts of+ Interpreter -> I.run+#ifdef ACCELERATE_CUDA_BACKEND+ CUDA -> CUDA.run+#endif++run1 :: (Arrays a, Arrays b) => Options -> (Acc a -> Acc b) -> a -> b+run1 opts f = case _optBackend opts of+ Interpreter -> head . I.stream f . return+#ifdef ACCELERATE_CUDA_BACKEND+ CUDA -> CUDA.run1 f+#endif+++-- Process command line arguments+--+options :: [OptDescr (Options -> Options)]+options =+ [ Option [] ["interpreter"] (NoArg (set optBackend Interpreter))+ "reference implementation (sequential)"++#ifdef ACCELERATE_CUDA_BACKEND+ , Option [] ["cuda"] (NoArg (set optBackend CUDA))+ "implementation for NVIDIA GPUs (parallel)"++#endif+ , Option [] ["viscosity"] (ReqArg (set viscosity . read) "FLOAT")+ $ "viscosity for velocity dampening " ++ def viscosity++ , Option [] ["diffusion"] (ReqArg (set diffusion . read) "FLOAT")+ $ "diffusion rate for mass dispersion " ++ def diffusion++ , Option [] ["width"] (ReqArg (set simulationWidth . read) "INT")+ $ "grid width for simulation " ++ def simulationWidth++ , Option [] ["height"] (ReqArg (set simulationHeight . read) "INT")+ $ "grid height for simulation " ++ def simulationHeight++ , Option [] ["scale"] (ReqArg (set displayScale . read) "INT")+ $ "feature size of visualisation " ++ def displayScale++ , Option [] ["framerate"] (ReqArg (set displayFramerate . read) "INT")+ $ "frame rate for visualisation " ++ def displayFramerate++ , Option [] ["bmp-density"] (ReqArg (set densityBMP . Just) "FILE.bmp")+ "file for initial fluid density"++ , Option [] ["bmp-velocity"] (ReqArg (set velocityBMP . Just) "FILE.bmp")+ "file for initial fluid velocity"++ --+ , Option [] ["benchmark"] (NoArg (set optBench True))+ "benchmark instead of displaying animation (False)"++ , Option "h?" ["help"] (NoArg (set optHelp True))+ "show help message"+ ]+ where+ parens s = "(" ++ s ++ ")"+ def f = parens (show (get f defaultOptions))+++processArgs :: [String] -> IO (Options, [String])+processArgs argv =+ case getOpt' Permute options argv of+ (o,_,n,[]) -> case foldl (flip id) defaultOptions o of+ opts | False <- get optHelp opts -> return (opts, n)+ opts | True <- get optBench opts -> return (opts, "--help":n)+ _ -> putStrLn (helpMsg []) >> exitSuccess+ (_,_,_,err) -> error (helpMsg err)+ where+ helpMsg err = concat err ++ usageInfo header options ++ footer+ header = unlines+ [ "accelerate-fluid (c) 2011 Trevor L. McDonell"+ , ""+ , "Usage: accelerate-fluid [OPTIONS]"+ ]++ footer = unlines+ [ ""+ , "Runtime usage:"+ , ""+ , " click add density sources to the image"+ , " shift-click add velocity sources"+ , " r reset the image"+ , " d toggle display of density field"+ , " v toggle display of velocity field lines"+ ]+
+ examples/fluid/src/Event.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE PatternGuards #-}+--+-- Event handling+--++module Event where++import Config+import World+import Data.Label+import Graphics.Gloss.Interface.Pure.Game+import Data.Array.Accelerate ( Z(..), (:.)(..) )+++-- Event locations are returned as window coordinates, where the origin is in+-- the centre of the window and increases to the right and up. If the simulation+-- size is (100,100) with scale factor of 4, then the event coordinates are+-- returned in the range [-200,200].+--+react :: Options -> Event -> World -> IO World+react opt event world =+ case event of+ EventKey (Char c) s m _ -> keyboard c s m+ EventKey (MouseButton LeftButton) s m uv -> return $ mouse m s (coord uv)+ EventMotion uv -> return $ motion (coord uv)+ _ -> return $ world+ where+ -- Inject a new density source when the left button is clicked.+ --+ -- If the shift key is held, remember the location and add a new velocity+ -- source between the old and new points as the mouse moves.+ --+ mouse key button xy+ | Up <- shift key, Down <- button+ = world { currentSource = Density xy+ , densitySource = addDensity xy }++ | Down <- shift key, Down <- button+ = world { currentSource = Velocity xy }++ | Down <- shift key, Up <- button+ = case currentSource world of+ Velocity x0y0 -> world { currentSource = None+ , velocitySource = addVelocity x0y0 xy }+ _ -> world { currentSource = None}++ | otherwise+ = world { currentSource = None }++ -- Handle key presses+ --+ keyboard 'r' Down _ = initialise opt+ keyboard 'd' Down _ = return $ world { displayDensity = not (displayDensity world) }+ keyboard 'v' Down _ = return $ world { displayVelocity = not (displayVelocity world) }+ keyboard _ _ _ = return world++ -- As the mouse moves, keep inserting density sources, or adding source+ -- velocities+ --+ motion xy =+ case currentSource world of+ Density _ -> world { currentSource = Density xy+ , densitySource = addDensity xy }+ Velocity x0y0 -> world { currentSource = Velocity xy+ , velocitySource = addVelocity x0y0 xy }+ _ -> world+ --+ addDensity (x,y) = (Z:.y:.x, 1) : densitySource world++ addVelocity (x0,y0) (x1,y1) = let u = fromIntegral (x1-x0)+ v = fromIntegral (y1-y0)+ in (Z:.y0:.x0, (u * width, v * height)) : velocitySource world+ --+ zoom = fromIntegral $ get displayScale opt+ width = fromIntegral $ get simulationWidth opt+ height = fromIntegral $ get simulationHeight opt+ scaleX = width / (width * zoom + 1)+ scaleY = height / (height * zoom + 1)+ coord (u,v) = ( truncate $ u * scaleX + width /2+ , truncate $ v * scaleY + height/2)+
+ examples/fluid/src/Fluid.hs view
@@ -0,0 +1,169 @@+--+-- Fluid simulation+--++module Fluid (++ Simulation, fluid++) where++import Type++import Data.Array.Accelerate ( Z(..), (:.)(..), Exp, Acc, Scalar, Vector, (?|), (==*) )+import qualified Data.Array.Accelerate as A+++type Simulation+ = Acc ( Scalar Timestep -- time to evolve the simulation+ , DensitySource -- locations to add density sources+ , VelocitySource -- locations to add velocity sources+ , DensityField -- the current density field+ , VelocityField ) -- the current velocity field+ -> Acc ( DensityField, VelocityField )+++-- A fluid simulation+--+fluid :: Viscosity -> Diffusion -> Simulation+fluid dp dn inputs =+ let (dt, ds, vs, df, vf) = A.unlift inputs+ df' = density dn dt ds vf df+ vf' = velocity dp dt vs vf+ in+ A.lift (df', vf')++-- The velocity over a timestep evolves due to three causes:+-- 1. the addition of forces+-- 2. viscous diffusion+-- 3. self-advection+--+velocity+ :: Viscosity+ -> Acc (Scalar Timestep)+ -> Acc VelocitySource+ -> Acc VelocityField+ -> Acc VelocityField+velocity dp dt vs vf0+ = project+ . advect dt vf0+ . project+ . diffuse dp dt+ $ inject vs vf0+++-- Ensure the velocity field conserves mass+--+project :: Acc VelocityField -> Acc VelocityField+project vf = A.stencil2 poisson A.Mirror vf A.Mirror p+ where+ steps = 20+ grad = A.stencil divF A.Mirror vf+ p1 = A.stencil2 pF (A.Constant 0) grad A.Mirror+ p = foldl1 (.) (replicate steps p1) grad++ poisson :: A.Stencil3x3 Velocity -> A.Stencil3x3 Float -> Exp Velocity+ poisson (_,(_,uv,_),_) ((_,t,_), (l,_,r), (_,b,_)) = uv .-. 0.5 .*. A.lift (r-l, t-b)++ divF :: A.Stencil3x3 Velocity -> Exp Float+ divF ((_,t,_), (l,_,r), (_,b,_)) = -0.5 * (A.fst r - A.fst l + A.snd t - A.snd b)++ pF :: A.Stencil3x3 Float -> A.Stencil3x3 Float -> Exp Float+ pF (_,(_,x,_),_) ((_,t,_), (l,_,r), (_,b,_)) = 0.25 * (x + l + t + r + b)++++-- The density over a timestep evolves due to three causes:+-- 1. the addition of source particles+-- 2. self-diffusion+-- 3. motion through the velocity field+--+density+ :: Diffusion+ -> Acc (Scalar Timestep)+ -> Acc DensitySource+ -> Acc VelocityField+ -> Acc DensityField+ -> Acc DensityField+density dn dt ds vf+ = advect dt vf+ . diffuse dn dt+ . inject ds+++-- Inject sources into the field+--+-- TLM: sources should be a vector of (index, value) pairs, but no fusion means+-- that extracting the components for permute (via unzip) is extra work.+--+inject+ :: FieldElt e+ => Acc (Vector Index, Vector e)+ -> Acc (Field e)+ -> Acc (Field e)+inject source field =+ let (is, ps) = A.unlift source+ in A.size ps ==* 0+ ?| ( field, A.permute (.+.) field (is A.!) ps )+++diffuse+ :: FieldElt e+ => Diffusion+ -> Acc (Scalar Timestep)+ -> Acc (Field e)+ -> Acc (Field e)+diffuse dn dt df0 =+ a ==* 0+ ?| ( df0 , foldl1 (.) (replicate steps diffuse1) df0 )+ where+ steps = 20+ a = A.the dt * A.constant dn * (A.fromIntegral (A.size df0))+ c = 1 + 4*a++ diffuse1 df = A.stencil2 relax (A.Constant zero) df0 A.Mirror df++ relax :: FieldElt e => A.Stencil3x3 e -> A.Stencil3x3 e -> Exp e+ relax (_,(_,x0,_),_) ((_,t,_), (l,_,r), (_,b,_)) = (x0 .+. a .*. (l.+.t.+.r.+.b)) ./. c+++advect+ :: FieldElt e+ => Acc (Scalar Timestep)+ -> Acc VelocityField+ -> Acc (Field e)+ -> Acc (Field e)+advect dt' vf df = A.generate sh backtrace+ where+ dt = A.the dt'+ sh = A.shape vf+ Z :. h :. w = A.unlift sh++ backtrace ix = s0.*.(t0.*.d00 .+. t1.*.d10) .+. s1.*.(t0.*.d01 .+. t1.*.d11)+ where+ Z:.j:.i = A.unlift ix+ (u, v) = A.unlift (vf A.! ix)++ -- backtrack densities based on velocity field+ clamp z = A.max 0.5 . A.min (A.fromIntegral z - 1.5)+ x = w `clamp` (A.fromIntegral i - dt * u)+ y = h `clamp` (A.fromIntegral j - dt * v)++ -- discrete locations surrounding point+ i0 = A.truncate x+ j0 = A.truncate y+ i1 = i0 + 1+ j1 = j0 + 1++ -- weighting based on location between the discrete points+ s1 = x - A.fromIntegral i0+ t1 = y - A.fromIntegral j0+ s0 = 1 - s1+ t0 = 1 - t1++ -- read the density values surrounding the calculated advection point+ d00 = df A.! A.lift (Z :. j0 :. i0)+ d10 = df A.! A.lift (Z :. j1 :. i0)+ d01 = df A.! A.lift (Z :. j0 :. i1)+ d11 = df A.! A.lift (Z :. j1 :. i1)+
+ examples/fluid/src/Main.hs view
@@ -0,0 +1,72 @@+--+-- A stable fluid simulation+--+-- Jos Stam, "Real-time Fluid Dynamics for Games"+--++module Main where++import Config+import World+import Fluid+import Event+import Data.Label+import Criterion.Main+import System.Environment+import Graphics.Gloss.Interface.IO.Game++import Prelude as P+import Data.Array.Accelerate as A+++main :: IO ()+main = do+ (opt,noms) <- processArgs =<< getArgs+ let -- configuration parameters+ --+ width = get simulationWidth opt * get displayScale opt+ height = get simulationHeight opt * get displayScale opt+ fps = get displayFramerate opt+ dp = get viscosity opt+ dn = get diffusion opt++ -- Prepare user-input density and velocity sources+ --+ sources s = let (ix, ss) = P.unzip s+ sh = Z :. length ix+ in ( A.fromList sh ix, A.fromList sh ss )++ -- Prepare to execute the next step of the simulation.+ --+ -- Critically, we use the run1 execution form to ensure we bypass all+ -- front-end conversion phases.+ --+ simulate timestep world =+ let step = run1 opt (fluid dp dn)+ dt = A.fromList Z [timestep]+ ds = sources (densitySource world)+ vs = sources (velocitySource world)+ (df', vf') = step ( dt, ds, vs, densityField world, velocityField world )+ in+ return $ world { densityField = df', velocityField = vf'+ , densitySource = [], velocitySource = [] }++ -- warming up...+ initialWorld <- initialise opt+ _ <- simulate 0.1 initialWorld++ if get optBench opt+ -- benchmark+ then withArgs noms $ defaultMain+ [ bench "fluid" $ whnfIO (simulate 1.0 initialWorld) ]++ -- simulate+ else playIO+ (InWindow "accelerate-fluid" (width, height) (10, 20))+ black -- background colour+ fps -- display framerate+ initialWorld -- initial state of the simulation+ (render opt) -- render world state into a picture+ (react opt) -- handle user events+ simulate -- one step of the simulation+
+ examples/fluid/src/Type.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE FlexibleInstances #-}+--+-- Types used throughout the simulation+--++module Type (++ Timestep, Viscosity, Diffusion, Index, Density, Velocity,+ Field, FieldElt(..), DensityField, VelocityField, DensitySource, VelocitySource,++ RGBA, Image++) where++import Data.Word+import Data.Array.Accelerate++type Timestep = Float+type Viscosity = Float+type Diffusion = Float+type Index = DIM2+type Density = Float+type Velocity = (Float, Float)++type Field a = Array DIM2 a+type DensityField = Field Density+type VelocityField = Field Velocity++type Source a = (Vector Index, Vector a)+type DensitySource = Source Density+type VelocitySource = Source Velocity++type RGBA = Word32+type Image a = Array DIM2 a+++infixl 6 .+.+infixl 6 .-.+infixl 7 .*.+infixl 7 ./.++class Elt e => FieldElt e where+ zero :: e+ (.+.) :: Exp e -> Exp e -> Exp e+ (.-.) :: Exp e -> Exp e -> Exp e+ (.*.) :: Exp Float -> Exp e -> Exp e+ (./.) :: Exp e -> Exp Float -> Exp e++instance FieldElt Density where+ zero = 0+ (.+.) = (+)+ (.-.) = (-)+ (.*.) = (*)+ (./.) = (/)++instance FieldElt Velocity where+ zero = (0, 0)+ (.+.) = app2 (+)+ (.-.) = app2 (-)+ c .*. xy = let (x,y) = unlift xy in lift (c*x, c*y)+ xy ./. c = let (x,y) = unlift xy in lift (x/c, y/c)++app2 :: Elt e => (Exp e -> Exp e -> Exp e) -> Exp (e,e) -> Exp (e,e) -> Exp (e,e)+app2 f xu yv = let (x,u) = unlift xu+ (y,v) = unlift yv+ in lift (f x y, f u v)+
+ examples/fluid/src/World.hs view
@@ -0,0 +1,198 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE PatternGuards #-}+--+-- Displaying the world state+--++module World (World(..), Source(..), initialise, render) where++import Type+import Config++import Codec.BMP+import Data.Bits+import Data.Int+import Data.Word+import Data.Label+import Control.Monad+import Graphics.Gloss.Interface.IO.Game+import Foreign.Ptr+import Foreign.ForeignPtr+import Foreign.Storable+import Foreign.Marshal.Alloc+import Data.Array.Accelerate ( Z(..), (:.)(..), Exp )+import Data.Array.Accelerate.Array.Sugar ( Array(..) )++import qualified Data.Array.Accelerate.Array.Data as A+import qualified Data.Array.Accelerate.IO as A+import qualified Data.Array.Accelerate as A+++data World = World+ {+ -- current state of the simulation+ densityField :: !DensityField+ , velocityField :: !VelocityField++ -- user input+ , densitySource :: [(Index, Density)]+ , velocitySource :: [(Index, Velocity)]+ , currentSource :: Source+ , displayDensity :: Bool+ , displayVelocity :: Bool+ }+ deriving Show++data Source = Density (Int, Int)+ | Velocity (Int, Int)+ | None+ deriving (Eq, Show)+++-- Initialisation --------------------------------------------------------------+-- -------------- --++initialise :: Options -> IO World+initialise opt =+ let width = get simulationWidth opt+ height = get simulationHeight opt+ in do+ density <- initialDensity opt width height+ velocity <- initialVelocity opt width height++ return $ World+ { densityField = density+ , velocityField = velocity+ , densitySource = []+ , velocitySource = []+ , currentSource = None+ , displayDensity = True+ , displayVelocity = False+ }+++initialDensity :: Options -> Int -> Int -> IO DensityField+initialDensity opt width height+ -- Load the file, and use the luminance value as scalar density+ --+ | Just file <- get densityBMP opt+ = do+ arr <- readImageFromBMP file+ let (Z:.h:.w) = A.arrayShape arr++ when (w /= width || h /= height)+ $ error "fluid: density-bmp does not match width x height"++ return . run opt $ A.map densityOfRGBA (A.use arr)++ -- No density file given, just set the field to zero+ --+ | otherwise+ = return $ A.fromList (Z :. height :. width) (repeat 0)+++initialVelocity :: Options -> Int -> Int -> IO VelocityField+initialVelocity opt width height+ -- Load the file, and use the red and green channels for x- and y- velocity+ -- values respectively+ --+ | Just file <- get velocityBMP opt+ = do+ arr <- readImageFromBMP file+ let (Z:.h:.w) = A.arrayShape arr++ when (w /= width || h /= height)+ $ error "fluid: velocity-bmp does not match width x height"++ return . run opt $ A.map velocityOfRGBA (A.use arr)++ -- No density file given, just set to zero+ --+ | otherwise+ = return $ A.fromList (Z :. height :. width) (repeat (0,0))+++readImageFromBMP :: FilePath -> IO (Image RGBA)+readImageFromBMP file = do+ bmp <- either (error . show) id `fmap` readBMP file+ let (w,h) = bmpDimensions bmp+ --+ A.fromByteString (Z :. h :. w) ((), unpackBMPToRGBA32 bmp)+++densityOfRGBA :: Exp RGBA -> Exp Density+densityOfRGBA rgba =+ let b = (0.11 / 255) * A.fromIntegral ((rgba `div` 0x100) .&. 0xFF)+ g = (0.59 / 255) * A.fromIntegral ((rgba `div` 0x10000) .&. 0xFF)+ r = (0.3 / 255) * A.fromIntegral ((rgba `div` 0x1000000) .&. 0xFF)+ in+ r + g + b++velocityOfRGBA :: Exp RGBA -> Exp Velocity+velocityOfRGBA rgba =+ let g = A.fromIntegral (-128 + A.fromIntegral ((rgba `div` 0x10000) .&. 0xFF) :: Exp Int32)+ r = A.fromIntegral (-128 + A.fromIntegral ((rgba `div` 0x1000000) .&. 0xFF) :: Exp Int32)+ in+ A.lift (r * 0.001, g * 0.001)+++-- Rendering -------------------------------------------------------------------+-- --------- --++render :: Options -> World -> IO Picture+render opt world = do+ den <- if displayDensity world+ then renderDensity $ densityField world+ else return blank++ vel <- if displayVelocity world+ then renderVelocity $ velocityField world+ else return blank+ --+ return $ Scale zoom zoom $ Pictures [ den, vel ]+ where+ zoom = fromIntegral $ get displayScale opt+++renderDensity :: DensityField -> IO Picture+renderDensity df@(Array _ ad) = do+ dst <- mallocBytes (n*4)+ fill 0 src dst+ fptr <- newForeignPtr finalizerFree dst+ return $ bitmapOfForeignPtr w h fptr False+ where+ ((),src) = A.ptrsOfArrayData ad+ Z:.h:.w = A.arrayShape df+ n = h*w+ colour !f = let c = 0 `max` f `min` 1+ in floatToWord8 (255*c)++ fill !i !s !d | i >= n = return ()+ | otherwise = do c <- colour `fmap` peek s+ poke d 0xFF -- A+ pokeByteOff d 1 c -- B+ pokeByteOff d 2 c -- G+ pokeByteOff d 3 c -- R+ fill (i+1) (plusPtr s 4) (plusPtr d 4)+++renderVelocity :: VelocityField -> IO Picture+renderVelocity vf+ = return+ $ Translate (fromIntegral $ -w `div` 2) (fromIntegral $ -h `div` 2)+ $ Pictures [ field (x,y) | y <- [2,7..h], x <- [2,7..w] ]+ where+ Z:.h:.w = A.arrayShape vf+ field (x0,y0) =+ let x = fromIntegral x0+ y = fromIntegral y0+ (u,v) = A.indexArray vf (Z:.y0:.x0)+ in Color red $ Line [ (x,y), (x+u, y+v) ]+++-- Float to Word8 conversion because the one in the GHC libraries doesn't have+-- enough specialisations and goes via Integer.+{-# INLINE floatToWord8 #-}+floatToWord8 :: Float -> Word8+floatToWord8 f = fromIntegral (truncate f :: Int)+
+ examples/quickcheck/Arbitrary/Array.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeOperators #-}++module Arbitrary.Array where++import Arbitrary.Shape++import Data.List+import Test.QuickCheck+import Data.Array.Accelerate.Array.Sugar+import System.Random ( Random )+++instance (Elt e, Arbitrary e) => Arbitrary (Array DIM0 e) where+ arbitrary = do+ e <- arbitrary+ return $! fromList Z [e]+ --+ shrink arr =+ [ fromList Z [x] | x <- shrink (arr ! Z) ]+++instance (Elt e, Arbitrary e) => Arbitrary (Array DIM1 e) where+ arbitrary = do+ sh <- sized arbitrarySmallShape+ adata <- vectorOf (size sh) arbitrary+ return $! fromList sh adata+ --+ shrink arr =+ let (Z :. n) = shape arr+ indices = [ map (Z:.) (nub sz) | sz <- shrink [0 .. n-1] ]+ in+ [ fromList (Z :. length sl) (map (arr!) sl) | sl <- indices ]+++instance (Elt e, Arbitrary e) => Arbitrary (Array DIM2 e) where+ arbitrary = do+ sh <- sized arbitrarySmallShape+ adata <- vectorOf (size sh) arbitrary+ return $! fromList sh adata+ --+ shrink arr =+ let (Z :. width :. height) = shape arr+ in+ [ fromList (Z :. length slx :. length sly) [ arr ! (Z:.x:.y) | x <- slx, y <- sly ]+ | slx <- map nub $ shrink [0 .. width - 1]+ , sly <- map nub $ shrink [0 .. height - 1]+ ]+++arbitraryArrayOfShape+ :: (Shape sh, Elt e, Arbitrary e)+ => sh+ -> Gen (Array sh e)+arbitraryArrayOfShape sh = do+ adata <- vectorOf (size sh) arbitrary+ return $! fromList sh adata++arbitrarySegmentedArray+ :: (Integral i, Shape sh, Elt e, Arbitrary sh, Arbitrary e)+ => Segments i -> Gen (Array (sh :. Int) e)+arbitrarySegmentedArray segs = do+ let sz = fromIntegral . sum $ toList segs+ sh <- sized $ \n -> arbitrarySmallShape (n `div` 2)+ adata <- vectorOf (size sh * sz) arbitrary+ return $! fromList (sh :. sz) adata++arbitrarySegments :: (Elt i, Integral i, Arbitrary i, Random i) => Gen (Segments i)+arbitrarySegments = do+ seg <- listOf (sized $ \n -> choose (0, fromIntegral n))+ return $! fromList (Z :. length seg) seg++arbitrarySegments1 :: (Elt i, Integral i, Arbitrary i, Random i) => Gen (Segments i)+arbitrarySegments1 = do+ seg <- listOf (sized $ \n -> choose (1, fromIntegral n))+ return $! fromList (Z :. length seg) seg+
+ examples/quickcheck/Arbitrary/Shape.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeOperators #-}++module Arbitrary.Shape where++import Test.QuickCheck+import Data.Array.Accelerate.Array.Sugar+++instance Arbitrary Z where+ arbitrary = return Z+ shrink = return++-- Keep shapes relatively small, because we are generating arrays via lists, but+-- scale the 'sized' parameter so we still get non-trivial test vectors.+--+instance (Shape sh, Arbitrary sh) => Arbitrary (sh :. Int) where+ arbitrary = do+ sh <- arbitrary+ sz <- sized $ \n ->+ let nMax = 2048 `div` max 1 (size sh)+ nMaxed = (n*4) `mod` nMax+ in+ choose (0, nMaxed)+ --+ return (sh :. sz)++ shrink (sh :. sz) = [ sh' :. sz' | sh' <- shrink sh, sz' <- shrink sz ]+++-- Generate an arbitrary shape, where each dimension is less than some specific+-- value. This will generate zero-sized shapes, but will take care not to+-- generate too many of them.+--+arbitrarySmallShape :: forall sh. (Shape sh, Arbitrary sh) => Int -> Gen sh+arbitrarySmallShape maxDim = resize maxDim arbitrary++-- Generate a shape as above, but also restrict the dimensions to be either all+-- zero, or all non-zero.+--+arbitrarySmallNonEmptyShape :: forall sh. (Shape sh, Arbitrary sh) => Int -> Gen sh+arbitrarySmallNonEmptyShape maxDim = do+ sh <- resize maxDim arbitrary :: Gen sh+ let ix = map (`mod` max 1 maxDim) (shapeToList sh)+ sh'+ | all (== 0) ix = ix+ | otherwise = map (max 1) ix+ --+ return (listToShape sh' :: sh)+
+ examples/quickcheck/Config.hs view
@@ -0,0 +1,150 @@+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE CPP #-}++module Config (++ -- options & test configuration+ Options,+ processArgs,+ optBackend, double, float, int64, int32, int16, int8,++ -- running tests+ run, run1++) where++import Data.Char+import Data.List+import Data.Label+import Control.Monad+import Test.Framework+import System.Console.GetOpt ( OptDescr(..), ArgDescr(..) )++import Data.Array.Accelerate ( Arrays, Acc )+import qualified Data.Array.Accelerate.Interpreter as Interp++#ifdef ACCELERATE_CUDA_BACKEND+import qualified Foreign.CUDA.Driver as CUDA+import qualified Data.Array.Accelerate.CUDA as CUDA+#endif++data Backend = Interpreter+#ifdef ACCELERATE_CUDA_BACKEND+ | CUDA+#endif+ deriving (Eq, Enum, Bounded, Show)+++data Options = Options+ {+ _optBackend :: !Backend,+ _double :: !Bool,+ _float :: !Bool,+ _int64 :: !Bool,+ _int32 :: !Bool,+ _int16 :: !Bool,+ _int8 :: !Bool+ }+ deriving Show++$( mkLabels [''Options] )++defaultOptions :: Options+defaultOptions = Options+ { _optBackend = maxBound+ , _double = True+ , _float = True+ , _int64 = True+ , _int32 = True+ , _int16 = True+ , _int8 = True+ }+++backends :: [OptDescr (Options -> Options)]+backends =+ [ Option [] ["interpreter"] (NoArg (set optBackend Interpreter)) "reference implementation (sequential)"+#ifdef ACCELERATE_CUDA_BACKEND+ , Option [] ["cuda"] (NoArg (set optBackend CUDA)) "implementation for NVIDIA GPUs (parallel)"+#endif+ ]+++run :: Arrays a => Options -> Acc a -> a+run opts = case _optBackend opts of+ Interpreter -> Interp.run+#ifdef ACCELERATE_CUDA_BACKEND+ CUDA -> CUDA.run+#endif++run1 :: (Arrays a, Arrays b) => Options -> (Acc a -> Acc b) -> a -> b+run1 opts f = case _optBackend opts of+ Interpreter -> head . Interp.stream f . return+#ifdef ACCELERATE_CUDA_BACKEND+ CUDA -> CUDA.run1 f+#endif+++-- Display a very basic usage message info: specifically, list the available+-- backends and highlight the active one.+--+usageInfo :: Options -> String+usageInfo opts = unlines (header : table)+ where+ active this = if this == map toLower (show $ get optBackend opts) then "*" else ""+ (ss,bs,ds) = unzip3 $ map (\(b,d) -> (active b, b, d)) $ concatMap extract backends+ table = zipWith3 paste (sameLen ss) (sameLen bs) ds+ paste x y z = " " ++ x ++ " " ++ y ++ " " ++ z+ sameLen xs = flushLeft ((maximum . map length) xs) xs+ flushLeft n xs = [ take n (x ++ repeat ' ') | x <- xs ]+ --+ extract (Option _ los _ descr) =+ let losFmt = intercalate ", " los+ in case lines descr of+ [] -> [(losFmt, "")]+ (x:xs) -> (losFmt, x) : [ ("",x') | x' <- xs ]+ --+ header = intercalate "\n" $+ [ "accelerate-quickcheck (c) 2012 The Accelerate Team"+ , ""+ , "Usage: accelerate-quickcheck [BACKEND] [OPTIONS]"+ , ""+ , "Available backends:"+ ]++-- Once the backend has been selected, we might need to enable or disable+-- certain classes of tests.+--+-- CUDA: double precision is only supported on certain kinds of hardware. We+-- can't get the exact device the backend will choose to run on, but we do+-- know that it will pick the most capable device available.+--+configureBackend :: Options -> IO Options+configureBackend opts = case _optBackend opts of+ Interpreter -> return opts+#ifdef ACCELERATE_CUDA_BACKEND+ CUDA -> do+ CUDA.initialise []+ n <- CUDA.count+ devs <- mapM CUDA.device [0 .. n-1]+ props <- mapM CUDA.props devs+ return $! opts { _double = any (\dev -> CUDA.computeCapability dev >= 1.3) props }+#endif+++processArgs :: [String] -> IO (Options, RunnerOptions)+processArgs argv = do+ args <- interpretArgs argv+ (options, runner) <- case args of+ Left msg -> error msg+ Right (opts, rest) -> (,opts) `liftM` configureBackend (foldl parse1 defaultOptions rest)+ --+ putStrLn $ usageInfo options+ return $ (options, runner)+ where+ parse1 opts x =+ case filter (\(Option _ [f] _ _) -> map toLower x `isPrefixOf` f) backends of+ [Option _ _ (NoArg go) _] -> go opts+ _ -> opts+
+ examples/quickcheck/Main.hs view
@@ -0,0 +1,34 @@++module Main where++import Test.Framework+import System.Environment++import Config+import Test.Mapping+import Test.Reduction+import Test.PrefixSum+import Test.IndexSpace+++main :: IO ()+main = do+ -- process command line args, and print a brief usage message+ --+ (options, runner) <- processArgs =<< getArgs++ -- the default execution order uses some knowledge of what functionality is+ -- required for each operation in the CUDA backend.+ --+ defaultMainWithOpts+ [ test_map options+ , test_zipWith options+ , test_foldAll options+ , test_fold options+ , test_prefixsum options -- requires fold+ , test_foldSeg options -- requires scan+ , test_permute options+ , test_backpermute options+ ]+ runner+
+ examples/quickcheck/Test/Base.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE DefaultSignatures #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE TypeOperators #-}++module Test.Base where++import Prelude as P+import Test.QuickCheck+import Data.Array.Accelerate+import Data.Array.Accelerate.Array.Sugar as Sugar+++-- A class of things that support almost-equality, so that we can disregard+-- small amounts of floating-point round-off error.+--+class Similar a where+ {-# INLINE (~=) #-}+ (~=) :: a -> a -> Bool+ default (~=) :: Eq a => a -> a -> Bool+ (~=) = (==)++infix 4 ~=++instance Similar a => Similar [a] where+ [] ~= [] = True+ (x:xs) ~= (y:ys) = x ~= y && xs ~= ys+ _ ~= _ = False++instance (Similar a, Similar b) => Similar (a, b) where+ (x1, y1) ~= (x2, y2) = x1 ~= x2 && y1 ~= y2+++instance Similar Int+instance Similar Int8+instance Similar Int16+instance Similar Int32+instance Similar Int64+instance Similar Word+instance Similar Word8+instance Similar Word16+instance Similar Word32+instance Similar Word64++instance Similar Float where (~=) = absRelTol+instance Similar Double where (~=) = absRelTol++{-# INLINE relTol #-}+relTol :: (Fractional a, Ord a) => a -> a -> a -> Bool+relTol epsilon x y = abs ((x-y) / (x+y+epsilon)) < epsilon++{-# INLINE absRelTol #-}+absRelTol :: (Fractional a, Ord a) => a -> a -> Bool+absRelTol u v+ | abs (u-v) < epsilonAbs = True+ | abs u > abs v = abs ((u-v) / u) < epsilonRel+ | otherwise = abs ((v-u) / v) < epsilonRel+ where+ epsilonRel = 0.001+ epsilonAbs = 0.00001+++-- some "missing" instances+--+instance Eq Z where+ Z == Z = True++instance (Eq sh, Shape sh) => Eq (sh :. Int) where+ (sh1 :. n1) == (sh2 :. n2) = n1 == n2 && sh1 == sh2+ (sh1 :. n1) /= (sh2 :. n2) = n1 /= n2 || sh1 /= sh2++instance (Eq e, Eq sh, Shape sh) => Eq (Array sh e) where+ a1 == a2 = arrayShape a1 == arrayShape a2+ && toList a1 == toList a2++ a1 /= a2 = arrayShape a1 /= arrayShape a2+ || toList a1 /= toList a2++instance (Similar e, Eq sh, Shape sh) => Similar (Array sh e) where+ a1 ~= a2 = arrayShape a1 == arrayShape a2+ && toList a1 ~= toList a2+++-- Print expected/received message on inequality+--+infix 4 .==.+(.==.) :: (Similar a, Show a) => a -> a -> Property+(.==.) ans ref = printTestCase message (ref ~= ans)+ where+ message = unlines ["*** Expected:", show ref+ ,"*** Received:", show ans ]+++-- Miscellaneous+--++indexHead :: Shape sh => (sh:.Int) -> Int+indexHead (_ :. sz) = sz++indexTail :: Shape sh => (sh:.Int) -> sh+indexTail (sh :. _) = sh++isEmptyArray :: Shape sh => Array sh e -> Bool+isEmptyArray arr = arraySize (arrayShape arr) == 0++mkDim :: Shape sh => Int -> sh+mkDim n = listToShape (P.replicate n 0)++dim0 :: DIM0+dim0 = mkDim 0++dim1 :: DIM1+dim1 = mkDim 1++dim2 :: DIM2+dim2 = mkDim 2++splitEvery :: Int -> [a] -> [[a]]+splitEvery _ [] = cycle [[]]+splitEvery n xs = let (h,t) = splitAt n xs+ in h : splitEvery n t+
+ examples/quickcheck/Test/IndexSpace.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Test.IndexSpace where++import Prelude as P+import Data.Label+import Data.Maybe+import Data.Typeable+import Test.QuickCheck+import Test.Framework+import Test.Framework.Providers.QuickCheck2++import Config+import Test.Base+import Arbitrary.Array ( )+import Data.Array.Unboxed as IArray hiding ( Array )+import Data.Array.Accelerate as Acc+import Data.Array.Accelerate.Array.Sugar ( newArray )+++--+-- Forward permutation ---------------------------------------------------------+--++test_permute :: Options -> Test+test_permute opt = testGroup "permute" $ catMaybes+ [ testIntegralElt int8 (undefined :: Int8)+ , testIntegralElt int16 (undefined :: Int16)+ , testIntegralElt int32 (undefined :: Int32)+ , testIntegralElt int64 (undefined :: Int64)+ , testIntegralElt int8 (undefined :: Word8)+ , testIntegralElt int16 (undefined :: Word16)+ , testIntegralElt int32 (undefined :: Word32)+ , testIntegralElt int64 (undefined :: Word64)+ , testFloatingElt float (undefined :: Float)+ , testFloatingElt double (undefined :: Double)+ ]+ where+ testIntegralElt :: forall e. (Elt e, Integral e, IsIntegral e, Arbitrary e) => (Options :-> Bool) -> e -> Maybe Test+ testIntegralElt ok _+ | P.not (get ok opt) = Nothing+ | otherwise = Just $ testGroup (show (typeOf (undefined :: e)))+ [ testProperty "histogram" (test_histogram Acc.fromIntegral P.fromIntegral :: Vector e -> Property)+ ]++ testFloatingElt :: forall e. (Elt e, RealFrac e, IsFloating e, Arbitrary e) => (Options :-> Bool) -> e -> Maybe Test+ testFloatingElt ok _+ | P.not (get ok opt) = Nothing+ | otherwise = Just $ testGroup (show (typeOf (undefined :: e)))+ [ testProperty "histogram" (test_histogram Acc.floor P.floor :: Vector e -> Property)+ ]++ test_histogram f g xs =+ sized $ \n -> run opt (histogramAcc n f xs) .==. histogramRef n g xs++ histogramAcc n f xs =+ let n' = unit (constant n)+ xs' = use xs+ zeros = generate (constant (Z :. n)) (const 0)+ ones = generate (shape xs') (const 1)+ in+ permute (+) zeros (\ix -> index1 $ f (xs' Acc.! ix) `mod` the n') ones++ histogramRef n f xs =+ let arr :: UArray Int Int32+ arr = accumArray (+) 0 (0, n-1) [ (f e `mod` n, 1) | e <- toList xs ]+ in+ fromIArray arr+++--+-- Backward permutation --------------------------------------------------------+--++test_backpermute :: Options -> Test+test_backpermute opt = testGroup "backpermute" $ catMaybes+ [ testElt int8 (undefined :: Int8)+ , testElt int16 (undefined :: Int16)+ , testElt int32 (undefined :: Int32)+ , testElt int64 (undefined :: Int64)+ , testElt int8 (undefined :: Word8)+ , testElt int16 (undefined :: Word16)+ , testElt int32 (undefined :: Word32)+ , testElt int64 (undefined :: Word64)+ , testElt float (undefined :: Float)+ , testElt double (undefined :: Double)+ ]+ where+ testElt :: forall e. (Elt e, Similar e, Arbitrary e) => (Options :-> Bool) -> e -> Maybe Test+ testElt ok _+ | P.not (get ok opt) = Nothing+ | otherwise = Just $ testGroup (show (typeOf (undefined::e)))+ [ testProperty "reverse" (test_reverse :: Array DIM1 e -> Property)+ , testProperty "transpose" (test_transpose :: Array DIM2 e -> Property)+ ]++ test_reverse xs = run opt (reverseAcc xs) .==. reverseRef xs+ test_transpose xs = run opt (transposeAcc xs) .==. transposeRef xs++ -- Reverse a vector+ --+ reverseRef xs = fromList (arrayShape xs) (reverse $ toList xs)+ reverseAcc xs =+ let xs' = use xs+ n = unindex1 $ shape xs'+ in+ backpermute (shape xs') (\ix -> index1 $ n - unindex1 ix - 1) xs'++ -- Transpose a 2D matrix+ --+ transposeAcc xs =+ let xs' = use xs+ swap = lift1 $ \(Z:.x:.y) -> Z:.y:.x :: Z :. Exp Int :. Exp Int+ in+ backpermute (swap (shape xs')) swap xs'++ transposeRef xs =+ let swap (Z:.x:.y) = Z :. y :. x+ in newArray (swap (arrayShape xs)) (\ix -> indexArray xs (swap ix))+
+ examples/quickcheck/Test/Mapping.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE RankNTypes #-}++module Test.Mapping where++import Prelude as P+import Data.Label+import Data.Maybe+import Data.Typeable+import Test.QuickCheck+import Test.Framework+import Test.Framework.Providers.QuickCheck2++import Config+import Test.Base+import Arbitrary.Array ()+import Data.Array.Accelerate as Acc+import Data.Array.Accelerate.Array.Sugar as Sugar+import qualified Data.Array.Accelerate.Array.Representation as R++--+-- Map -------------------------------------------------------------------------+--++test_map :: Options -> Test+test_map opt = testGroup "map" $ catMaybes+ [ testElt int8 (undefined :: Int8)+ , testElt int16 (undefined :: Int16)+ , testElt int32 (undefined :: Int32)+ , testElt int64 (undefined :: Int64)+ , testElt int8 (undefined :: Word8)+ , testElt int16 (undefined :: Word16)+ , testElt int32 (undefined :: Word32)+ , testElt int64 (undefined :: Word64)+ , testElt float (undefined :: Float)+ , testElt double (undefined :: Double)+ ]+ where+ test_square xs = run opt (Acc.map (\x -> x*x) (use xs)) .==. mapRef (\x -> x*x) xs+ test_abs xs = run opt (Acc.map abs (use xs)) .==. mapRef abs xs+ test_plus z xs =+ let z' = unit (constant z)+ in run opt (Acc.map (+ the z') (use xs)) .==. mapRef (+ z) xs++ testElt :: forall a. (Elt a, IsNum a, Similar a, Arbitrary a)+ => (Options :-> Bool)+ -> a+ -> Maybe Test+ testElt ok _+ | P.not (get ok opt) = Nothing+ | otherwise = Just $ testGroup (show (typeOf (undefined :: a)))+ [ testDim dim0+ , testDim dim1+ , testDim dim2+ ]+ where+ testDim :: forall sh. (Shape sh, Eq sh, Arbitrary sh, Arbitrary (Array sh a)) => sh -> Test+ testDim sh = testGroup ("DIM" ++ show (dim sh))+ [ testProperty "abs" (test_abs :: Array sh a -> Property)+ , testProperty "plus" (test_plus :: a -> Array sh a -> Property)+ , testProperty "square" (test_square :: Array sh a -> Property)+ ]+++test_zipWith :: Options -> Test+test_zipWith opt = testGroup "zipWith" $ catMaybes+ [ testElt int8 (undefined :: Int8)+ , testElt int16 (undefined :: Int16)+ , testElt int32 (undefined :: Int32)+ , testElt int64 (undefined :: Int64)+ , testElt int8 (undefined :: Word8)+ , testElt int16 (undefined :: Word16)+ , testElt int32 (undefined :: Word32)+ , testElt int64 (undefined :: Word64)+ , testElt float (undefined :: Float)+ , testElt double (undefined :: Double)+ ]+ where+ test_zip xs ys = run opt (Acc.zip (use xs) (use ys)) .==. zipWithRef (,) xs ys+ test_plus xs ys = run opt (Acc.zipWith (+) (use xs) (use ys)) .==. zipWithRef (+) xs ys+ test_min xs ys = run opt (Acc.zipWith Acc.min (use xs) (use ys)) .==. zipWithRef P.min xs ys++ testElt :: forall a. (Elt a, IsNum a, Ord a, Similar a, Arbitrary a)+ => (Options :-> Bool)+ -> a+ -> Maybe Test+ testElt ok _+ | P.not (get ok opt) = Nothing+ | otherwise = Just $ testGroup (show (typeOf (undefined :: a)))+ [ testDim dim0+ , testDim dim1+ , testDim dim2+ ]+ where+ testDim :: forall sh. (Shape sh, Eq sh, Arbitrary sh, Arbitrary (Array sh a)) => sh -> Test+ testDim sh = testGroup ("DIM" ++ show (dim sh))+ [ testProperty "zip" (test_zip :: Array sh a -> Array sh a -> Property)+ , testProperty "plus" (test_plus :: Array sh a -> Array sh a -> Property)+ , testProperty "min" (test_min :: Array sh a -> Array sh a -> Property)+ ]+++-- Reference Implementation+-- ------------------------++mapRef :: (Shape sh, Elt b) => (a -> b) -> Array sh a -> Array sh b+mapRef f xs+ = fromList (arrayShape xs)+ $ P.map f+ $ toList xs++zipWithRef :: (Shape sh, Elt c) => (a -> b -> c) -> Array sh a -> Array sh b -> Array sh c+zipWithRef f xs ys =+ let shx = fromElt (arrayShape xs)+ shy = fromElt (arrayShape ys)+ sh = toElt (R.intersect shx shy)+ in+ newArray sh (\ix -> f (xs Sugar.! ix) (ys Sugar.! ix))+
+ examples/quickcheck/Test/PrefixSum.hs view
@@ -0,0 +1,105 @@+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Test.PrefixSum where++import Prelude as P hiding ( sum )+import Test.QuickCheck+import Data.Label+import Data.Maybe+import Data.Typeable+import Test.Framework+import Test.Framework.Providers.QuickCheck2++import Config+import Test.Base+import Arbitrary.Array ()+import Data.Array.Accelerate as Acc+++--+-- prefix sum ------------------------------------------------------------------+--++test_prefixsum :: Options -> Test+test_prefixsum opt = testGroup "prefix sum" $ catMaybes+ [ testElt int8 (undefined :: Int8)+ , testElt int16 (undefined :: Int16)+ , testElt int32 (undefined :: Int32)+ , testElt int64 (undefined :: Int64)+ , testElt int8 (undefined :: Word8)+ , testElt int16 (undefined :: Word16)+ , testElt int32 (undefined :: Word32)+ , testElt int64 (undefined :: Word64)+ , testElt float (undefined :: Float)+ , testElt double (undefined :: Double)+ ]+ where+ testElt :: forall e. (Elt e, IsNum e, Ord e, Similar e, Arbitrary e) => (Options :-> Bool) -> e -> Maybe Test+ testElt ok _+ | P.not (get ok opt) = Nothing+ | otherwise = Just $ testGroup (show (typeOf (undefined :: e)))+ [ testProperty "scanl" (test_scanl :: Vector e -> Property)+ , testProperty "scanl'" (test_scanl' :: Vector e -> Property)+ , testProperty "scanl1" (test_scanl1 :: Vector e -> Property)+ , testProperty "scanr" (test_scanr :: Vector e -> Property)+ , testProperty "scanr'" (test_scanr' :: Vector e -> Property)+ , testProperty "scanr1" (test_scanr1 :: Vector e -> Property)+ ]++ -- left scan+ --+ test_scanl xs = run opt (Acc.scanl (+) 0 (use xs)) .==. scanlRef (+) 0 xs+ test_scanl1 xs = run opt (Acc.scanl1 Acc.min (use xs)) .==. scanl1Ref P.min xs+ test_scanl' xs =+ let (vec, sum) = Acc.scanl' (+) 0 (use xs)+ in (run opt vec, run opt sum) .==. scanl'Ref (+) 0 xs++ -- right scan+ --+ test_scanr xs = run opt (Acc.scanr (+) 0 (use xs)) .==. scanrRef (+) 0 xs+ test_scanr1 xs = run opt (Acc.scanr1 Acc.max (use xs)) .==. scanr1Ref P.max xs+ test_scanr' xs =+ let (vec, sum) = Acc.scanr' (+) 0 (use xs)+ in (run opt vec, run opt sum) .==. scanr'Ref (+) 0 xs++++-- Reference implementation+-- ------------------------++scanlRef :: Elt e => (e -> e -> e) -> e -> Vector e -> Vector e+scanlRef f z vec =+ let (Z :. n) = arrayShape vec+ in Acc.fromList (Z :. n+1) . P.scanl f z . Acc.toList $ vec++scanl'Ref :: Elt e => (e -> e -> e) -> e -> Vector e -> (Vector e, Scalar e)+scanl'Ref f z vec =+ let (Z :. n) = arrayShape vec+ result = P.scanl f z (Acc.toList vec)+ in (Acc.fromList (Z :. n) result, Acc.fromList Z (P.drop n result))++scanl1Ref :: Elt e => (e -> e -> e) -> Vector e -> Vector e+scanl1Ref f vec+ = Acc.fromList (arrayShape vec)+ . P.scanl1 f+ . Acc.toList $ vec++scanrRef :: Elt e => (e -> e -> e) -> e -> Vector e -> Vector e+scanrRef f z vec =+ let (Z :. n) = arrayShape vec+ in Acc.fromList (Z :. n+1) . P.scanr f z . Acc.toList $ vec++scanr'Ref :: Elt e => (e -> e -> e) -> e -> Vector e -> (Vector e, Scalar e)+scanr'Ref f z vec =+ let (Z :. n) = arrayShape vec+ result = P.scanr f z (Acc.toList vec)+ in (Acc.fromList (Z :. n) (P.tail result), Acc.fromList Z result)++scanr1Ref :: Elt e => (e -> e -> e) -> Vector e -> Vector e+scanr1Ref f vec+ = Acc.fromList (arrayShape vec)+ . P.scanr1 f+ . Acc.toList $ vec+
+ examples/quickcheck/Test/Reduction.hs view
@@ -0,0 +1,225 @@+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Test.Reduction where++import Prelude as P+import Data.List+import Data.Label+import Data.Maybe+import Data.Typeable+import Test.QuickCheck+import Test.Framework+import Test.Framework.Providers.QuickCheck2++import Config+import Test.Base+import Arbitrary.Array+import Data.Array.Accelerate as Acc+import Data.Array.Accelerate.Array.Sugar as Sugar++++--+-- Reduction -------------------------------------------------------------------+--++-- foldAll+-- -------++test_foldAll :: Options -> Test+test_foldAll opt = testGroup "foldAll" $ catMaybes+ [ testElt int8 (undefined :: Int8)+ , testElt int16 (undefined :: Int16)+ , testElt int32 (undefined :: Int32)+ , testElt int64 (undefined :: Int64)+ , testElt int8 (undefined :: Word8)+ , testElt int16 (undefined :: Word16)+ , testElt int32 (undefined :: Word32)+ , testElt int64 (undefined :: Word64)+ , testElt float (undefined :: Float)+ , testElt double (undefined :: Double)+ ]+ where+ testElt :: forall e. (Elt e, IsNum e, Ord e, Similar e, Arbitrary e) => (Options :-> Bool) -> e -> Maybe Test+ testElt ok _+ | P.not (get ok opt) = Nothing+ | otherwise = Just $ testGroup (show (typeOf (undefined :: e)))+ [ testDim dim0+ , testDim dim1+ , testDim dim2+ ]+ where+ testDim :: forall sh. (Shape sh, Arbitrary sh, Arbitrary (Array sh e)) => sh -> Test+ testDim sh = testGroup ("DIM" ++ show (dim sh))+ [+ testProperty "sum" (test_sum :: Array sh e -> Property)+ , testProperty "non-neutral sum" (test_sum' :: Array sh e -> e -> Property)+ , testProperty "minimum" (test_min :: Array sh e -> Property)+ , testProperty "maximum" (test_max :: Array sh e -> Property)+ ]+ --+ -- The tests+ --+ test_min xs+ = arraySize (arrayShape xs) > 0+ ==> run opt (Acc.fold1All Acc.min (use xs)) .==. fold1AllRef P.min xs++ test_max xs+ = arraySize (arrayShape xs) > 0+ ==> run opt (Acc.fold1All Acc.max (use xs)) .==. fold1AllRef P.max xs++ test_sum xs = run opt (Acc.foldAll (+) 0 (use xs)) .==. foldAllRef (+) 0 xs+ test_sum' xs z =+ let z' = unit (constant z)+ in run opt (Acc.foldAll (+) (the z') (use xs)) .==. foldAllRef (+) z xs++++-- multidimensional fold+-- ---------------------++test_fold :: Options -> Test+test_fold opt = testGroup "fold" $ catMaybes+ [ testElt int8 (undefined :: Int8)+ , testElt int16 (undefined :: Int16)+ , testElt int32 (undefined :: Int32)+ , testElt int64 (undefined :: Int64)+ , testElt int8 (undefined :: Word8)+ , testElt int16 (undefined :: Word16)+ , testElt int32 (undefined :: Word32)+ , testElt int64 (undefined :: Word64)+ , testElt float (undefined :: Float)+ , testElt double (undefined :: Double)+ ]+ where+ testElt :: forall e. (Elt e, IsNum e, Ord e, Similar e, Arbitrary e) => (Options :-> Bool) -> e -> Maybe Test+ testElt ok _+ | P.not (get ok opt) = Nothing+ | otherwise = Just $ testGroup (show (typeOf (undefined :: e)))+ [ testDim dim1+ , testDim dim2+ ]+ where+ testDim :: forall sh. (Shape sh, Eq sh, Arbitrary sh, Arbitrary (Array (sh:.Int) e)) => (sh:.Int) -> Test+ testDim sh = testGroup ("DIM" ++ show (dim sh))+ [+ testProperty "sum" (test_sum :: Array (sh :. Int) e -> Property)+ , testProperty "non-neutral sum" (test_sum' :: Array (sh :. Int) e -> e -> Property)+ , testProperty "minimum" (test_min :: Array (sh :. Int) e -> Property)+ , testProperty "maximum" (test_max :: Array (sh :. Int) e -> Property)+ ]+ --+ -- The tests+ --+ test_min xs+ = indexHead (arrayShape xs) > 0+ ==> run opt (Acc.fold1 Acc.min (use xs)) .==. fold1Ref P.min xs++ test_max xs+ = indexHead (arrayShape xs) > 0+ ==> run opt (Acc.fold1 Acc.max (use xs)) .==. fold1Ref P.max xs++ test_sum xs = run opt (Acc.fold (+) 0 (use xs)) .==. foldRef (+) 0 xs+ test_sum' xs z =+ let z' = unit (constant z)+ in run opt (Acc.fold (+) (the z') (use xs)) .==. foldRef (+) z xs+++-- segmented fold+-- --------------++test_foldSeg :: Options -> Test+test_foldSeg opt = testGroup "foldSeg" $ catMaybes+ [ testElt int8 (undefined :: Int8)+ , testElt int16 (undefined :: Int16)+ , testElt int32 (undefined :: Int32)+ , testElt int64 (undefined :: Int64)+ , testElt int8 (undefined :: Word8)+ , testElt int16 (undefined :: Word16)+ , testElt int32 (undefined :: Word32)+ , testElt int64 (undefined :: Word64)+ , testElt float (undefined :: Float)+ , testElt double (undefined :: Double)+ ]+ where+ testElt :: forall e. (Elt e, IsNum e, Ord e, Similar e, Arbitrary e) => (Options :-> Bool) -> e -> Maybe Test+ testElt ok _+ | P.not (get ok opt) = Nothing+ | otherwise = Just $ testGroup (show (typeOf (undefined :: e)))+ [ testDim dim1+ , testDim dim2+ ]+ where+ testDim :: forall sh. (Shape sh, Eq sh, Arbitrary sh, Arbitrary (Array (sh:.Int) e)) => (sh:.Int) -> Test+ testDim sh = testGroup ("DIM" ++ show (dim sh))+ [+ testProperty "sum"+ $ forAll arbitrarySegments $ \(seg :: Segments Int32) ->+ forAll (arbitrarySegmentedArray seg) $ \(xs :: Array (sh:.Int) e) ->+ run opt (Acc.foldSeg (+) 0 (use xs) (use seg)) .==. foldSegRef (+) 0 xs seg++ , testProperty "non-neutral sum"+ $ forAll arbitrarySegments $ \(seg :: Segments Int32) ->+ forAll (arbitrarySegmentedArray seg) $ \(xs :: Array (sh:.Int) e) ->+ forAll arbitrary $ \z ->+ let z' = unit (constant z)+ in run opt (Acc.foldSeg (+) (the z') (use xs) (use seg)) .==. foldSegRef (+) z xs seg++ , testProperty "minimum"+ $ forAll arbitrarySegments1 $ \(seg :: Segments Int32) ->+ forAll (arbitrarySegmentedArray seg) $ \(xs :: Array (sh:.Int) e) ->+ run opt (Acc.fold1Seg Acc.min (use xs) (use seg)) .==. fold1SegRef P.min xs seg+ ]+++-- Reference implementation+-- ------------------------++foldAllRef :: Elt e => (e -> e -> e) -> e -> Array sh e -> Array Z e+foldAllRef f z+ = Acc.fromList Z+ . return+ . foldl f z+ . Acc.toList++fold1AllRef :: Elt e => (e -> e -> e) -> Array sh e -> Array Z e+fold1AllRef f+ = Acc.fromList Z+ . return+ . foldl1 f+ . Acc.toList++foldRef :: (Shape sh, Elt e) => (e -> e -> e) -> e -> Array (sh :. Int) e -> Array sh e+foldRef f z arr =+ let (sh :. n) = arrayShape arr+ in fromList sh [ foldl f z sub | sub <- splitEvery n (toList arr) ]++fold1Ref :: (Shape sh, Elt e) => (e -> e -> e) -> Array (sh :. Int) e -> Array sh e+fold1Ref f arr =+ let (sh :. n) = arrayShape arr+ in fromList sh [ foldl1 f sub | sub <- splitEvery n (toList arr) ]++foldSegRef :: (Shape sh, Elt e, Elt i, Integral i) => (e -> e -> e) -> e -> Array (sh :. Int) e -> Segments i -> Array (sh :. Int) e+foldSegRef f z arr seg = fromList (sh :. sz) $ concat [ foldseg sub | sub <- splitEvery n (toList arr) ]+ where+ (sh :. n) = arrayShape arr+ (Z :. sz) = arrayShape seg+ seg' = toList seg+ foldseg xs = P.map (foldl' f z) (split seg' xs)++fold1SegRef :: (Shape sh, Elt e, Elt i, Integral i) => (e -> e -> e) -> Array (sh :. Int) e -> Segments i -> Array (sh :. Int) e+fold1SegRef f arr seg = fromList (sh :. sz) $ concat [ foldseg sub | sub <- splitEvery n (toList arr) ]+ where+ (sh :. n) = arrayShape arr+ (Z :. sz) = arrayShape seg+ seg' = toList seg+ foldseg xs = P.map (foldl1' f) (split seg' xs)++split :: Integral i => [i] -> [a] -> [[a]]+split [] _ = []+split (i:is) vs =+ let (h,t) = splitAt (P.fromIntegral i) vs+ in h : split is t+
+ examples/tests/Benchmark.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE FlexibleContexts #-}+{-# OPTIONS_GHC -fno-warn-orphans #-}++module Benchmark where++import Data.Array.IArray+import Data.Array.Unboxed (UArray)++import Data.List+import Data.Monoid+import Criterion+import Criterion.IO+import Criterion.Config+import Criterion.Main+import Criterion.Monad+import Criterion.Types+import Criterion.Environment+import Control.Monad+import Control.Monad.Trans (liftIO)+import Control.DeepSeq+import System.IO+import System.Directory+import System.Environment+++instance (Ix dim, IArray UArray e) => NFData (UArray dim e) where+ rnf a = a ! head (indices a) `seq` ()+++-- Much like defaultMain, but we ignore any non-flag command line arguments,+-- which we take as the inputs to the program itself (returned via getArg')+--+runBenchmark :: [Benchmark] -> IO ()+runBenchmark = runBenchmarkWith defaultConfig (return ())++runBenchmarkWith :: Config -> Criterion () -> [Benchmark] -> IO ()+runBenchmarkWith defCfg prep bs = do+ (cfg, _) <- parseArgs defCfg defaultOptions =<< getArgs+ withConfig cfg $+ if cfgPrintExit cfg == List+ then do+ _ <- note "Benchmarks:\n"+ mapM_ (note " %s\n") (sort $ concatMap benchNames bs)+ else do+ case getLast $ cfgSummaryFile cfg of+ Just fn -> liftIO $ writeFileOnce fn "Name,Mean,MeanLB,MeanUB,Stddev,StddevLB,StddevUB\n"+ Nothing -> return ()+ env <- measureEnvironment+ let shouldRun = const True+ prep+ runAndAnalyse shouldRun env $ BenchGroup "" bs++writeFileOnce :: FilePath -> String -> IO ()+writeFileOnce fn line = do+ exists <- doesFileExist fn+ size <- withFile fn ReadWriteMode hFileSize+ unless (exists && size > 0) $ writeFile fn line+
+ examples/tests/Config.hs view
@@ -0,0 +1,191 @@+{-# LANGUAGE CPP, DeriveDataTypeable #-}++module Config where++import Data.Version+import Text.PrettyPrint+import System.Console.CmdArgs+import Paths_accelerate_examples++import Data.Array.Accelerate ( Arrays, Acc )+import qualified Data.Array.Accelerate.Interpreter as Interpreter++-- -----------------------------------------------------------------------------+-- [NOTE: Adding backend support]+--+-- To add support for additional Accelerate backends:+--+-- 1. Edit the cabal file so that the backend can be optionally included via+-- CPP macros, as has been done for the CUDA backend. Add the appropriate+-- import statement below.+--+-- 2. Add a new constructor to the 'Backend' data type, and add this case to+-- the 'backend' dispatch function. This function is called to evaluate an+-- Accelerate expression.+--+-- 3. Add the new constructor to the 'cfgBackend' list in 'defaultConfig'.+-- This will make the backend appear in the command-line options.+--+#ifdef ACCELERATE_CUDA_BACKEND+import qualified Data.Array.Accelerate.CUDA as CUDA+#endif++#ifdef ACCELERATE_OPENCL_BACKEND+import qualified Data.Array.Accelerate.OpenCL as OpenCL+#endif++-- The Accelerate backends available to test, which should be no larger than the+-- build configuration for the Accelerate library itself.+--+data Backend+ = Interpreter+#ifdef ACCELERATE_CUDA_BACKEND+ | CUDA+#endif+#ifdef ACCELERATE_OPENCL_BACKEND+ | OpenCL+#endif+ deriving (Show, Data, Typeable)+++-- How to evaluate Accelerate programs with the chosen backend?+--+backend :: Arrays a => Config -> Acc a -> a+backend cfg =+ case cfgBackend cfg of+ Interpreter -> Interpreter.run+#ifdef ACCELERATE_CUDA_BACKEND+ CUDA -> CUDA.run+#endif+#ifdef ACCELERATE_OPENCL_BACKEND+ OpenCL -> OpenCL.run+#endif++--+-- -----------------------------------------------------------------------------+--++-- Program configuration options+--+data Config = Config+ {+ -- common options+ cfgBackend :: Backend+ , cfgVerify :: Bool+ , cfgElements :: Int+ , cfgImage :: Maybe FilePath+ , cfgMatrix :: Maybe FilePath++ -- criterion hooks+ , cfgPerformGC :: Bool+ , cfgConfidence :: Maybe Double+ , cfgResamples :: Maybe Int+ , cfgSummaryFile :: Maybe FilePath++ -- names of tests to run (all non-option arguments)+ , cfgArgs :: [String]+ }+ deriving (Show, Data, Typeable)+++-- With list of (name,description) pairs for the available tests+--+defaultConfig :: [(String,String)] -> Config+defaultConfig testPrograms =+ let numElements = 100000+ in Config+ {+ cfgBackend = enum+ [ Interpreter+ &= help "Reference implementation (sequential)"+#ifdef ACCELERATE_CUDA_BACKEND+ , CUDA+ &= explicit+ &= name "cuda"+ &= help "Implementation for NVIDIA GPUs (parallel)"+#endif+#ifdef ACCELERATE_OPENCL_BACKEND+ , OpenCL+ &= explicit+ &= name "opencl"+ &= help "Implementation for OpenCL (parallel)"+#endif++ ]++ , cfgVerify = def+ &= explicit+ &= name "k"+ &= name "verify"+ &= help "Only verify examples, do not run timing tests"++ , cfgElements = numElements+ &= explicit+ &= name "n"+ &= name "size"+ &= help ("Canonical test data size (" ++ shows numElements ")")++ , cfgImage = def+ &= explicit+ &= name "i"+ &= name "image"+ &= help "PGM image file to use for image-processing tests"+ &= typFile++ , cfgMatrix = def+ &= name "m"+ &= name "matrix"+ &= explicit+ &= help "MatrixMarket file to use for SMVM test"+ &= typFile++ , cfgPerformGC = enum+ [ False+ &= name "G"+ &= name "no-gc"+ &= explicit+ &= help "Do not collect garbage between iterations"+ , True+ &= name "g"+ &= name "gc"+ &= explicit+ &= help "Collect garbage between iterations"+ ]++ , cfgConfidence = def+ &= explicit+ &= name "I"+ &= name "ci"+ &= help "Bootstrap confidence interval"+ &= typ "CI"++ , cfgResamples = def+ &= explicit+ &= name "s"+ &= name "resamples"+ &= help "Number of bootstrap resamples to perform"++ , cfgSummaryFile = def+ &= name "u"+ &= name "summary"+ &= explicit+ &= help "Produce a summary CSV file of all results"+ &= typFile++ , cfgArgs = def+ &= args+ &= typ "TESTS"+ }+ &= program "accelerate-examples"+ &= summary "accelerate-examples (c) 2011 The Accelerate Team"+ &= versionArg [summary $ "accelerate-examples-" ++ showVersion version]+ &= verbosityArgs [help "Print more output"] [help "Print less output"]+ &= details (+ [ "Available tests, by prefix match:"+ , " <default> run all tests"+ ]+ +++ map (\(n,d) -> render . nest 2 $ text n $$ nest 22 (text d)) testPrograms)+ --+ -- magic number to make the second columns of the help text align+
+ examples/tests/Main.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE TupleSections #-}++module Main where++import Test+import Config+import Benchmark++import Prelude hiding (catch)+import Data.List+import Data.Maybe+import Control.Arrow+import Control.Monad+import System.Environment+import System.Console.CmdArgs (cmdArgs, whenNormal, getVerbosity, Verbosity(..))+++-- Process command line options, prepare selected test programs for benchmarking+-- or verification+--+processArgs :: IO (Config, [Test])+processArgs = do+ testInfo <- map (title &&& description) `fmap` allTests undefined+ config <- cmdArgs $ defaultConfig testInfo+ tests <- filter (selected config) `fmap` allTests config+ --+ return (config, tests)+ where+ selected a = case cfgArgs a of+ [] -> const True+ ps -> \x -> any (\p -> p `isPrefixOf` title x) ps+++-- Verify results with the chosen backend, turning exceptions into failures.+-- Pass back the tests which succeeded.+--+runVerify :: Config -> [Test] -> IO [Test]+runVerify cfg tests = do+ results <- forM tests $ \t -> (t,) `fmap` verifyTest cfg t+ return . map fst+ $ filter (\(_,r) -> r `elem` [Ok, Skipped]) results+++-- Run criterion timing tests in the chosen backend+--+runTiming :: Config -> [Test] -> IO ()+runTiming cfg tests = do+ verbose <- getVerbosity+ unless (verbose == Quiet) $ putStrLn ""+ let args = [ maybe "" (\ci -> "--ci=" ++ show ci) (cfgConfidence cfg)+ , maybe "" (\r -> "--resamples=" ++ show r) (cfgResamples cfg)+ , maybe "" (\f -> "--summary=" ++ f) (cfgSummaryFile cfg)+ , if cfgPerformGC cfg then "-g" else "-G"+ , case verbose of+ Loud -> "--verbose"+ Quiet -> "--quiet"+ Normal -> ""+ ]+ --+ withArgs args+ . runBenchmark+ . catMaybes+ $ map (benchmarkTest cfg) tests+++-- Main+-- ====++main :: IO ()+main = do+ (config, tests) <- processArgs+ whenNormal . putStrLn $+ unlines ["running with " ++ shows (cfgBackend config) " backend"+ ,"to display available options, rerun with '--help'"+ ]+ valid <- runVerify config tests+ --+ unless (null valid || cfgVerify config) $ runTiming config valid
+ examples/tests/Random.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE BangPatterns, FlexibleContexts #-}++module Random where++import System.Random.MWC+import Data.Array.IArray+import Data.Array.Unboxed (UArray)+import Data.Array.IO (MArray, IOUArray)+import Control.Exception (evaluate)+import Data.Array.Accelerate (Z(..),(:.)(..))+import qualified Data.Vector.Generic as G+import qualified Data.Vector.Generic.Mutable as GM+import qualified Data.Array.MArray as M+import qualified Data.Array.Unsafe as U+import qualified Data.Array.Accelerate as Acc+++-- Convert an Unboxed Data.Array to an Accelerate Array+--+convertUArray :: (IArray UArray e, Acc.Elt e) => UArray Int e -> IO (Acc.Vector e)+convertUArray v =+ let arr = Acc.fromIArray v+ in evaluate (arr `Acc.indexArray` (Z:.0)) >> return arr+++-- Convert a Data.Vector to an Accelerate Array+--+convertVector+ :: (IArray UArray a, MArray IOUArray a IO, G.Vector v a, Acc.Elt a)+ => v a+ -> IO (Acc.Vector a)++convertVector vec = do+ arr <- Acc.fromIArray `fmap` toIArray vec+ evaluate (arr `Acc.indexArray` (Z:.0)) >> return arr+ where+ toIArray :: (MArray IOUArray a IO, IArray UArray a, G.Vector v a) => v a -> IO (UArray Int a)+ toIArray v = do+ let n = G.length v+ mu <- M.newArray_ (0,n-1) :: MArray IOUArray a IO => IO (IOUArray Int a)+ let go !i | i < n = M.writeArray mu i (G.unsafeIndex v i) >> go (i+1)+ | otherwise = U.unsafeFreeze mu+ go 0+++-- Generate a random, uniformly distributed vector of specified size over the+-- range. For integral types the range is inclusive, for floating point numbers+-- the range (a,b] is used, if one ignores rounding errors.+--+randomUArrayR+ :: (Variate a, MArray IOUArray a IO, IArray UArray a)+ => (a,a)+ -> GenIO+ -> Int+ -> IO (UArray Int a)++randomUArrayR lim gen n = do+ mu <- M.newArray_ (0,n-1) :: MArray IOUArray e IO => IO (IOUArray Int e)+ let go !i | i < n = uniformR lim gen >>= M.writeArray mu i >> go (i+1)+ | otherwise = U.unsafeFreeze mu+ go 0+++-- Generate a uniformly distributed Data.Vector of specified range and size+--+randomVectorR :: (G.Vector v a, Variate a) => (a,a) -> GenIO -> Int -> IO (v a)+randomVectorR lim gen n = do+ mu <- GM.unsafeNew n+ let go !i | i < n = uniformR lim gen >>= GM.unsafeWrite mu i >> go (i+1)+ | otherwise = G.unsafeFreeze mu+ go 0++
+ examples/tests/Test.hs view
@@ -0,0 +1,237 @@+{-# LANGUAGE CPP, ExistentialQuantification #-}++module Test (++ Title, Description, Test(..), Status(..),+ allTests, verifyTest, benchmarkTest++) where++-- individual test implementations+import qualified Map+import qualified Zip+import qualified ZipWith+import qualified Fold+import qualified FoldSeg+import qualified ScanSeg+import qualified Stencil+import qualified Stencil2+import qualified Permute+import qualified Backpermute+import qualified Vector+import qualified Gather+import qualified Scatter++import qualified SASUM+import qualified SAXPY+import qualified DotP+import qualified Filter+import qualified SMVM+import qualified BlackScholes+import qualified Radix+import qualified SliceExamples++#ifdef ACCELERATE_IO+import qualified BlockCopy+import qualified VectorCopy () -- FIXME: Need to add tests from here+#endif++import qualified Canny+import qualified IntegralImage+import qualified SharingRecovery++-- friends+import Util+import Config+import Validate++-- libraries+import Prelude hiding (catch)+import Criterion (Benchmark, bench, whnf)+import Data.Maybe+import Data.Array.IArray+import Control.Exception+import System.IO+import System.IO.Unsafe+import System.Console.CmdArgs (getVerbosity, Verbosity(..))++import Data.Array.Accelerate (Acc)+import qualified Data.Array.Accelerate as Acc+++data Status+ = Ok+ | Skipped+ | Failed String++instance Eq Status where+ Ok == Ok = True+ Skipped == Skipped = True+ _ == _ = False++instance Show Status where+ show Ok = "Ok"+ show Skipped = "Skipped"+ show (Failed s) = "Failed: " ++ s+++type Title = String+type Description = String++data Test+ -- A cannonical test program, where we have a reference implementation that+ -- the Accelerate program must match. The 'convert' field is slightly magic:+ -- we need to carry it around as a proof that ELtRepr sh ~ EltRepr ix.+ --+ = forall array ix sh e. (Similar e, Acc.Elt e, Acc.Shape sh, Show ix, Show e, IArray array e, Ix ix) => Test+ { title :: Title+ , description :: Description+ , reference :: () -> array ix e+ , accelerate :: () -> Acc (Acc.Array sh e)+ , convert :: Acc.Array sh e -> array ix e+ }++ -- No reference implementation, so the result can not be validated, but we can+ -- check that no exceptions are thrown, and benchmark the operation.+ --+ | forall sh e. (Acc.Elt e, Acc.Shape sh) => TestNoRef+ { title :: Title+ , description :: Description+ , accelerate :: () -> Acc (Acc.Array sh e)+ }++ -- An IO action. Run once to verify that no exceptions are thrown, do not+ -- benchmark.+ --+ | forall a. TestIO+ { title :: Title+ , description :: Description+ , action :: IO a+ }+++allTests :: Config -> IO [Test]+allTests cfg = sequence'+ [++ -- primitive functions+ mkTest "map-abs" "absolute value of each element" $ Map.run "abs" n+ , mkTest "map-plus" "add a constant to each element" $ Map.run "plus" n+ , mkTest "map-square" "square of each element" $ Map.run "square" n+ , mkTest "zip" "vector zip" $ Zip.run n+ , mkTest "zipWith-plus" "element-wise addition" $ ZipWith.run "plus" n+ , mkTest "fold-sum" "vector reduction: fold (+) 0" $ Fold.run "sum" n+ , mkTest "fold-product" "vector product: fold (*) 1" $ Fold.run "product" n+ , mkTest "fold-maximum" "maximum of a vector: fold1 max" $ Fold.run "maximum" n+ , mkTest "fold-minimum" "minimum of a vector: fold1 min" $ Fold.run "minimum" n+ , mkTest "fold-2d-sum" "reduction along innermost matrix dimension" $ Fold.run2d "sum-2d" n+ , mkTest "fold-2d-product" "product along innermost matrix dimension" $ Fold.run2d "product-2d" n+ , mkTest "fold-2d-maximum" "maximum along innermost matrix dimension" $ Fold.run2d "maximum-2d" n+ , mkTest "fold-2d-minimum" "minimum along innermost matrix dimension" $ Fold.run2d "minimum-2d" n+ , mkTest "foldseg-sum" "segmented vector reduction" $ FoldSeg.run "sum" n+ , mkTest "scanseg-sum" "segmented vector prescanl (+) 0" $ ScanSeg.run "sum" n+ , mkTest "stencil-1D" "3-element vector" $ Stencil.run "1D" n+ , mkTest "stencil-2D" "3x3 pattern" $ Stencil.run2D "2D" n+ , mkTest "stencil-3D" "3x3x3 pattern" $ Stencil.run3D "3D" n+ , mkTest "stencil-3x3-cross" "3x3 cross pattern" $ Stencil.run2D "3x3-cross" n+ , mkTest "stencil-3x3-pair" "3x3 non-symmetric pattern with pairs" $ Stencil.run2D "3x3-pair" n+ , mkTest "stencil2-2D" "3x3 pattern" $ Stencil2.run2D "2D" n+ , mkTest "permute-hist" "histogram" $ Permute.run "histogram" n+ , mkTest "backpermute-reverse" "reverse a vector" $ Backpermute.run "reverse" n+ , mkTest "backpermute-transpose" "transpose a matrix" $ Backpermute.run2d "transpose" n+ , mkTest "init" "vector init" $ Vector.run "init" n+ , mkTest "tail" "vector tail" $ Vector.run "tail" n+ , mkTest "take" "vector take" $ Vector.run "take" n+ , mkTest "drop" "vector drop" $ Vector.run "drop" n+ , mkTest "slit" "vector slit" $ Vector.run "slit" n+ , mkTest "gather" "backpermute via index mapping vector" $ Gather.run "gather" n+ , mkTest "gather-if" "cond. backpermute via index mapping vector" $ Gather.run "gather-if" n+ , mkTest "scatter" "permute via index mapping vector" $ Scatter.run "scatter" n+ , mkTest "scatter-if" "cond. permute via index mapping vector" $ Scatter.run "scatter-if" n++ + -- simple examples+ , mkTest "sasum" "sum of absolute values" $ SASUM.run n+ , mkTest "saxpy" "scalar alpha*x + y" $ SAXPY.run n+ , mkTest "dotp" "vector dot-product" $ DotP.run n+ , mkTest "filter" "return elements that satisfy a predicate" $ Filter.run n+ , mkTest "smvm" "sparse-matrix vector multiplication" $ SMVM.run (cfgMatrix cfg)+ , mkTest "black-scholes" "Black-Scholes option pricing" $ BlackScholes.run n+ , mkTest "radixsort" "radix sort" $ Radix.run n++#ifdef ACCELERATE_IO+ -- Array IO+ , mkIO "io" "array IO test" $ BlockCopy.run+#endif++ -- image processing+ , mkNoRef "canny" "canny edge detection" $ Canny.run img+ , mkNoRef "integral-image" "image integral (2D scan)" $ IntegralImage.run img+ -- slices+ , mkTest "slices" "replicate (Z:.2:.All:.All)" $ SliceExamples.run1+ , mkTest "slices" "replicate (Z:.All:.2:.All)" $ SliceExamples.run2+ , mkTest "slices" "replicate (Z:.All:.All:.2)" $ SliceExamples.run3+ , mkTest "slices" "replicate (Any:.2)" $ SliceExamples.run4 + , mkTest "slices" "replicate (Z:.2:.2:.2)" $ SliceExamples.run5+ --+ , mkIO "sharing-recovery" "simple" $ return (show SharingRecovery.simple)+ , mkIO "sharing-recovery" "orderFail" $ return (show SharingRecovery.orderFail)+ , mkIO "sharing-recovery" "testSort" $ return (show SharingRecovery.testSort)+ , mkIO "sharing-recovery" "muchSharing" $ return (show $ SharingRecovery.muchSharing 20)+ , mkIO "sharing-recovery" "bfsFail" $ return (show SharingRecovery.bfsFail)+ , mkIO "sharing-recovery" "twoLetsSameLevel" $ return (show SharingRecovery.twoLetsSameLevel)+ , mkIO "sharing-recovery" "twoLetsSameLevel2" $ return (show SharingRecovery.twoLetsSameLevel2)+ , mkIO "sharing-recovery" "noLetAtTop" $ return (show SharingRecovery.noLetAtTop)+ , mkIO "sharing-recovery" "noLetAtTop2" $ return (show SharingRecovery.noLetAtTop2)+ , mkIO "sharing-recovery" "pipe" $ return (show SharingRecovery.pipe)+ --+ , mkIO "bound-variables" "stencil2" $ return (show Stencil2.varUse)+ ]+ where+ n = cfgElements cfg+ img = fromMaybe (error "no image file specified") (cfgImage cfg)+ --+ mkTest name desc builder = do+ ~(ref,acc) <- unsafeInterleaveIO builder -- must be super lazy+ return $ Test name desc ref acc Acc.toIArray++ mkNoRef name desc builder = do+ acc <- unsafeInterleaveIO builder+ return $ TestNoRef name desc acc++ mkIO name desc act = return $ TestIO name desc act+++-- Verify that the Accelerate and reference implementations yield the same+-- result in the chosen backend+--+verifyTest :: Config -> Test -> IO Status+verifyTest cfg test = do+ quiet <- (==Quiet) `fmap` getVerbosity+ verify quiet `catch` \e -> let r = Failed (show (e :: SomeException))+ in putStrLn (show r) >> return r+ where+ run acc = backend cfg $ acc ()+ verify quiet = do+ putStr (title test ++ ": ") >> hFlush stdout+ result <- case test of+ Test _ _ ref acc cvt ->+ return $ case validate (ref ()) (cvt $ run acc) of+ [] -> Ok+ errs -> Failed $+ if quiet then ("(" ++ show (length errs) ++ " differences)")+ else unlines . ("":) $ map (\(i,v) -> ">>> " ++ shows i " : " ++ show v) errs+ TestNoRef _ _ acc -> return $ run acc `seq` Ok+ TestIO _ _ act -> act >>= \v -> v `seq` return Ok+ --+ putStrLn (show result)+ return result+++-- Benchmark a test with Criterion+--+benchmarkTest :: Config -> Test -> Maybe Benchmark+benchmarkTest cfg (Test name _ _ acc _) = Just . bench name $ whnf (backend cfg . acc) ()+benchmarkTest cfg (TestNoRef name _ acc) = Just . bench name $ whnf (backend cfg . acc) ()+benchmarkTest _ (TestIO _ _ _) = Nothing+
+ examples/tests/Util.hs view
@@ -0,0 +1,20 @@++module Util where++import System.IO.Unsafe++-- Lazier version of 'Control.Monad.sequence'+--+sequence' :: [IO a] -> IO [a]+sequence' = foldr k (return [])+ where k m ms = do { x <- m; xs <- unsafeInterleaveIO ms; return (x:xs) }++mapM' :: (a -> IO b) -> [a] -> IO [b]+mapM' f xs = sequence' $ map f xs++forM' :: [a] -> (a -> IO b) -> IO [b]+forM' = flip mapM'++replicateM' :: Int -> IO a -> IO [a]+replicateM' n x = sequence' (replicate n x)+
+ examples/tests/Validate.hs view
@@ -0,0 +1,102 @@+{-# LANGUAGE FlexibleContexts, ParallelListComp #-}+{-# OPTIONS_GHC -fno-warn-unused-binds #-}++module Validate (Similar(..), validate, validate') where++import Data.Int+import Data.Word+import Data.Array.IArray+import Foreign.C.Types+import Foreign.Storable+import Control.Exception (assert)+import Unsafe.Coerce++class Similar a where+ sim :: a -> a -> Bool++instance Similar Int where sim = (==)+instance Similar Int8 where sim = (==)+instance Similar Int16 where sim = (==)+instance Similar Int32 where sim = (==)+instance Similar Int64 where sim = (==)+instance Similar Word where sim = (==)+instance Similar Word8 where sim = (==)+instance Similar Word16 where sim = (==)+instance Similar Word32 where sim = (==)+instance Similar Word64 where sim = (==)+instance Similar CShort where sim = (==)+instance Similar CUShort where sim = (==)+instance Similar CInt where sim = (==)+instance Similar CUInt where sim = (==)+instance Similar CLong where sim = (==)+instance Similar CULong where sim = (==)+instance Similar CLLong where sim = (==)+instance Similar CULLong where sim = (==)++instance Similar Bool where sim = (==)+instance Similar Char where sim = (==)+instance Similar CChar where sim = (==)+instance Similar CSChar where sim = (==)+instance Similar CUChar where sim = (==)++instance Similar Float where sim = absoluteOrRelative+instance Similar CFloat where sim = absoluteOrRelative+instance Similar Double where sim = absoluteOrRelative+instance Similar CDouble where sim = absoluteOrRelative++instance (Similar a, Similar b) => Similar (a,b) where+ (x,y) `sim` (u,v) = x `sim` u && y `sim` v++--+-- http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm+--++absoluteOrRelative :: (Fractional a, Ord a) => a -> a -> Bool+absoluteOrRelative u v+ | abs (u-v) < epsilonAbs = True+ | abs u > abs v = abs ((u-v) / u) < epsilonRel+ | otherwise = abs ((v-u) / v) < epsilonRel+ where+ epsilonRel = 0.001+ epsilonAbs = 0.00001+++-- Comparisons using lexicographically ordered floating-point numbers+-- reinterpreted as twos-complement integers.+--+lexicographic32 :: (Num a, Storable a) => Int -> a -> a -> Bool+lexicographic32 maxUlps a b+ = assert (sizeOf a == 4 && maxUlps > 0 && maxUlps < 4 * 1024 * 1024)+ $ intDiff < fromIntegral maxUlps+ where+ intDiff = abs (toInt a - toInt b)+ toInt x | x' < 0 = 0x80000000 - x'+ | otherwise = x'+ where x' = unsafeCoerce x :: Int32+++lexicographic64 :: (Num a, Storable a) => Int -> a -> a -> Bool+lexicographic64 maxUlps a b+ = assert (sizeOf a == 8 && maxUlps > 0 && maxUlps < 8 * 1024 * 1024)+ $ intDiff < fromIntegral maxUlps+ where+ intDiff = abs (toInt a - toInt b)+ toInt x | x' < 0 = 0x8000000000000000 - x'+ | otherwise = x'+ where x' = unsafeCoerce x :: Int64+++-- Compare two vectors element-wise for equality, for a given measure of+-- similarity. The index and values are returned for pairs that fail.+--+validate+ :: (IArray array e, Ix ix, Similar e)+ => array ix e+ -> array ix e+ -> [(ix,(e,e))]+validate ref arr = validate' (assocs ref) (elems arr)++validate' :: (Ix ix, Similar e) => [(ix,e)] -> [e] -> [(ix,(e,e))]+validate' ref arr =+ filter (not . uncurry sim . snd) [ (i,(x,y)) | (i,x) <- ref | y <- arr ]+
+ examples/tests/image-processing/Canny.hs view
@@ -0,0 +1,117 @@+{-# LANGUAGE TypeOperators #-}++module Canny where++import PGM++import Data.Array.Accelerate hiding (zipWith, unindex2)+import qualified Data.Array.Accelerate as Acc+++type Image a = Array DIM2 a+type Stencil7x1 a = (Stencil3 a, Stencil7 a, Stencil3 a)+type Stencil1x7 a = (Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a)+++convolve7x1 :: (Elt a, IsNum a) => [Exp a] -> Stencil7x1 a -> Exp a+convolve7x1 kernel (_, (a,b,c,d,e,f,g), _) =+ sum $ zipWith (*) kernel [a,b,c,d,e,f,g]++convolve1x7 :: (Elt a, IsNum a) => [Exp a] -> Stencil1x7 a -> Exp a+convolve1x7 kernel ((_,a,_), (_,b,_), (_,c,_), (_,d,_), (_,e,_), (_,f,_), (_,g,_)) =+ sum $ zipWith (*) kernel [a,b,c,d,e,f,g]+++-- Gaussian smoothing+--+gaussian :: (Elt a, IsFloating a) => [Exp a]+gaussian = [ 0.00442012927963+ , 0.05384819825462+ , 0.24133088157513+ , 0.39788735772974+ , 0.24133088157513+ , 0.05384819825462+ , 0.00442012927963 ]++gaussianX :: (Elt a, IsFloating a) => Acc (Image a) -> Acc (Image a)+gaussianX = stencil (convolve7x1 gaussian) (Constant 0)++gaussianY :: (Elt a, IsFloating a) => Acc (Image a) -> Acc (Image a)+gaussianY = stencil (convolve1x7 gaussian) (Constant 0)+++-- Gaussian derivative and gradient quantisation+--+gaussian' :: (Elt a, IsFloating a) => [Exp a]+gaussian' = [ 0.02121662054222+ , 0.17231423441479+ , 0.38612941052022+ , 0.0+ ,-0.38612941052022+ ,-0.17231423441479+ ,-0.02121662054222 ]++gradientX :: (Elt a, IsFloating a) => Acc (Image a) -> Acc (Image a)+gradientX = stencil (convolve7x1 gaussian') (Constant 0)++gradientY :: (Elt a, IsFloating a) => Acc (Image a) -> Acc (Image a)+gradientY = stencil (convolve1x7 gaussian') (Constant 0)++gradientMagnitude :: (Elt a, IsFloating a) => Acc (Image a) -> Acc (Image a) -> Acc (Image a)+gradientMagnitude = Acc.zipWith magdir+ where+ magdir dx dy = let mag = sqrt (dx*dx + dy*dy)+ -- dir = atan2 dy dx+ in mag -- lift (mag, dir)+++-- Non-maximum suppression+--+nonMaximumSuppression+ :: (Elt a, IsFloating a)+ => Exp a+ -> Acc (Image a)+ -> Acc (Image a)+ -> Acc (Image a)+ -> Acc (Image a)+nonMaximumSuppression threshold gradX gradY gradM =+ generate (shape gradX) $ \ix ->+ let dx = gradX ! ix+ dy = gradY ! ix+ mag = gradM ! ix+ alpha = 1.3065629648763766 -- 0.5 / sin (pi / 8.0)+ offsetx = Acc.round (alpha * dx / mag)+ offsety = Acc.round (alpha * dy / mag)+ --+ (m,n) = unindex2 (shape gradX)+ (x,y) = unindex2 ix+ fwd = gradM ! clamp (x+offsetx, y+offsety)+ rev = gradM ! clamp (x-offsetx, y-offsety)+ --+ unindex2 uv = let Z:.u:.v = unlift uv in (u,v)+ clamp (u,v) = lift (Z:. 0 `Acc.max` u `Acc.min` (m-1) :. 0 `Acc.max` v `Acc.min` (n-1))+ in+ (mag <* threshold ||* fwd >* mag ||* rev >* mag) ? (0, 1)+++-- Canny edge detection+--+canny :: (Elt a, IsFloating a) => Image a -> Acc (Image a)+canny img =+ let smooth = gaussianX . gaussianY $ use img+ gradX = gradientX smooth+ gradY = gradientY smooth+ gradMag = gradientMagnitude gradX gradY+ in+ nonMaximumSuppression 0.1 gradX gradY gradMag+++-- Main+-- ----++-- TLM: should compare to a pre-saved reference image+run :: FilePath -> IO (() -> Acc (Array DIM2 Float))+run file = do+ pgm <- readPGM file+ return (\() -> canny pgm)+
+ examples/tests/image-processing/IntegralImage.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE ScopedTypeVariables, TypeOperators #-}++module IntegralImage where++import PGM++import Data.Array.Accelerate as Acc+++-- |The value of each element in an integral image is the sum of all input elements+-- above and to the left, inclusive. It is calculated by performing an inclusive/post+-- scan from left-to-right then top-to-bottom.+--+integralImage :: (Elt a, IsNum a) => Array DIM2 a -> Acc (Array DIM2 a)+integralImage img = sumTable+ where+ -- scan rows+ rowArr = reshape (lift $ Z:.(w * h)) arr+ rowSegs = Acc.replicate (lift $ Z:.h) $ unit w+ rowSum = reshape (lift (Z:.w:.h)) $ Acc.scanl1Seg (+) rowArr rowSegs++ -- scan cols+ colArr = reshape (lift $ Z:.(h * w)) $ transpose2D rowSum+ colSegs = Acc.replicate (lift $ Z:.w) $ unit h+ colSum = reshape (lift (Z:.h:.w)) $ Acc.scanl1Seg (+) colArr colSegs++ -- transpose back+ sumTable = transpose2D colSum++ --+ arr = use img+ Z:.w:.h = unlift $ shape arr+++-- |Simple 2D matrix transpose.+--+transpose2D :: Elt a => Acc (Array DIM2 a) -> Acc (Array DIM2 a)+transpose2D arr = backpermute (swap $ shape arr) swap arr+ where+ swap = lift1 $ \(Z:.x:.y) -> Z:.y:.x :: Z :. Exp Int :. Exp Int+++-- Run integralImage over the input PGM+--+run :: FilePath -> IO (() -> Acc (Array DIM2 Float))+run file = do+ pgm <- readPGM file+ return (\() -> integralImage pgm)+
+ examples/tests/image-processing/PGM.hs view
@@ -0,0 +1,32 @@+--+-- Load a PGM file. MacOS X users might find the following quicklook plugin+-- useful for viewing PGM files:+--+-- http://code.google.com/p/quicklook-pfm/+--++module PGM where++import Control.Applicative+import Graphics.Pgm++import Prelude as P+import Data.Array.Accelerate as Acc+import Data.Array.Unboxed hiding (Array)+import qualified Data.ByteString as B+++-- Read an 8-bit PGM file, and marshal to an Accelerate array as floating-point+-- data in the range [0,1].+--+readPGM :: FilePath -> IO (Array DIM2 Float)+readPGM fp = do+ img <- either (error . show) head . pgmsToArrays <$> B.readFile fp :: IO (UArray (Int,Int) Word8)+ return . fromIArray $ amap (\x -> P.fromIntegral x / 255) img+++writePGM :: FilePath -> Array DIM2 Float -> IO ()+writePGM fp img =+ let arr = toIArray img :: UArray (Int,Int) Float+ in arrayToFile fp $ amap (\x -> P.round (255 * x)) arr+
+ examples/tests/io/BlockCopy.hs view
@@ -0,0 +1,91 @@+{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, TypeOperators #-}++module BlockCopy where++-- standard libraries+import Prelude as P+import Foreign.Ptr+import Foreign.C+import Control.Monad+import Control.Exception++-- friends+import Data.Array.Accelerate+import Data.Array.Accelerate.IO++assertEqual :: (Eq a, Show a) => String -> a -> a -> IO ()+assertEqual preface expected actual =+ unless (actual == expected) (throw $ AssertionFailed msg)+ where+ msg = (if null preface then "" else preface ++ "\n") +++ "expected: " ++ show expected ++ "\n but got: " ++ show actual++run :: IO ()+run =+ mapM_ (\(msg,act) -> putStrLn ("test: " ++ msg) >> act)+ [ ("fromPtr Int", testBlockCopyPrim)+ , ("fromPtr (Int,Double)", testBlockCopyTuples)+ , ("toPtr Int16", testBlockCopyFromArrayInt16)+ , ("toPtr Int32", testBlockCopyFromArrayInt32)+ , ("toPtr Int64", testBlockCopyFromArrayInt64)+ , ("fromArray Int", testBlockCopyFromArrayWithFunctions) ]+++testBlockCopyPrim :: IO ()+testBlockCopyPrim = do+ ptr <- oneToTen+ (arr :: Vector Int32) <- fromPtr (Z :. 10) ((), ptr)+ assertEqual "Not equal" [1..10] (toList arr)++testBlockCopyTuples :: IO ()+testBlockCopyTuples = do+ intPtr <- oneToTen+ doublePtr <- tenToOne+ (arr :: Vector (Int32, Double)) <- fromPtr (Z :. 10) (((), intPtr), doublePtr)+ assertEqual "Not equal" [ (x, P.fromIntegral (11 - x)) | x <- [1..10]] (toList arr)++testBlockCopyFromArrayWithFunctions :: IO ()+testBlockCopyFromArrayWithFunctions = do+ let n = 5^(3::Int)+ let (arr :: Array (Z:.Int:.Int:.Int) Int32) = fromList (Z:.5:.5:.5) [2*x | x <- [0..n-1]]+ ohi <- nInt32s (P.fromIntegral n)+ fromArray arr ((), memcpy ohi)+ b <- isFilledWithEvens32 ohi (P.fromIntegral n)+ assertEqual "Not equal" 1 b++testBlockCopyFromArrayInt16 :: IO ()+testBlockCopyFromArrayInt16 = do+ let n = 50+ let (arr :: Vector Int16) = fromList (Z:.n) [2 * P.fromIntegral x | x <- [0..n-1]]+ ohi <- nInt16s (P.fromIntegral n)+ toPtr arr ((), ohi)+ b <- isFilledWithEvens16 ohi (P.fromIntegral n)+ assertEqual "Not equal" 1 b++testBlockCopyFromArrayInt32 :: IO ()+testBlockCopyFromArrayInt32 = do+ let (arr :: Array (Z:.Int:.Int) Int32) = fromList (Z:.10:.10) [2*x | x <- [0..99]]+ ohi <- nInt32s 100+ toPtr arr ((), ohi)+ b <- isFilledWithEvens32 ohi 100+ assertEqual "Not equal" 1 b++testBlockCopyFromArrayInt64 :: IO ()+testBlockCopyFromArrayInt64 = do+ let n = 73+ let (arr :: Vector Int64) = fromList (Z:.n) [2 * P.fromIntegral x | x <- [0..n-1]]+ ohi <- nInt64s (P.fromIntegral n)+ toPtr arr ((), ohi)+ b <- isFilledWithEvens64 ohi (P.fromIntegral n)+ assertEqual "Not equal" 1 b++foreign import ccall "one_to_ten" oneToTen :: IO (Ptr Int32)+foreign import ccall "ten_to_one" tenToOne :: IO (Ptr Double)+foreign import ccall "n_int_16s" nInt16s :: CInt -> IO (Ptr Int16)+foreign import ccall "n_int_32s" nInt32s :: CInt -> IO (Ptr Int32)+foreign import ccall "n_int_64s" nInt64s :: CInt -> IO (Ptr Int64)+foreign import ccall "is_filled_with_evens_16" isFilledWithEvens16 :: Ptr Int16 -> CInt -> IO CInt+foreign import ccall "is_filled_with_evens_32" isFilledWithEvens32 :: Ptr Int32 -> CInt -> IO CInt+foreign import ccall "is_filled_with_evens_64" isFilledWithEvens64 :: Ptr Int64 -> CInt -> IO CInt+foreign import ccall memcpy :: Ptr a -> Ptr b -> Int -> IO ()+
+ examples/tests/io/VectorCopy.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE TemplateHaskell, TypeFamilies #-}++module VectorCopy where++import Data.Array.Accelerate hiding (fromList)+import Data.Array.Accelerate.Array.Sugar (EltRepr)+import Data.Array.Accelerate.IO++import Data.Vector.Storable++import Foreign++import Test.QuickCheck+import Test.QuickCheck.All+import Test.QuickCheck.Monadic++roundtrip :: ( Arbitrary a+ , Eq a+ , Elt a+ , Storable a+ , BlockPtrs (EltRepr a) ~ ((), Ptr a) )+ => [a] -> Property+roundtrip xs = monadicIO $ do+ let xsv = fromList xs+ xsarr <- run $ fromVectorIO xsv+ xsv' <- run $ toVectorIO xsarr+ assert (xsv == xsv')++unsaferoundtrip :: ( Arbitrary a+ , Eq a+ , Elt a+ , Storable a+ , BlockPtrs (EltRepr a) ~ ((), Ptr a) )+ => [a] -> Bool+unsaferoundtrip xs = xsv == (toVector (fromVector xsv))+ where xsv = fromList xs++prop_Int8_roundtrip :: [Int8] -> Property+prop_Int8_roundtrip = roundtrip+prop_Int8_unsaferoundtrip :: [Int8] -> Bool+prop_Int8_unsaferoundtrip = unsaferoundtrip++prop_Int16_roundtrip :: [Int16] -> Property+prop_Int16_roundtrip = roundtrip+prop_Int16_unsaferoundtrip :: [Int16] -> Bool+prop_Int16_unsaferoundtrip = unsaferoundtrip++prop_Int32_roundtrip :: [Int32] -> Property+prop_Int32_roundtrip = roundtrip+prop_Int32_unsaferoundtrip :: [Int32] -> Bool+prop_Int32_unsaferoundtrip = unsaferoundtrip++prop_Int64_roundtrip :: [Int64] -> Property+prop_Int64_roundtrip = roundtrip+prop_Int64_unsaferoundtrip :: [Int64] -> Bool+prop_Int64_unsaferoundtrip = unsaferoundtrip++prop_Int_roundtrip :: [Int] -> Property+prop_Int_roundtrip = roundtrip+prop_Int_unsaferoundtrip :: [Int] -> Bool+prop_Int_unsaferoundtrip = unsaferoundtrip++prop_Float_roundtrip :: [Float] -> Property+prop_Float_roundtrip = roundtrip+prop_Float_unsaferoundtrip :: [Float] -> Bool+prop_Float_unsaferoundtrip = unsaferoundtrip++prop_Double_roundtrip :: [Double] -> Property+prop_Double_roundtrip = roundtrip+prop_Double_unsaferoundtrip :: [Double] -> Bool+prop_Double_unsaferoundtrip = unsaferoundtrip++test :: IO Bool+test = $quickCheckAll
+ examples/tests/io/fill_with_values.cpp view
@@ -0,0 +1,81 @@+#include <stdio.h>+#include <stdlib.h>+#include <stdint.h>++/* Returns one if it's filled with even values starting at 0 */+template <typename T>+int is_filled_with_evens(T *p, int size) {+ T prev = 0;+ int result = 1; // default to true+ int i;++ if (p[0] != 0) {+ result = 0;+ }++ for (i=1; result && i < size; i++) {+ if (p[i] != prev + 2) {+ result = 0;+ }+ else {+ prev = p[i];+ }+ }++ return result;+}+++#ifdef __cplusplus+extern "C" {+#endif++int32_t *one_to_ten() {+ int32_t *p = (int32_t*) malloc(sizeof(int32_t) * 10);+ int i;+ for (i=0; i<10; i++) {+ p[i] = i+1;+ }+ return p;+}++double *ten_to_one() {+ double *p = (double*) malloc(sizeof(double) * 10);+ int i;+ for (i=0; i< 10; i++) {+ p[i] = 10.0 - (double) i;+ }+ return p;+}++int32_t *n_int_32s (int n) {+ return (int32_t*) malloc(sizeof(int32_t) * n);+}++int16_t *n_int_16s(int n) {+ return (int16_t*) malloc(sizeof(int16_t) * n);+}++int64_t *n_int_64s(int n) {+ return (int64_t*) malloc(sizeof(int64_t) * n);+}++int is_filled_with_evens_16(int16_t *p, int size)+{+ return is_filled_with_evens(p, size);+}++int is_filled_with_evens_32(int32_t *p, int size)+{+ return is_filled_with_evens(p, size);+}++int is_filled_with_evens_64(int64_t *p, int size)+{+ return is_filled_with_evens(p, size);+}++#ifdef __cplusplus+}+#endif+
+ examples/tests/primitives/Backpermute.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE TypeOperators #-}++module Backpermute where++import Util+import Random++import Control.Monad+import Control.Exception+import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate as Acc+import Prelude as P+++-- Tests+-- -----++reverseAcc :: Vector Float -> Acc (Vector Float)+reverseAcc xs =+ let xs' = use xs+ len = unindex1 (shape xs')+ in+ backpermute (shape xs') (\ix -> index1 $ len - (unindex1 ix) - 1) xs'++reverseRef :: UArray Int Float -> UArray Int Float+reverseRef xs = listArray (bounds xs) (reverse (elems xs))+++transposeAcc :: Acc.Array DIM2 Float -> Acc (Acc.Array DIM2 Float)+transposeAcc mat =+ let mat' = use mat+ swap = lift1 $ \(Z:.x:.y) -> Z:.y:.x :: Z:.Exp Int:.Exp Int+ in+ backpermute (swap $ shape mat') swap mat'++transposeRef :: UArray (Int,Int) Float -> UArray (Int,Int) Float+transposeRef mat =+ let swap (x,y) = (y,x)+ (u,v) = bounds mat+ in+ array (swap u, swap v) [(swap ix, e) | (ix, e) <- assocs mat]+++-- Main+-- ----++run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run alg n = withSystemRandom $ \gen -> do+ vec <- randomUArrayR (-1,1) gen n+ vec' <- convertUArray vec+ --+ let go f g = return (\() -> f vec, \() -> g vec')+ case alg of+ "reverse" -> go reverseRef reverseAcc+ _ -> error $ "unknown variant: " ++ alg++run2d :: String -> Int -> IO (() -> UArray (Int,Int) Float, () -> Acc (Acc.Array DIM2 Float))+run2d alg n = withSystemRandom $ \gen -> do+ let n' = P.round $ sqrt (P.fromIntegral n :: Double)+ (u,v) = (n'*2, n'`div`2)+ mat <- listArray ((0,0), (u-1,v-1)) `fmap` replicateM' (u*v) (uniformR (-1,1) gen)+ mat' <- let m = fromIArray mat :: Acc.Array DIM2 Float+ in evaluate (m `Acc.indexArray` (Z:.0:.0)) >> return m+ --+ let go f g = return (\() -> f mat, \() -> g mat')+ case alg of+ "transpose" -> go transposeRef transposeAcc+ _ -> error $ "unknown variant: " ++ alg+
+ examples/tests/primitives/Fold.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE FlexibleContexts, TypeOperators #-}++module Fold where++import Util+import Random++import Control.Monad+import Control.Exception+import System.Random.MWC+import Data.List+import Data.Array.Unboxed hiding (Array)+import Data.Array.Accelerate as Acc+import Prelude as P+++-- one-dimension ah-ha-ha+-- ----------------------++toUA :: (IArray UArray a, IArray UArray b) => ([a] -> b) -> UArray Int a -> UArray () b+toUA f = listArray ((),()) . return . f . elems+++sumAcc, prodAcc, maxAcc, minAcc :: Shape ix => Array (ix:.Int) Float -> Acc (Array ix Float)+sumAcc = Acc.fold (+) 0 . Acc.use+prodAcc = Acc.fold (*) 1 . Acc.use+maxAcc = Acc.fold1 Acc.max . Acc.use+minAcc = Acc.fold1 Acc.min . Acc.use++sumRef, prodRef, maxRef, minRef :: UArray Int Float -> UArray () Float+sumRef = toUA (foldl' (+) 0)+prodRef = toUA (foldl' (*) 1)+maxRef = toUA (foldl1' P.max)+minRef = toUA (foldl1' P.min)+++-- two-dimensions ah-ha-ha+-- -----------------------++foldU2D :: IArray UArray a => (a -> a -> a) -> a -> UArray (Int,Int) a -> UArray Int a+foldU2D f z arr =+ let (_,(m,_)) = bounds arr+ in accumArray f z (0,m) [ (i,e) | ((i,_),e) <- assocs arr ]++sum2DRef, prod2DRef, min2DRef, max2DRef :: UArray (Int,Int) Float -> UArray Int Float+sum2DRef = foldU2D (+) 0+prod2DRef = foldU2D (*) 1+min2DRef = foldU2D P.min ( 1/0)+max2DRef = foldU2D P.max (-1/0)+++-- Main+-- ----+run :: String -> Int -> IO (() -> UArray () Float, () -> Acc (Scalar Float))+run alg n = withSystemRandom $ \gen -> do+ vec <- randomUArrayR (-1,1) gen n+ vec' <- convertUArray vec+ --+ let go f g = return (run_ref f vec, run_acc g vec')+ case alg of+ "sum" -> go sumRef sumAcc+ "product" -> go prodRef prodAcc+ "maximum" -> go maxRef maxAcc+ "minimum" -> go minRef minAcc+ x -> error $ "unknown variant: " ++ x+ where+ {-# NOINLINE run_ref #-}+ run_ref f xs () = f xs+ run_acc f xs () = f xs++run2d :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run2d alg n = withSystemRandom $ \gen -> do+ let u = P.floor . sqrt $ (P.fromIntegral n :: Double)+ v = 2*u+1 :: Int+ mat <- listArray ((0,0), (u-1,v-1)) `fmap` replicateM' (u*v) (uniformR (-1,1) gen)+ mat' <- let m = fromIArray mat :: Array DIM2 Float+ in evaluate (m `Acc.indexArray` (Z:.0:.0)) >> return m+ --+ let go f g = return (run_ref f mat, run_acc g mat')+ case alg of+ "sum-2d" -> go sum2DRef sumAcc+ "product-2d" -> go prod2DRef prodAcc+ "maximum-2d" -> go max2DRef maxAcc+ "minimum-2d" -> go min2DRef minAcc+ x -> error $ "unknown variant: " ++ x+ where+ {-# NOINLINE run_ref #-}+ run_ref f xs () = f xs+ run_acc f xs () = f xs+
+ examples/tests/primitives/FoldSeg.hs view
@@ -0,0 +1,62 @@++module FoldSeg where++import Random++import Data.List+import System.IO+import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate as A+import Prelude as P+++-- segmented reduction+-- -------------------++sumSegAcc :: Vector Float -> Segments Int32 -> Acc (Vector Float)+sumSegAcc xs seg+ = let xs' = use xs+ seg' = use seg+ in+ A.foldSeg (+) 0 xs' seg'++sumSegRef :: UArray Int Float -> UArray Int Int32 -> UArray Int Float+sumSegRef xs seg+ = listArray (bounds seg)+ $ list_foldSeg (+) 0 (elems xs) (elems seg)++list_foldSeg :: (a -> a -> a) -> a -> [a] -> [Int32] -> [a]+list_foldSeg f s xs seg = P.map (foldl' f s) (split seg xs)+ where+ split [] _ = []+ split _ [] = []+ split (i:is) vs =+ let (h,t) = splitAt (P.fromIntegral i) vs+ in h : split is t+++-- main+-- ----++run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run alg m = withSystemRandom $ \gen -> do+ -- generate segments+ --+ let n = P.round $ sqrt (P.fromIntegral m :: Double)+ seg <- randomUArrayR (0, 2*n) gen (P.fromIntegral n)+ seg' <- convertUArray seg++ -- generate elements+ --+ let x = P.fromIntegral $ sum (elems seg)+ vec <- randomUArrayR (-1,1) gen x+ vec' <- convertUArray vec++ -- super-happy-fun-times+ --+ let go f g = return (\() -> f vec seg, \() -> g vec' seg')+ case alg of+ "sum" -> go sumSegRef sumSegAcc+ unknown -> error $ "unknown variant: " ++ unknown+
+ examples/tests/primitives/Gather.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE FlexibleContexts #-}++module Gather where++import Random++import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate as Acc hiding ((!))+import Prelude as P+++-- Tests+-- -----++gatherAcc :: Vector Int -> Vector Float -> Acc (Vector Float)+gatherAcc mapV inputV = Acc.gather (use mapV) (use inputV)++gatherIfAcc :: Vector Int -> Vector Int -> Vector Float -> Vector Float -> Acc (Vector Float)+gatherIfAcc mapV maskV defaultV inputV+ = Acc.gatherIf (use mapV) (use maskV) evenAcc (use defaultV) (use inputV)++evenAcc :: Exp Int -> Exp Bool+evenAcc v = (v `mod` 2) ==* 0+++gatherRef :: UArray Int Int -> UArray Int Float -> UArray Int Float+gatherRef mapV inputV = amap (\ix -> inputV ! ix) mapV++gatherIfRef :: UArray Int Int -> UArray Int Int -> UArray Int Float -> UArray Int Float -> UArray Int Float+gatherIfRef mapV maskV defaultV inputV+ = listArray (bounds mapV)+ $ P.map (\(mIx, mV, dV) -> if evenRef mV then (inputV ! mIx) else dV)+ $ P.zip3 mapL maskL defaultL+ where+ mapL = elems mapV+ maskL = elems maskV+ defaultL = elems defaultV++evenRef :: Int -> Bool+evenRef = even+++-- Main+-- ----+run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run alg n = withSystemRandom $ \gen -> do+ vec <- randomUArrayR (-1, 1) gen n+ vec' <- convertUArray vec++ mapV <- randomUArrayR (0, n - 1) gen n+ mapV' <- convertUArray mapV++ maskV <- randomUArrayR (0, n) gen n+ maskV' <- convertUArray maskV++ defaultV <- randomUArrayR (-1, 1) gen n+ defaultV' <- convertUArray defaultV++ --+ let go f g = return (run_ref f vec, run_acc g vec')++ case alg of+ "gather" -> go (gatherRef mapV) (gatherAcc mapV')+ "gather-if" -> go (gatherIfRef mapV maskV defaultV) (gatherIfAcc mapV' maskV' defaultV')+ x -> error $ "unknown variant: " ++ x++ where+ {-# NOINLINE run_ref #-}+ run_ref f xs () = f xs+ run_acc f xs () = f xs++
+ examples/tests/primitives/Map.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE FlexibleContexts #-}++module Map where++import Random++import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate as Acc+++-- Tests+-- -----+sqAcc, absAcc :: Vector Float -> Acc (Vector Float)+absAcc = Acc.map abs . Acc.use+sqAcc = Acc.map (\x -> x * x) . Acc.use++plusAcc :: Exp Float -> Vector Float -> Acc (Vector Float)+plusAcc alpha = Acc.map (+ alpha) . Acc.use+++toUA :: (IArray UArray a, IArray UArray b) => ([a] -> [b]) -> UArray Int a -> UArray Int b+toUA f xs = listArray (bounds xs) $ f (elems xs)++sqRef, absRef :: UArray Int Float -> UArray Int Float+absRef = toUA $ Prelude.map abs+sqRef = toUA $ Prelude.map (\x -> x*x)++plusRef :: Float -> UArray Int Float -> UArray Int Float+plusRef alpha = toUA $ Prelude.map (+alpha)+++-- Main+-- ----+run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run alg n = withSystemRandom $ \gen -> do+ vec <- randomUArrayR (-1,1) gen n+ vec' <- convertUArray vec+ alpha <- uniform gen+ --+ let go f g = return (run_ref f vec, run_acc g vec')+ case alg of+ "abs" -> go absRef absAcc+ "plus" -> go (plusRef alpha) (plusAcc $ constant alpha)+ "square" -> go sqRef sqAcc+ x -> error $ "unknown variant: " ++ x++ where+ {-# NOINLINE run_ref #-}+ run_ref f xs () = f xs+ run_acc f xs () = f xs+
+ examples/tests/primitives/Permute.hs view
@@ -0,0 +1,40 @@+module Permute where++import Random++import Data.Int+import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate as Acc+import Prelude as P+++-- Tests+-- -----++histogramAcc :: (Int,Int) -> Vector Float -> Acc (Vector Int32)+histogramAcc (m,n) vec =+ let vec' = use vec+ zeros = generate (constant (Z:. n-m)) (const 0)+ ones = generate (shape vec') (const 1)+ in+ permute (+) zeros (\ix -> index1 $ Acc.floor (vec' Acc.! ix)) ones++histogramRef :: (Int,Int) -> UArray Int Float -> UArray Int Int32+histogramRef (m,n) vec =+ accumArray (+) 0 (0,n-m-1) [(P.floor e, 1) | e <- elems vec]+++-- Main+-- ----+run :: String -> Int -> IO (() -> UArray Int Int32, () -> Acc (Vector Int32))+run alg n = withSystemRandom $ \gen -> do+ vec <- randomUArrayR (0,100::Float) gen n+ vec' <- convertUArray vec+ --+ let go f g = return (\() -> f vec, \() -> g vec')+ case alg of+ "histogram" -> go (histogramRef (0,100)) (histogramAcc (0,100))+ _ -> error $ "unknown variant: " ++ alg++
+ examples/tests/primitives/ScanSeg.hs view
@@ -0,0 +1,63 @@++module ScanSeg where++import Random++import System.IO+import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate as Acc+import Prelude as P+++-- Segmented prefix-sum+-- --------------------+prefixSumSegAcc :: Vector Float -> Segments Int32 -> Acc (Vector Float)+prefixSumSegAcc xs seg+ = let+ xs' = use xs+ seg' = use seg+ in+ prescanlSeg (+) 0 xs' seg'+++prefixSumSegRef :: UArray Int Float -> UArray Int Int32 -> UArray Int Float+prefixSumSegRef xs seg+ = listArray (bounds xs)+ $ list_prescanlSeg (+) 0 (elems xs) (elems seg)++list_prescanlSeg :: (a -> a -> a) -> a -> [a] -> [Int32] -> [a]+list_prescanlSeg f x xs seg = concatMap (P.init . P.scanl f x) (split seg xs)+ where+ split [] _ = []+ split _ [] = []+ split (i:is) vs =+ let (h,t) = splitAt (P.fromIntegral i) vs+ in h : split is t+++-- Main+-- ----+run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run alg m = withSystemRandom $ \gen -> do+ -- generate segments+ --+ let n = P.round . sqrt $ (P.fromIntegral m :: Double)+ seg <- randomUArrayR (0,n) gen (P.fromIntegral n)+ seg' <- convertUArray seg++ -- generate elements+ --+ let ne = P.fromIntegral $ sum (elems seg)+ vec <- randomUArrayR (-1,1) gen ne+ vec' <- convertUArray vec+ --+ let go f g = return (run_ref f vec seg, run_acc g vec' seg')+ case alg of+ "sum" -> go prefixSumSegRef prefixSumSegAcc+ x -> error $ "unknown variant: " ++ x+ where+ {-# NOINLINE run_ref #-}+ run_ref f xs seg () = f xs seg+ run_acc f xs seg () = f xs seg+
+ examples/tests/primitives/Scatter.hs view
@@ -0,0 +1,107 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}++module Scatter where++import Random++import Data.List+import Data.Maybe+import Data.Array.ST+import Control.Monad+import Control.Applicative+import System.Random.MWC+import Data.Array.Unboxed++import Prelude as P+import Data.Array.Accelerate as Acc hiding ((!))+import qualified Data.Array.MArray as M+import qualified Data.HashTable.IO as Hash+++-- Tests+-- -----++scatterAcc :: Vector Int -> Vector Float -> Vector Float -> Acc (Vector Float)+scatterAcc mapV defaultV inputV = Acc.scatter (use mapV) (use defaultV) (use inputV)++scatterIfAcc :: Vector Int -> Vector Int -> Vector Float -> Vector Float -> Acc (Vector Float)+scatterIfAcc mapV maskV defaultV inputV+ = Acc.scatterIf (use mapV) (use maskV) evenAcc (use defaultV) (use inputV)++evenAcc :: Exp Int -> Exp Bool+evenAcc v = (v `mod` 2) ==* 0+++scatterRef :: UArray Int Int -> UArray Int Float -> UArray Int Float -> UArray Int Float+scatterRef mapV defaultV inputV = runSTUArray $ do+ mu <- M.thaw defaultV+ forM_ (P.zip [0..] $ elems mapV) $ \(inIx, outIx) -> do+ writeArray mu outIx (inputV ! inIx)+ return mu++scatterIfRef :: UArray Int Int -> UArray Int Int -> UArray Int Float -> UArray Int Float -> UArray Int Float+scatterIfRef mapV maskV defaultV inputV = runSTUArray $ do+ mu <- M.thaw defaultV+ forM_ (P.zip [0..] $ elems mapV) $ \(inIx, outIx) -> do+ when (evenRef (maskV ! inIx)) $ do+ writeArray mu outIx (inputV ! inIx)+ return mu++evenRef :: Int -> Bool+evenRef = even+++-- Random+-- ------++uniqueRandomUArrayR :: GenIO -> (Int,Int) -> Int -> IO (UArray Int Int)+uniqueRandomUArrayR gen lim n = do+ set <- Hash.new :: IO (Hash.BasicHashTable Int ())++ let go !i !m | i >= n = return m+ | otherwise = do+ v <- uniformR lim gen+ exists <- isJust <$> Hash.lookup set v+ if exists+ then go (i+1) m+ else Hash.insert set v () >> go (i+1) (m+1)++ n' <- go 0 0+ listArray (0, n'-1) . P.map P.fst <$> Hash.toList set+++-- Main+-- ----+run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run alg n = withSystemRandom $ \gen -> do+ let m = 2 * n++ mapV <- uniqueRandomUArrayR gen (0, m-1) n+ mapV' <- convertUArray mapV+ let n' = rangeSize (bounds mapV)++ vec <- randomUArrayR (-1, 1) gen n'+ vec' <- convertUArray vec++ maskV <- randomUArrayR (0, n') gen n'+ maskV' <- convertUArray maskV++ defaultV <- randomUArrayR (-1, 1) gen m+ defaultV' <- convertUArray defaultV++ --+ let go f g = return (run_ref f vec, run_acc g vec')++ case alg of+ "scatter" -> go (scatterRef mapV defaultV) (scatterAcc mapV' defaultV')+ "scatter-if" -> go (scatterIfRef mapV maskV defaultV) (scatterIfAcc mapV' maskV' defaultV')+ x -> error $ "unknown variant: " ++ x++ where+ {-# NOINLINE run_ref #-}+ run_ref f xs () = f xs+ run_acc f xs () = f xs+++
+ examples/tests/primitives/Stencil.hs view
@@ -0,0 +1,229 @@+{-# LANGUAGE FlexibleContexts #-}++module Stencil where++import Util+import Random++import Control.Exception+import System.Random.MWC++import Data.Array.Unboxed hiding (Array)+import qualified Data.Array.IArray as IArray++import Data.Array.Accelerate hiding (min, max, round, fromIntegral)+import qualified Data.Array.Accelerate as Acc++++-- Stencil Tests+-- -------------++-- 1D --------------------------------------------------------------------------++stencil1D :: Floating a+ => (a, a, a) -> a+stencil1D (x, y, z) = (x + z - 2 * y) / 2++test_stencil1D :: Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+test_stencil1D n = withSystemRandom $ \gen -> do+ vec <- randomUArrayR (-1,1) gen n+ vec' <- convertUArray vec+ return (\() -> run_ref vec, \() -> run_acc vec')+ where+ run_acc = stencil stencil1D Clamp . use+ run_ref v =+ let (minx,maxx) = bounds v+ clamp x = minx `max` x `min` maxx++ f ix = let x = v IArray.! clamp (ix-1)+ y = v IArray.! ix+ z = v IArray.! clamp (ix+1)+ in+ (x + z - 2 * y) / 2+ in+ array (bounds v) [(ix, f ix) | ix <- indices v]+++-- 2D --------------------------------------------------------------------------++stencil2D :: Floating (Exp a)+ => Stencil3x3 a -> Exp a+stencil2D ( (t1, t2, t3)+ , (l , m, r )+ , (b1, b2, b3)+ )+ = (t1/2 + t2 + t3/2 + l + r + b1/2 + b2 + b3/2 - 4 * m) / 4++test_stencil2D :: Int -> IO (() -> IArray.Array (Int,Int) Float, () -> Acc (Array DIM2 Float))+test_stencil2D n2 = withSystemRandom $ \gen -> do+ let n = round . (/3) . sqrt $ (fromIntegral n2 :: Double)+ m = n * 4+ mat <- listArray ((0,0),(n-1,m-1)) `fmap` replicateM' (n*m) (uniformR (-1,1) gen) :: IO (IArray.Array (Int,Int) Float)+ mat' <- let v = fromIArray mat :: Array DIM2 Float+ in evaluate (v `indexArray` (Z:.0:.0)) >> return v+ --+ return (\() -> run_ref mat, \() -> run_acc mat')+ where+ run_acc = stencil stencil2D (Constant 0) . use+ run_ref arr =+ let get ix+ | inRange (bounds arr) ix = arr IArray.! ix+ | otherwise = 0++ f (x,y) = let t1 = get (x-1,y-1)+ t2 = get (x, y-1)+ t3 = get (x+1,y-1)+ l = get (x-1,y)+ m = get (x, y)+ r = get (x+1,y)+ b1 = get (x-1,y+1)+ b2 = get (x, y+1)+ b3 = get (x+1,y+1)+ in+ (t1/2 + t2 + t3/2 + l + r + b1/2 + b2 + b3/2 - 4 * m) / 4+ in+ array (bounds arr) [(ix, f ix) | ix <- indices arr]++++stencil2D5 :: Floating (Exp a)+ => Stencil3x3 a -> Exp a+stencil2D5 ( (_, t, _)+ , (l, m, r)+ , (_, b, _)+ )+ = (t + l + r + b - 4 * m) / 4++test_stencil2D5 :: Int -> IO (() -> IArray.Array (Int,Int) Float, () -> Acc (Array DIM2 Float))+test_stencil2D5 n2 = withSystemRandom $ \gen -> do+ let n = round . sqrt $ (fromIntegral n2 :: Double)+ mat <- listArray ((0,0),(n-1,n-1)) `fmap` replicateM' (n*n) (uniformR (-1,1) gen) :: IO (IArray.Array (Int,Int) Float)+ mat' <- let m = fromIArray mat :: Array DIM2 Float+ in evaluate (m `indexArray` (Z:.0:.0)) >> return m+ --+ return (\() -> run_ref mat, \() -> run_acc mat')+ where+ run_acc = stencil stencil2D5 Clamp . use+ run_ref arr =+ let ((minx,miny),(maxx,maxy)) = bounds arr+ clamp (x,y) = (minx `max` x `min` maxx+ ,miny `max` y `min` maxy)+ f (x,y) = let t = arr IArray.! clamp (x,y-1)+ b = arr IArray.! clamp (x,y+1)+ l = arr IArray.! clamp (x-1,y)+ r = arr IArray.! clamp (x+1,y)+ m = arr IArray.! (x,y)+ in+ (t + l + r + b - 4 * m) / 4+ in+ array (bounds arr) [(ix, f ix) | ix <- indices arr]++++stencil2Dpair :: Stencil3x3 (Int,Float) -> Exp Float+stencil2Dpair ( (_, _, _)+ , (x, _, _)+ , (y, _, z)+ )+ = let (x1,x2) = unlift x :: (Exp Int, Exp Float)+ (y1,y2) = unlift y+ (z1,z2) = unlift z+ in+ (x2 * Acc.fromIntegral x1 + y2 * Acc.fromIntegral z1 - z2 * Acc.fromIntegral y1)++test_stencil2Dpair :: Int -> IO (() -> IArray.Array (Int,Int) Float, () -> Acc (Array DIM2 Float))+test_stencil2Dpair n2 = withSystemRandom $ \gen -> do+ let n = round (fromIntegral n2 ** 0.5 :: Double)+ m = 2 * n+ mat <- listArray ((0,0),(n-1,m-1)) `fmap` replicateM' (n*m) (uniformR ((-100,0), (100,0)) gen) :: IO (IArray.Array (Int,Int) (Int,Float))+ mat' <- let a = fromIArray mat+ in evaluate (a `indexArray` (Z:.0:.0)) >> return a+ --+ return (\() -> run_ref mat, \() -> run_acc mat')+ where+ run_acc = stencil stencil2Dpair Wrap . use+ run_ref arr =+ let ((minx,miny),(maxx,maxy)) = bounds arr+ wrap (m,n) i+ | i < m = n + (i-m)+ | i > n = i - n + m+ | otherwise = i++ get (x,y) = arr IArray.! ( wrap (minx,maxx) x, wrap (miny,maxy) y)+ f (x,y) = let (a1,a2) = get (x-1,y)+ (b1,b2) = get (x-1,y+1)+ (c1,c2) = get (x+1,y+1)+ in+ (a2 * fromIntegral a1 + b2 * fromIntegral c1 - c2 * fromIntegral b1)+ in+ array (bounds arr) [(ix, f ix) | ix <- indices arr]+++-- 3D --------------------------------------------------------------------------++stencil3D :: Num (Exp a)+ => Stencil3x3x3 a -> Exp a+stencil3D (front, back, _) = -- 'b4' is the focal point+ let ((f1, f2, _),+ (f3, f4, _),+ _ ) = front+ ((b1, b2, _),+ (b3, b4, _),+ _ ) = back+ in+ f1 + f2 + f3 + f4 + b1 + b2 + b3 + b4++test_stencil3D :: Int -> IO (() -> UArray (Int,Int,Int) Float, () -> Acc (Array DIM3 Float))+test_stencil3D n3 = withSystemRandom $ \gen -> do+ let u = round (fromIntegral n3 ** (1/3) :: Double)+ v = u `div` 2+ w = u * 3+ arr <- listArray ((0,0,0), (u-1, v-1, w-1)) `fmap` replicateM' (u*v*w) (uniformR (-1,1) gen) :: IO (UArray (Int,Int,Int) Float)+ arr' <- let a = fromIArray arr+ in evaluate (a `indexArray` (Z:.0:.0:.0)) >> return a+ --+ return (\() -> run_ref arr, \() -> run_acc arr')+ where+ run_acc = stencil stencil3D Mirror . use+ run_ref arr =+ let ((minx,miny,minz),(maxx,maxy,maxz)) = bounds arr+ mirror (m,n) i+ | i < m = -i + m+ | i > n = n - (i-n+2)+ | otherwise = i++ get (x,y,z) = arr IArray.! ( mirror (minx,maxx) x, mirror (miny,maxy) y, mirror (minz,maxz) z)+ f (x,y,z) = let f1 = get (x-1,y-1,z-1)+ f2 = get (x, y-1,z-1)+ f3 = get (x-1,y, z-1)+ f4 = get (x, y, z-1)+ b1 = get (x-1,y-1,z )+ b2 = get (x, y-1,z )+ b3 = get (x-1,y, z )+ b4 = get (x, y, z )+ in+ f1 + f2 + f3 + f4 + b1 + b2 + b3 + b4+ in+ array (bounds arr) [(ix, f ix) | ix <- indices arr]+++-- Main+-- ----++run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run "1D" = test_stencil1D+run x = error $ "unknown variant: " ++ x+++run2D :: String -> Int -> IO (() -> IArray.Array (Int,Int) Float, () -> Acc (Array DIM2 Float))+run2D "2D" = test_stencil2D+run2D "3x3-cross" = test_stencil2D5+run2D "3x3-pair" = test_stencil2Dpair+run2D x = error $ "unknown variant: " ++ x+++run3D :: String -> Int -> IO (() -> UArray (Int,Int,Int) Float, () -> Acc (Array DIM3 Float))+run3D "3D" = test_stencil3D+run3D x = error $ "unknown variant: " ++ x+
+ examples/tests/primitives/Stencil2.hs view
@@ -0,0 +1,109 @@+{-# LANGUAGE FlexibleContexts #-}++module Stencil2 where++import Util++import Control.Exception+import System.Random.MWC+import Data.Array.Unboxed hiding (Array)+import Data.Array.Accelerate hiding (round, min, max, fromIntegral)+import qualified Data.Array.Accelerate as A+import qualified Data.Array.IArray as IArray++++stencil2D2 :: Floating (Exp a) => Stencil3x3 a -> Stencil3x3 a -> Exp a+stencil2D2 ((_,t,_), (_,x,_), (_,b,_))+ ((_,_,_), (l,y,r), (_,_,_)) = t + b + l + r - ((x+y) / 2)+++stencil2D2Ref+ :: (Floating a, IArray UArray a)+ => UArray (Int,Int) a+ -> UArray (Int,Int) a+ -> UArray (Int,Int) a+stencil2D2Ref xs ys = array sh [(ix, f ix) | ix <- range sh]+ where+ (_,(n,m)) = bounds xs+ (_,(u,v)) = bounds ys+ sh = ((0,0), (n `min` u, m `min` v))++ -- boundary conditions are placed on the *source* arrays+ --+ get1 (x,y) = xs IArray.! (mirror n x, mirror m y)+ get0 (x,y) = ys IArray.! (wrap u x, wrap v y)++ mirror sz i+ | i < 0 = -i+ | i > sz = sz - (i-sz)+ | otherwise = i++ wrap sz i+ | i < 0 = sz + i + 1+ | i > sz = i - sz - 1+ | otherwise = i++ f (ix,iy) =+ let t = get1 (ix-1, iy )+ b = get1 (ix+1, iy )+ x = get1 (ix, iy )+ l = get0 (ix, iy-1)+ r = get0 (ix, iy+1)+ y = get0 (ix, iy )+ in+ t + b + l + r - ((x+y) / 2)+++test_stencil2_2D :: Int -> IO (() -> UArray (Int,Int) Float, () -> Acc (Array DIM2 Float))+test_stencil2_2D n2 = withSystemRandom $ \gen -> do+ let n = round $ sqrt (fromIntegral n2 :: Double)+ m = n * 2+ u = m `div` 3+ v = n + m+ m1 <- listArray ((0,0),(n-1,m-1)) `fmap` replicateM' (n*m) (uniformR (-1,1) gen) :: IO (UArray (Int,Int) Float)+ m2 <- listArray ((0,0),(u-1,v-1)) `fmap` replicateM' (u*v) (uniformR (-1,1) gen) :: IO (UArray (Int,Int) Float)+ m1' <- let m1' = fromIArray m1 in evaluate (m1' `indexArray` (Z:.0:.0)) >> return m1'+ m2' <- let m2' = fromIArray m2 in evaluate (m2' `indexArray` (Z:.0:.0)) >> return m2'+ --+ return (\() -> run_ref m1 m2, \() -> run_acc m1' m2')+ where+ run_acc xs ys = stencil2 stencil2D2 Mirror (use xs) Wrap (use ys)+ run_ref xs ys = stencil2D2Ref xs ys+++varUse :: (Acc (Array DIM2 Int), Acc (Array DIM2 Float), Acc (Array DIM2 Float))+varUse = (first, both, second)+ where+ is :: Array DIM2 Int+ is = fromList (Z:.10:.10) [0..]+ + fs :: Array DIM2 Float+ fs = fromList (Z:.10:.10) [0..]++ -- Ignoring the first parameter+ first = stencil2 centre Clamp (use fs) Clamp (use is)+ where+ centre :: Stencil3x3 Float -> Stencil3x3 Int -> Exp Int+ centre _ (_,(_,y,_),_) = y++ -- Using both+ both = stencil2 centre Clamp (use fs) Clamp (use is)+ where+ centre :: Stencil3x3 Float -> Stencil3x3 Int -> Exp Float+ centre (_,(_,x,_),_) (_,(_,y,_),_) = x + A.fromIntegral y++ -- Not using the second parameter+ second = stencil2 centre Clamp (use fs) Clamp (use is)+ where+ centre :: Stencil3x3 Float -> Stencil3x3 Int -> Exp Float+ centre (_,(_,x,_),_) _ = x+++-- Main+-- ----++run2D :: String -> Int -> IO (() -> UArray (Int,Int) Float, () -> Acc (Array DIM2 Float))+run2D "2D" = test_stencil2_2D+run2D x = error $ "unknown variant: " ++ x+
+ examples/tests/primitives/Vector.hs view
@@ -0,0 +1,67 @@+{-# LANGUAGE FlexibleContexts #-}++module Vector where++import Random++import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate as Acc+++-- Tests+-- -----++initAcc, tailAcc :: Vector Float -> Acc (Vector Float)+initAcc = Acc.init . Acc.use+tailAcc = Acc.tail . Acc.use++takeAcc, dropAcc :: Int -> Vector Float -> Acc (Vector Float)+takeAcc n = (Acc.take $ constant n) . Acc.use+dropAcc n = (Acc.drop $ constant n) . Acc.use++slitAcc :: Int -> Int -> Vector Float -> Acc (Vector Float)+slitAcc i n = (Acc.slit (constant i) (constant n)) . Acc.use++toUA :: (IArray UArray a, IArray UArray b) => ([a] -> [b]) -> UArray Int a -> UArray Int b+toUA f xs = listArray (bounds xs) $ f (elems xs)++initRef, tailRef :: UArray Int Float -> UArray Int Float+initRef = toUA $ Prelude.init+tailRef = toUA $ Prelude.tail++takeRef, dropRef :: Int -> UArray Int Float -> UArray Int Float+takeRef n = toUA $ Prelude.take n+dropRef n = toUA $ Prelude.drop n++slitRef :: Int -> Int -> UArray Int Float -> UArray Int Float+slitRef i n = toUA $ (Prelude.take n . Prelude.drop i)+++-- Main+-- ----+run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run alg n = withSystemRandom $ \gen -> do+ vec <- randomUArrayR (-1,1) gen n+ vec' <- convertUArray vec+ ri0 <- uniform gen -- ri = random int+ ri1 <- uniform gen++ --+ let go f g = return (run_ref f vec, run_acc g vec')+ m = (abs ri0) `mod` n+ len = (abs ri1) `mod` (n - m)++ case alg of+ "init" -> go initRef initAcc+ "tail" -> go tailRef tailAcc+ "take" -> go (takeRef m) (takeAcc m)+ "drop" -> go (dropRef m) (dropAcc m)+ "slit" -> go (slitRef m len) (slitAcc m len)+ x -> error $ "unknown variant: " ++ x++ where+ {-# NOINLINE run_ref #-}+ run_ref f xs () = f xs+ run_acc f xs () = f xs+
+ examples/tests/primitives/Zip.hs view
@@ -0,0 +1,35 @@++module Zip where++import Random++import System.Random.MWC+import Data.Array.Unboxed as IArray+import Data.Array.Accelerate as Acc hiding (min)+++-- Tests+-- -----++zipAcc :: Vector Float -> Vector Int -> Acc (Vector (Float,Int))+zipAcc xs ys = Acc.zip (use xs) (use ys)+++zipRef :: UArray Int Float -> UArray Int Int -> IArray.Array Int (Float,Int)+zipRef xs ys =+ let mn = bounds xs+ uv = bounds ys+ newSize = (0, (rangeSize mn `min` rangeSize uv) - 1)+ in+ listArray newSize $ Prelude.zip (elems xs) (elems ys)++-- Main+-- ----+run :: Int -> IO (() -> IArray.Array Int (Float,Int), () -> Acc (Vector (Float,Int)))+run n = withSystemRandom $ \gen -> do+ xs <- randomUArrayR (-1,1) gen n+ ys <- randomUArrayR (-1,1) gen n+ xs' <- convertUArray xs+ ys' <- convertUArray ys+ return $ (\() -> zipRef xs ys, \() -> zipAcc xs' ys')+
+ examples/tests/primitives/ZipWith.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE ParallelListComp #-}++module ZipWith where++import Random++import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate as Acc hiding (min)+++-- Tests+-- -----++plusAcc :: Vector Float -> Vector Float -> Acc (Vector Float)+plusAcc xs ys = Acc.zipWith (+) (use xs) (use ys)++plusRef :: UArray Int Float -> UArray Int Float -> UArray Int Float+plusRef = zipWithRef (+)++zipWithRef :: (IArray array a, IArray array b, IArray array c)+ => (a -> b -> c) -> array Int a -> array Int b -> array Int c+zipWithRef f xs ys =+ let mn = bounds xs+ uv = bounds ys+ newSize = (0, (rangeSize mn `min` rangeSize uv) - 1)+ in+ listArray newSize [f x y | x <- elems xs | y <- elems ys]++-- Main+-- ----+run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run alg n = withSystemRandom $ \gen -> do+ xs <- randomUArrayR (-1,1) gen n+ ys <- randomUArrayR (-1,1) gen n+ xs' <- convertUArray xs+ ys' <- convertUArray ys+ let go f g = return (\() -> f xs ys, \() -> g xs' ys')+ case alg of+ "plus" -> go plusRef plusAcc+ _ -> error $ "unknown variant: " ++ alg+
+ examples/tests/simple/BlackScholes.hs view
@@ -0,0 +1,88 @@++module BlackScholes where++import Random++import System.Random.MWC+import Data.Array.IArray as IArray+import Data.Array.Accelerate as Acc+import Prelude as P+++riskfree, volatility :: Float+riskfree = 0.02+volatility = 0.30++-- Black-Scholes option pricing+-------------------------------++horner :: Num a => [a] -> a -> a+horner coeff x = foldr1 madd coeff+ where+ madd a b = b*x + a++cnd' :: Floating a => a -> a+cnd' d =+ let poly = horner coeff+ coeff = [0.0,0.31938153,-0.356563782,1.781477937,-1.821255978,1.330274429]+ rsqrt2pi = 0.39894228040143267793994605993438+ k = 1.0 / (1.0 + 0.2316419 * abs d)+ in+ rsqrt2pi * exp (-0.5*d*d) * poly k+++blackscholesAcc :: Vector (Float, Float, Float) -> Acc (Vector (Float, Float))+blackscholesAcc xs = Acc.map go (Acc.use xs)+ where+ go x =+ let (price, strike, years) = Acc.unlift x+ r = Acc.constant riskfree+ v = Acc.constant volatility+ sqrtT = sqrt years+ d1 = (log (price / strike) + (r + 0.5 * v * v) * years) / (v * sqrtT)+ d2 = d1 - v * sqrtT+ cnd d = d >* 0 ? (1.0 - cnd' d, cnd' d)+ cndD1 = cnd d1+ cndD2 = cnd d2+ expRT = exp (-r * years)+ in+ Acc.lift ( price * cndD1 - strike * expRT * cndD2+ , strike * expRT * (1.0 - cndD2) - price * (1.0 - cndD1))+++blackscholesRef :: IArray.Array Int (Float,Float,Float) -> IArray.Array Int (Float,Float)+blackscholesRef xs = listArray (bounds xs) [ go x | x <- elems xs ]+ where+ go (price, strike, years) =+ let r = riskfree+ v = volatility+ sqrtT = sqrt years+ d1 = (log (price / strike) + (r + 0.5 * v * v) * years) / (v * sqrtT)+ d2 = d1 - v * sqrtT+ cnd d = if d > 0 then 1.0 - cnd' d else cnd' d+ cndD1 = cnd d1+ cndD2 = cnd d2+ expRT = exp (-r * years)+ in+ ( price * cndD1 - strike * expRT * cndD2+ , strike * expRT * (1.0 - cndD2) - price * (1.0 - cndD1))+++-- Main+-- ----++run :: Int -> IO (() -> IArray.Array Int (Float,Float), () -> Acc (Vector (Float,Float)))+run n = withSystemRandom $ \gen -> do+ v_sp <- randomUArrayR (5,30) gen n+ v_os <- randomUArrayR (1,100) gen n+ v_oy <- randomUArrayR (0.25,10) gen n++ let v_psy = listArray (0,n-1) $ P.zip3 (elems v_sp) (elems v_os) (elems v_oy)+ a_psy = Acc.fromIArray v_psy+ --+ return (run_ref v_psy, run_acc a_psy)+ where+ {-# NOINLINE run_ref #-}+ run_ref psy () = blackscholesRef psy+ run_acc psy () = blackscholesAcc psy+
+ examples/tests/simple/DotP.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE ParallelListComp #-}++module DotP where++import Random++import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate as Acc+++-- Dot product+-- -----------+dotpAcc :: Vector Float -> Vector Float -> Acc (Scalar Float)+dotpAcc xs ys+ = let+ xs' = use xs+ ys' = use ys+ in+ Acc.fold (+) 0 (Acc.zipWith (*) xs' ys')++dotpRef :: UArray Int Float+ -> UArray Int Float+ -> UArray () Float+dotpRef xs ys+ = listArray ((), ()) [sum [x * y | x <- elems xs | y <- elems ys]]+++-- Main+-- ----++run :: Int -> IO (() -> UArray () Float, () -> Acc (Scalar Float))+run n = withSystemRandom $ \gen -> do+ v1 <- randomUArrayR (-1,1) gen n+ v2 <- randomUArrayR (-1,1) gen n+ v1' <- convertUArray v1+ v2' <- convertUArray v2+ --+ return (run_ref v1 v2, run_acc v1' v2')+ where+ {-# NOINLINE run_ref #-}+ run_ref xs ys () = dotpRef xs ys+ run_acc xs ys () = dotpAcc xs ys+
+ examples/tests/simple/Filter.hs view
@@ -0,0 +1,55 @@+{-# LANGUAGE FlexibleContexts #-}++module Filter where++import Random++import System.Random.MWC+import Data.Array.Unboxed (IArray, UArray, elems, listArray)+import Data.Array.Accelerate as Acc+++-- Filter+-- ------+filterAcc :: Elt a+ => (Exp a -> Exp Bool)+ -> Vector a+ -> Acc (Vector a)+filterAcc p vec+ = let arr = Acc.use vec+ flags = Acc.map (boolToInt . p) arr+ (targetIdx, len) = Acc.scanl' (+) 0 flags+ arr' = Acc.backpermute (index1 $ the len) id arr+ in+ Acc.permute const arr' (\ix -> flags!ix ==* 0 ? (ignore, index1 $ targetIdx!ix)) arr+ -- FIXME: This is abusing 'permute' in that the first two arguments are+ -- only justified because we know the permutation function will+ -- write to each location in the target exactly once.+ -- Instead, we should have a primitive that directly encodes the+ -- compaction pattern of the permutation function.+++filterRef :: IArray UArray e+ => (e -> Bool)+ -> UArray Int e+ -> UArray Int e+filterRef p xs+ = let xs' = Prelude.filter p (elems xs)+ in+ listArray (0, Prelude.length xs' - 1) xs'+++-- Main+-- ----++run :: Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run n = withSystemRandom $ \gen -> do+ vec <- randomUArrayR (-1,1) gen n+ vec' <- convertUArray vec+ --+ return (run_ref vec, run_acc vec')+ where+ {-# NOINLINE run_ref #-}+ run_ref xs () = filterRef (> 0) xs+ run_acc xs () = filterAcc (>*0) xs+
+ examples/tests/simple/Radix.hs view
@@ -0,0 +1,90 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE ScopedTypeVariables #-}+--+-- Radix sort for a subclass of element types+--++module Radix where++import Random++import Prelude as P+import Data.Array.Accelerate as A++import Data.Bits+import Data.List ( sort )+import Data.Array.Unboxed ( IArray, UArray, listArray, bounds, elems )+import System.Random.MWC+++-- Radix sort+-- ----------++class Elt e => Radix e where+ passes :: e {- dummy -} -> Int+ radix :: Exp Int -> Exp e -> Exp Int++instance Radix Int32 where+ passes = bitSize+ radix i e = i ==* (passes' - 1) ? (radix' (e `xor` minBound), radix' e)+ where+ radix' x = A.fromIntegral $ (x `A.shiftR` i) .&. 1+ passes' = constant (passes (undefined :: Int32))++-- For IEEE-754 floating-point representation. Unsafe, but widely supported.+-- TLM: unsafeCoerce does not work in the CUDA backend.+--+-- instance Radix Float where+-- passes _ = 32+-- radix i e = let x = (unsafeCoerce e :: Exp Int32)+-- in i ==* 31 ? (radix' (x `xor` minBound), radix' (floatFlip x))+-- where+-- floatFlip x = x `testBit` 31 ? (complement x, x) -- twos-complement negative numbers+-- radix' x = x `testBit` i ? (1,0)++--+-- A simple (parallel) radix sort implementation [1].+--+-- [1] G. E. Blelloch. "Prefix sums and their applications." Technical Report+-- CMU-CS-90-190. Carnegie Mellon University. 1990.+--+sortAcc :: Radix a => Acc (Vector a) -> Acc (Vector a)+sortAcc = sortAccBy id++sortAccBy+ :: forall a r. (Elt a, Radix r)+ => (Exp a -> Exp r)+ -> Acc (Vector a)+ -> Acc (Vector a)+sortAccBy rdx arr = foldr1 (>->) (P.map radixPass [0..p-1]) arr+ where+ p = passes (undefined :: r)+ --+ deal f x = let (a,b) = unlift x in (f ==* 0) ? (a,b)+ radixPass k v = let k' = unit (constant k)+ flags = A.map (radix (the k') . rdx) v+ idown = prescanl (+) 0 . A.map (xor 1) $ flags+ iup = A.map (size v - 1 -) . prescanr (+) 0 $ flags+ index = A.zipWith deal flags (A.zip idown iup)+ in+ permute const v (\ix -> index1 (index!ix)) v+++sortRef :: (Ord a, IArray UArray a) => UArray Int a -> UArray Int a+sortRef xs = listArray (bounds xs) $ sort (elems xs)+++-- Main+-- ----++run :: Int -> IO (() -> UArray Int Int32, () -> Acc (Vector Int32))+run n = withSystemRandom $ \gen -> do+ vec <- randomUArrayR (minBound,maxBound) gen n+ vec' <- use `fmap` convertUArray vec+ --+ return (run_ref vec, run_acc vec')+ where+ {-# NOINLINE run_ref #-}+ run_ref xs () = sortRef xs+ run_acc xs () = sortAcc xs+
+ examples/tests/simple/SASUM.hs view
@@ -0,0 +1,35 @@++module SASUM where++import Random++import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate as Acc+++-- Sum of absolute values+-- ----------------------+sasumAcc :: Vector Float -> Acc (Scalar Float)+sasumAcc xs+ = Acc.fold (+) 0 . Acc.map abs $ Acc.use xs++sasumRef :: UArray Int Float -> UArray () Float+sasumRef xs+ = listArray ((), ()) [Prelude.sum . Prelude.map abs $ elems xs]+++-- Main+-- ----++run :: Int -> IO (() -> UArray () Float, () -> Acc (Scalar Float))+run n = withSystemRandom $ \gen -> do+ vec <- randomUArrayR (-1,1) gen n+ vec' <- convertUArray vec+ --+ return (run_ref vec, run_acc vec')+ where+ {-# NOINLINE run_ref #-}+ run_ref xs () = sasumRef xs+ run_acc xs () = sasumAcc xs+
+ examples/tests/simple/SAXPY.hs view
@@ -0,0 +1,42 @@+{-# LANGUAGE ParallelListComp #-}++module SAXPY where++import Random++import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate as Acc++-- SAXPY+-- -----+saxpyAcc :: Float -> Vector Float -> Vector Float -> Acc (Vector Float)+saxpyAcc alpha xs ys+ = let+ xs' = use xs+ ys' = use ys+ in+ Acc.zipWith (\x y -> constant alpha * x + y) xs' ys'++saxpyRef :: Float -> UArray Int Float -> UArray Int Float -> UArray Int Float+saxpyRef alpha xs ys+ = listArray (bounds xs) [alpha * x + y | x <- elems xs | y <- elems ys]+++-- Main+-- ----++run :: Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run nelements = withSystemRandom $ \gen -> do+ v1 <- randomUArrayR (-1,1) gen nelements+ v2 <- randomUArrayR (-1,1) gen nelements+ v1' <- convertUArray v1+ v2' <- convertUArray v2+ alpha <- uniform gen+ --+ return (run_ref alpha v1 v2, run_acc alpha v1' v2')+ where+ {-# NOINLINE run_ref #-}+ run_ref alpha xs ys () = saxpyRef alpha xs ys+ run_acc alpha xs ys () = saxpyAcc alpha xs ys+
+ examples/tests/simple/SMVM.hs view
@@ -0,0 +1,78 @@+{-# LANGUAGE FlexibleContexts #-}++module SMVM where++import Random+import SMVM.Matrix++import System.Random.MWC+import Data.Array.Unboxed+import Data.Array.Accelerate (Vector, Segments, Acc)+import qualified Data.Array.Accelerate as Acc+import qualified Data.Vector.Unboxed as V+++-- Sparse-matrix vector multiplication+-- -----------------------------------++type SparseVector a = (Vector Int, Vector a)+type SparseMatrix a = (Segments Int, SparseVector a)++smvmAcc :: SparseMatrix Float -> Vector Float -> Acc (Vector Float)+smvmAcc (segd', (inds', vals')) vec'+ = let+ segd = Acc.use segd'+ inds = Acc.use inds'+ vals = Acc.use vals'+ vec = Acc.use vec'+ ---+ vecVals = Acc.backpermute (Acc.shape inds) (\i -> Acc.index1 $ inds Acc.! i) vec+ products = Acc.zipWith (*) vecVals vals+ in+ Acc.foldSeg (+) 0 products segd+++-- The reference version will be slow, with many conversions between+-- array/vector/list representations. This will likely skew heap usage+-- calculations, but oh well...+--+type USparseMatrix a = (UArray Int Int, (UArray Int Int, UArray Int a))++smvmRef :: USparseMatrix Float -> UArray Int Float -> UArray Int Float+smvmRef (segd, (inds, values)) vec+ = listArray (0, rangeSize (bounds segd) - 1)+ [sum [ values!i * vec!(inds!i) | i <- range seg] | seg <- segd' ]+ where+ segbegin = scanl (+) 0 $ elems segd+ segend = scanl1 (+) $ elems segd+ segd' = zipWith (\x y -> (x,y-1)) segbegin segend+++-- Main+-- ----++run :: Maybe FilePath -> IO (() -> UArray Int Float, () -> Acc (Vector Float))+run f = withSystemRandom $ \gen -> do+ -- sparse-matrix+ (segd', smat') <- maybe (randomCSRMatrix gen 512 512) (readCSRMatrix gen) f+ let (ind',val') = V.unzip smat'++ segd <- convertVector segd'+ ind <- convertVector ind'+ val <- convertVector val'+ let smat = (segd, (ind,val))++ -- vector+ vec' <- uniformVector gen (V.length segd')+ vec <- convertVector vec'++ -- multiply!+ return (run_ref (v2a segd', (v2a ind',v2a val')) (v2a vec'), run_acc smat vec)+ where+ {-# NOINLINE run_ref #-}+ run_ref smat vec () = smvmRef smat vec+ run_acc smat vec () = smvmAcc smat vec+ --+ v2a :: (V.Unbox a, IArray UArray a) => V.Vector a -> UArray Int a+ v2a vec = listArray (0, V.length vec - 1) $ V.toList vec+
+ examples/tests/simple/SMVM/Matrix.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE BangPatterns, TupleSections #-}++module SMVM.Matrix (readCSRMatrix, randomCSRMatrix) where++import Random+import SMVM.MatrixMarket+import System.Random.MWC+import System.IO.Unsafe++import Data.Vector.Unboxed (Vector)+import qualified Data.Vector.Unboxed as V+import qualified Data.Vector.Unboxed.Mutable as M+import qualified Data.Vector.Algorithms.Intro as V++type CSRMatrix a = (Vector Int, Vector (Int,a))+++-- Read a sparse matrix from a MatrixMarket file. Pattern matrices are filled+-- with random numbers in the range (-1,1).+--+{-# INLINE readCSRMatrix #-}+readCSRMatrix :: GenIO -> FilePath -> IO (CSRMatrix Float)+readCSRMatrix gen file = do+ mtx <- readMatrix file+ case mtx of+ (RealMatrix dim l vals) -> csr dim l vals+ (PatternMatrix dim l ix) -> csr dim l =<< mapM' (\(a,b) -> (a,b,) `fmap` uniformR (-1,1) gen) ix+ (IntMatrix _ _ _) -> error "IntMatrix type not supported"+ (ComplexMatrix _ _ _) -> error "ComplexMatrix type not supported"+++-- A randomly generated matrix of given size+--+{-# INLINE randomCSRMatrix #-}+randomCSRMatrix :: GenIO -> Int -> Int -> IO (CSRMatrix Float)+randomCSRMatrix gen rows cols = do+ segd <- randomVectorR ( 0,cols`div`3) gen rows+ let nnz = V.sum segd+ inds <- randomVectorR ( 0,cols-1) gen nnz+ vals <- randomVectorR (-1,1) gen nnz+ return (segd, V.zip inds vals)+++-- Read elements into unboxed arrays, convert to zero-indexed compress sparse+-- row format.+--+{-# INLINE csr #-}+csr :: (Int,Int) -> Int -> [(Int,Int,Float)] -> IO (Vector Int, Vector (Int,Float))+csr (m,_) l elems = do+ mu <- M.new l+ let goe _ [] = return ()+ goe !n (x:xs) = let (i,j,v) = x in M.unsafeWrite mu n (i-1,j-1,v) >> goe (n+1) xs+ goe 0 elems++ let cmp (x1,y1,_) (x2,y2,_) | x1 == x2 = compare y1 y2+ | otherwise = compare x1 x2+ V.sortBy cmp mu++ (i,j,v) <- V.unzip3 `fmap` V.unsafeFreeze mu+ mseg <- M.new m+ let gos !n rows | n < m = let (s,ss) = V.span (==n) rows in M.unsafeWrite mseg n (V.length s) >> gos (n+1) ss+ | otherwise = V.unsafeFreeze mseg+ seg <- gos 0 i+ return (seg , V.zip j v)+++-- Lazier versions of things in Control.Monad+--+sequence' :: [IO a] -> IO [a]+sequence' ms = foldr k (return []) ms+ where k m m' = do { x <- m; xs <- unsafeInterleaveIO m'; return (x:xs) }++mapM' :: (a -> IO b) -> [a] -> IO [b]+mapM' f as = sequence' (map f as)+
+ examples/tests/simple/SMVM/MatrixMarket.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE OverloadedStrings, GADTs, StandaloneDeriving #-}++module SMVM.MatrixMarket (Matrix(..), readMatrix) where++import Control.Applicative hiding ( many )++import Data.Complex+import Data.Attoparsec.Char8+import Data.ByteString.Lex.Double+import qualified Data.Attoparsec.Lazy as L+import qualified Data.ByteString.Lazy as L+++-- | Specifies the element type. Pattern matrices do not have any elements,+-- only indices, and only make sense for coordinate matrices and vectors.+--+data Field = Real | Complex | Integer | Pattern+ deriving (Eq, Show)++-- | Specifies either sparse or dense storage. In sparse (\"coordinate\")+-- storage, elements are given in (i,j,x) triplets for matrices (or (i,x) for+-- vectors). Indices are 1-based, so that A(1,1) is the first element of a+-- matrix, and x(1) is the first element of a vector.+--+-- In dense (\"array\") storage, elements are given in column-major order.+--+-- In both cases, each element is given on a separate line.+--+data Format = Coordinate | Array+ deriving (Eq, Show)++-- | Specifies any special structure in the matrix. For symmetric and hermition+-- matrices, only the lower-triangular part of the matrix is given. For skew+-- matrices, only the entries below the diagonal are stored.+--+data Structure = General | Symmetric | Hermitian | Skew+ deriving (Eq, Show)+++-- We really want a type parameter to Matrix, but I think that requires some+-- kind of dynamic typing so that we can determine (a ~ Integral) or (a ~+-- RealFloat), and so forth, depending on the file being read. This will do for+-- our purposes...+--+-- Format is: (rows,columns) nnz [(row,column,value)]+--+data Matrix where+ PatternMatrix :: (Int,Int) -> Int -> [(Int,Int)] -> Matrix+ IntMatrix :: (Int,Int) -> Int -> [(Int,Int,Int)] -> Matrix+ RealMatrix :: (Int,Int) -> Int -> [(Int,Int,Float)] -> Matrix+ ComplexMatrix :: (Int,Int) -> Int -> [(Int,Int,Complex Float)] -> Matrix++deriving instance Show Matrix+++--------------------------------------------------------------------------------+-- Combinators+--------------------------------------------------------------------------------++comment :: Parser ()+comment = char '%' *> skipWhile (not . eol) *> endOfLine+ where eol w = w `elem` "\n\r"++floating :: Fractional a => Parser a+floating = do+ mv <- readDouble <$> (skipSpace *> takeTill isSpace) -- readDouble does the fancy stuff+ case mv of+ Just (v,_) -> return . realToFrac $ v+ Nothing -> fail "floating-point number"++integral :: Integral a => Parser a+integral = skipSpace *> decimal++format :: Parser Format+format = string "coordinate" *> pure Coordinate+ <|> string "array" *> pure Array+ <?> "matrix format"++field :: Parser Field+field = string "real" *> pure Real+ <|> string "complex" *> pure Complex+ <|> string "integer" *> pure Integer+ <|> string "pattern" *> pure Pattern+ <?> "matrix field"++structure :: Parser Structure+structure = string "general" *> pure General+ <|> string "symmetric" *> pure Symmetric+ <|> string "hermitian" *> pure Hermitian+ <|> string "skew-symmetric" *> pure Skew+ <?> "matrix structure"++header :: Parser (Format,Field,Structure)+header = string "%%MatrixMarket matrix"+ >> (,,) <$> (skipSpace *> format)+ <*> (skipSpace *> field)+ <*> (skipSpace *> structure)+ <* endOfLine+ <?> "MatrixMarket header"++extent :: Parser (Int,Int,Int)+extent = do+ [m,n,l] <- skipWhile isSpace *> count 3 integral <* endOfLine+ return (m,n,l)++line :: Parser a -> Parser (Int,Int,a)+line f = (,,) <$> integral+ <*> integral+ <*> f+ <* endOfLine++--------------------------------------------------------------------------------+-- Matrix Market+--------------------------------------------------------------------------------++matrix :: Parser Matrix+matrix = do+ (_,t,_) <- header+ (m,n,l) <- skipMany comment *> extent+ case t of+ Real -> RealMatrix (m,n) l `fmap` many1 (line floating)+ Complex -> ComplexMatrix (m,n) l `fmap` many1 (line ((:+) <$> floating <*> floating))+ Integer -> IntMatrix (m,n) l `fmap` many1 (line integral)+ Pattern -> PatternMatrix (m,n) l `fmap` many1 ((,) <$> integral <*> integral)+++readMatrix :: FilePath -> IO Matrix+readMatrix file = do+ chunks <- L.readFile file+ case L.parse matrix chunks of+ L.Fail _ _ msg -> error $ file ++ ": " ++ msg+ L.Done _ mtx -> return mtx+
+ examples/tests/simple/SharingRecovery.hs view
@@ -0,0 +1,145 @@+{-# LANGUAGE TypeOperators, ScopedTypeVariables #-}+++--+-- Some tests to make sure that sharing recovery is working.+--+module SharingRecovery where++import Prelude hiding (zip3)++import Data.Array.Accelerate as Acc+++mkArray :: Int -> Acc (Array DIM1 Int)+mkArray n = use $ fromList (Z:.1) [n]++muchSharing :: Int -> Acc (Array DIM1 Int)+muchSharing 0 = (mkArray 0)+muchSharing n = Acc.map (\_ -> newArr ! (lift (Z:.(0::Int))) ++ newArr ! (lift (Z:.(1::Int)))) (mkArray n)+ where+ newArr = muchSharing (n-1)++idx :: Int -> Exp DIM1+idx i = lift (Z:.i)++bfsFail :: Acc (Array DIM1 Int)+bfsFail = Acc.map (\x -> (map2 ! (idx 1)) + (map1 ! (idx 2)) + x) arr+ where+ map1 :: Acc (Array DIM1 Int)+ map1 = Acc.map (\y -> (map2 ! (idx 3)) + y) arr+ map2 :: Acc (Array DIM1 Int)+ map2 = Acc.map (\z -> z + 1) arr+ arr :: Acc (Array DIM1 Int)+ arr = mkArray 666++twoLetsSameLevel :: Acc (Array DIM1 Int)+twoLetsSameLevel =+ let arr1 = mkArray 1+ in let arr2 = mkArray 2+ in Acc.map (\_ -> arr1!(idx 1) + arr1!(idx 2) + arr2!(idx 3) + arr2!(idx 4)) (mkArray 3)++twoLetsSameLevel2 :: Acc (Array DIM1 Int)+twoLetsSameLevel2 =+ let arr2 = mkArray 2+ in let arr1 = mkArray 1+ in Acc.map (\_ -> arr1!(idx 1) + arr1!(idx 2) + arr2!(idx 3) + arr2!(idx 4)) (mkArray 3)++--+-- These two programs test that lets can be introduced not just at the top of a AST+-- but in intermediate nodes.+--+noLetAtTop :: Acc (Array DIM1 Int)+noLetAtTop = Acc.map (\x -> x + 1) bfsFail++noLetAtTop2 :: Acc (Array DIM1 Int)+noLetAtTop2 = Acc.map (\x -> x + 2) $ Acc.map (\x -> x + 1) bfsFail++--+--+--+simple :: Acc (Array DIM1 (Int,Int))+simple = Acc.map (\_ -> a ! (idx 1)) d+ where+ c = use $ Acc.fromList (Z :. 3) [1..]+ d = Acc.map (+1) c+ a = Acc.zip d c++--------------------------------------------------------------------------------+--+-- sortKey is a real program that Ben Lever wrote. It has some pretty interesting+-- sharing going on.+--+sortKey :: (Elt e)+ => (Exp e -> Exp Int) -- ^mapping function to produce key array from input array+ -> Acc (Vector e)+ -> Acc (Vector e)+sortKey keyFun arr = foldl sortOneBit arr (Prelude.map lift ([0..31] :: [Int]))+ where+ sortOneBit inArr bitNum = outArr+ where+ keys = Acc.map keyFun inArr++ bits = Acc.map (\a -> (Acc.testBit a bitNum) ? (1, 0)) keys+ bitsInv = Acc.map (\b -> (b ==* 0) ? (1, 0)) bits++ (falses, numZeroes) = Acc.scanl' (+) 0 bitsInv+ trues = Acc.map (\x -> (Acc.the numZeroes) + (Acc.fst x) - (Acc.snd x)) $+ Acc.zip ixs falses++ dstIxs = Acc.map (\x -> let (b, t, f) = unlift x in (b ==* (constant (0::Int))) ? (f, t)) $+ zip3 bits trues falses+ outArr = scatter dstIxs inArr inArr -- just use input as default array+ --(we're writing over everything anyway)+ --+ ixs = enumeratedArray (shape arr)++-- | Create an array where each element is the value of its corresponding row-major+-- index.+--+--enumeratedArray :: (Shape sh) => Exp sh -> Acc (Array sh Int)+--enumeratedArray sh = Acc.reshape sh+-- $ Acc.generate (index1 $ shapeSize sh) unindex1++enumeratedArray :: Exp DIM1 -> Acc (Array DIM1 Int)+enumeratedArray sh = Acc.generate sh unindex1++testSort :: Acc (Vector Int)+testSort = sortKey id $ use $ fromList (Z:.10) [9,8,7,6,5,4,3,2,1,0]++----------------------------------------------------------------------++--+-- map1 has children map3 and map2.+-- map2 has child map3.+-- Back when we still used a list for the NodeCounts data structure this mean that+-- you would be merging [1,3,2] with [2,3] which violated precondition of (+++).+-- This tests that the new algorithm works just fine on this.+--+orderFail :: Acc (Array DIM1 Int)+orderFail = Acc.map (\_ -> map1 ! (idx 1) + map2 ! (idx 1)) arr+ where+ map1 = Acc.map (\_ -> map3 ! (idx 1) + map2 ! (idx 2)) arr+ map2 = Acc.map (\_ -> map3 ! (idx 3)) arr+ map3 = Acc.map (+1) arr+ arr = mkArray 42++----------------------------------------------------------------------++-- Tests array-valued lambdas in conjunction with sharing recovery.+--+pipe :: Acc (Vector Int)+pipe = (acc1 >-> acc2) xs+ where+ z :: Acc (Scalar Int)+ z = unit 0++ xs :: Acc (Vector Int)+ xs = use $ fromList (Z:.10) [0..]++ acc1 :: Acc (Vector Int) -> Acc (Vector Int)+ acc1 = Acc.map (\_ -> the z)++ acc2 :: Acc (Vector Int) -> Acc (Vector Int)+ acc2 arr = let arr2 = use $ fromList (Z:.10) [10..] in Acc.map (\_ -> arr2!constant (Z:.(0::Int))) (Acc.zip arr arr2)
+ examples/tests/simple/SliceExamples.hs view
@@ -0,0 +1,115 @@+{-# LANGUAGE TypeOperators, ScopedTypeVariables #-}+module SliceExamples where++import Data.Array.Accelerate as Acc+import qualified Data.Array.Unboxed as UA++-- y+-- ^+-- | 3 4 +-- | 1 2+-- -------> x+--+arr :: Acc (Array DIM2 Int)+arr = use $ fromList (Z:.2:.2) [1,2,3,4]++slice1 :: Exp (Z:.Int:.All:.All)+slice1 = lift $ Z:.(2::Int):.All:.All++slice2 :: Exp (Z:.All:.Int:.All)+slice2 = lift $ Z:.All:.(2::Int):.All++slice3 :: Exp (Z:.All:.All:.Int)+slice3 = lift $ Z:.All:.All:.(2::Int)++-- Replicate into z-axis+-- should produce [1,2,3,4,1,2,3,4]+test1 :: Acc (Array DIM3 Int)+test1 = Acc.replicate slice1 arr++-- Replicate into y-axis+-- should produce [1,2,1,2,3,4,3,4]+test2 :: Acc (Array DIM3 Int)+test2 = Acc.replicate slice2 arr++-- Replicate into x-axis+-- should produce [1,1,2,2,3,3,4,4]+test3 :: Acc (Array DIM3 Int)+test3 = Acc.replicate slice3 arr++--+-- repN. Replicates an array into the rightmost dimension of+-- the result array.+--+repN :: forall sh e. (Shape sh, Elt e)+ => Int + -> Acc (Array sh e)+ -> Acc (Array (sh:.Int) e)+repN n a = Acc.replicate (lift (Any:.n :: Any sh:.Int)) a++repExample :: Acc (Array DIM2 Int) -> Acc (Array DIM3 Int)+repExample = repN 2++repExample' :: Acc (Array DIM2 Int) -> Acc (Array DIM3 Int)+repExample' = Acc.replicate (lift (Z:.All:.All:.(2::Int)))++slice1' :: Any (Z:.Int:.Int) :. Int+slice1' = Any:.2++slice2' :: Z:.All:.All:.Int+slice2' = Z:.All:.All:.2++run1 :: IO (() -> UA.UArray (Int,Int,Int) Int, () -> Acc (Array DIM3 Int))+run1 = return (\() -> UA.array ((0,0,0),(1,1,1)) [ ((0,0,0), 1)+ , ((0,0,1), 2)+ , ((0,1,0), 3)+ , ((0,1,1), 4)+ , ((1,0,0), 1)+ , ((1,0,1), 2)+ , ((1,1,0), 3)+ , ((1,1,1), 4) ]+ ,\() -> test1)+++run2 :: IO (() -> UA.UArray (Int,Int,Int) Int, () -> Acc (Array DIM3 Int))+run2 = return (\() -> UA.array ((0,0,0),(1,1,1)) [ ((0,0,0), 1)+ , ((0,0,1), 2)+ , ((0,1,0), 1)+ , ((0,1,1), 2)+ , ((1,0,0), 3)+ , ((1,0,1), 4)+ , ((1,1,0), 3)+ , ((1,1,1), 4) ]+ ,\() -> test2)++run3 :: IO (() -> UA.UArray (Int,Int,Int) Int, () -> Acc (Array DIM3 Int))+run3 = return (\() -> UA.array ((0,0,0),(1,1,1)) [ ((0,0,0), 1)+ , ((0,0,1), 1)+ , ((0,1,0), 2)+ , ((0,1,1), 2)+ , ((1,0,0), 3)+ , ((1,0,1), 3)+ , ((1,1,0), 4)+ , ((1,1,1), 4) ]+ ,\() -> test3)+run4 :: IO (() -> UA.UArray (Int,Int,Int) Int, () -> Acc (Array DIM3 Int))+run4 = return (\() -> UA.array ((0,0,0),(1,1,1)) [ ((0,0,0), 1)+ , ((0,0,1), 1)+ , ((0,1,0), 2)+ , ((0,1,1), 2)+ , ((1,0,0), 3)+ , ((1,0,1), 3)+ , ((1,1,0), 4)+ , ((1,1,1), 4) ]+ ,\() -> repExample arr)++run5 :: IO (() -> UA.UArray (Int,Int,Int) Int, () -> Acc (Array DIM3 Int))+run5 = return (\() -> UA.array ((0,0,0),(1,1,1)) [ ((0,0,0), 1)+ , ((0,0,1), 1)+ , ((0,1,0), 2)+ , ((0,1,1), 2)+ , ((1,0,0), 3)+ , ((1,0,1), 3)+ , ((1,1,0), 4)+ , ((1,1,1), 4) ]+ ,\() -> repExample' arr)
− src/Benchmark.hs
@@ -1,58 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}-{-# OPTIONS_GHC -fno-warn-orphans #-}--module Benchmark where--import Data.Array.IArray-import Data.Array.Unboxed (UArray)--import Data.List-import Data.Monoid-import Criterion-import Criterion.IO-import Criterion.Config-import Criterion.Main-import Criterion.Monad-import Criterion.Types-import Criterion.Environment-import Control.Monad-import Control.Monad.Trans (liftIO)-import Control.DeepSeq-import System.IO-import System.Directory-import System.Environment---instance (Ix dim, IArray UArray e) => NFData (UArray dim e) where- rnf a = a ! head (indices a) `seq` ()----- Much like defaultMain, but we ignore any non-flag command line arguments,--- which we take as the inputs to the program itself (returned via getArg')----runBenchmark :: [Benchmark] -> IO ()-runBenchmark = runBenchmarkWith defaultConfig (return ())--runBenchmarkWith :: Config -> Criterion () -> [Benchmark] -> IO ()-runBenchmarkWith defCfg prep bs = do- (cfg, _) <- parseArgs defCfg defaultOptions =<< getArgs- withConfig cfg $- if cfgPrintExit cfg == List- then do- _ <- note "Benchmarks:\n"- mapM_ (note " %s\n") (sort $ concatMap benchNames bs)- else do- case getLast $ cfgSummaryFile cfg of- Just fn -> liftIO $ writeFileOnce fn "Name,Mean,MeanLB,MeanUB,Stddev,StddevLB,StddevUB\n"- Nothing -> return ()- env <- measureEnvironment- let shouldRun = const True- prep- runAndAnalyse shouldRun env $ BenchGroup "" bs--writeFileOnce :: FilePath -> String -> IO ()-writeFileOnce fn line = do- exists <- doesFileExist fn- size <- withFile fn ReadWriteMode hFileSize- unless (exists && size > 0) $ writeFile fn line-
− src/Config.hs
@@ -1,135 +0,0 @@-{-# LANGUAGE CPP, DeriveDataTypeable #-}--module Config where--import Data.Version-import Text.PrettyPrint-import System.Console.CmdArgs-import Paths_accelerate_examples---- The Accelerate backends available to test, which should be no larger than the--- build configuration for the Accelerate library itself.----data Backend- = Interpreter-#ifdef ACCELERATE_CUDA_BACKEND- | CUDA-#endif- deriving (Show, Data, Typeable)----- Program configuration options----data Config = Config- {- -- common options- cfgBackend :: Backend- , cfgVerify :: Bool- , cfgElements :: Int- , cfgImage :: Maybe FilePath- , cfgMatrix :: Maybe FilePath-- -- criterion hooks- , cfgPerformGC :: Bool- , cfgConfidence :: Maybe Double- , cfgResamples :: Maybe Int- , cfgSummaryFile :: Maybe FilePath-- -- names of tests to run (all non-option arguments)- , cfgArgs :: [String]- }- deriving (Show, Data, Typeable)----- With list of (name,description) pairs for the available tests----defaultConfig :: [(String,String)] -> Config-defaultConfig testPrograms = Config- {- cfgBackend = enum- [ Interpreter- &= help "Reference implementation (sequential)"-#ifdef ACCELERATE_CUDA_BACKEND- , CUDA- &= explicit- &= name "cuda"- &= help "Implementation for NVIDIA GPUs (parallel)"-#endif- ]-- , cfgVerify = def- &= explicit- &= name "k"- &= name "verify"- &= help "Only verify examples, do not run timing tests"-- , cfgElements = 1000000- &= explicit- &= name "n"- &= name "size"- &= help "Canonical test data size (1000000)"-- , cfgImage = def- &= explicit- &= name "i"- &= name "image"- &= help "PGM image file to use for image-processing tests"- &= typFile-- , cfgMatrix = def- &= name "m"- &= name "matrix"- &= explicit- &= help "MatrixMarket file to use for SMVM test"- &= typFile-- , cfgPerformGC = enum- [ False- &= name "G"- &= name "no-gc"- &= explicit- &= help "Do not collect garbage between iterations"- , True- &= name "g"- &= name "gc"- &= explicit- &= help "Collect garbage between iterations"- ]-- , cfgConfidence = def- &= explicit- &= name "I"- &= name "ci"- &= help "Bootstrap confidence interval"- &= typ "CI"-- , cfgResamples = def- &= explicit- &= name "s"- &= name "resamples"- &= help "Number of bootstrap resamples to perform"-- , cfgSummaryFile = def- &= name "u"- &= name "summary"- &= explicit- &= help "Produce a summary CSV file of all results"- &= typFile-- , cfgArgs = def- &= args- &= typ "TESTS"- }- &= program "accelerate-examples"- &= summary "accelerate-examples (c) 2011 The Accelerate Team"- &= versionArg [summary $ "accelerate-examples-" ++ showVersion version]- &= verbosityArgs [help "Print more output"] [help "Print less output"]- &= details (- [ "Available tests, by prefix match:"- , " <default> run all tests"- ]- ++- map (\(n,d) -> render . nest 2 $ text n $$ nest 22 (text d)) testPrograms)- --- -- magic number to make the second columns of the help text align-
− src/Main.hs
@@ -1,74 +0,0 @@-{-# LANGUAGE TupleSections #-}--module Main where--import Test-import Config-import Benchmark--import Prelude hiding (catch)-import Data.List-import Data.Maybe-import Control.Arrow-import Control.Monad-import System.Environment-import System.Console.CmdArgs (cmdArgs, getVerbosity, Verbosity(..))----- Process command line options, prepare selected test programs for benchmarking--- or verification----processArgs :: IO (Config, [Test])-processArgs = do- testInfo <- map (title &&& description) `fmap` allTests undefined- config <- cmdArgs $ defaultConfig testInfo- tests <- filter (selected config) `fmap` allTests config- --- return (config, tests)- where- selected a = case cfgArgs a of- [] -> const True- ps -> \x -> any (\p -> p `isPrefixOf` title x) ps----- Verify results with the chosen backend, turning exceptions into failures.--- Pass back the tests which succeeded.----runVerify :: Config -> [Test] -> IO [Test]-runVerify cfg tests = do- results <- forM tests $ \t -> (t,) `fmap` verifyTest cfg t- return . map fst- $ filter (\(_,r) -> r `elem` [Ok, Skipped]) results----- Run criterion timing tests in the chosen backend----runTiming :: Config -> [Test] -> IO ()-runTiming cfg tests = do- verbose <- getVerbosity- unless (verbose == Quiet) $ putStrLn ""- let args = [ maybe "" (\ci -> "--ci=" ++ show ci) (cfgConfidence cfg)- , maybe "" (\r -> "--resamples=" ++ show r) (cfgResamples cfg)- , maybe "" (\f -> "--summary=" ++ f) (cfgSummaryFile cfg)- , if cfgPerformGC cfg then "-g" else "-G"- , case verbose of- Loud -> "--verbose"- Quiet -> "--quiet"- Normal -> ""- ]- --- withArgs args- . runBenchmark- . catMaybes- $ map (benchmarkTest cfg) tests----- Main--- ====--main :: IO ()-main = do- (config, tests) <- processArgs- valid <- runVerify config tests- --- unless (null valid || cfgVerify config) $ runTiming config valid
− src/Random.hs
@@ -1,72 +0,0 @@-{-# LANGUAGE BangPatterns, FlexibleContexts #-}--module Random where--import System.Random.MWC-import Data.Array.IArray-import Data.Array.Unboxed (UArray)-import Data.Array.IO (MArray, IOUArray)-import Control.Exception (evaluate)-import Data.Array.Accelerate (Z(..),(:.)(..))-import qualified Data.Vector.Generic as G-import qualified Data.Vector.Generic.Mutable as GM-import qualified Data.Array.MArray as M-import qualified Data.Array.Accelerate as Acc----- Convert an Unboxed Data.Array to an Accelerate Array----convertUArray :: (IArray UArray e, Acc.Elt e) => UArray Int e -> IO (Acc.Vector e)-convertUArray v =- let arr = Acc.fromIArray v- in evaluate (arr `Acc.indexArray` (Z:.0)) >> return arr----- Convert a Data.Vector to an Accelerate Array----convertVector- :: (IArray UArray a, MArray IOUArray a IO, G.Vector v a, Acc.Elt a)- => v a- -> IO (Acc.Vector a)--convertVector vec = do- arr <- Acc.fromIArray `fmap` toIArray vec- evaluate (arr `Acc.indexArray` (Z:.0)) >> return arr- where- toIArray :: (MArray IOUArray a IO, IArray UArray a, G.Vector v a) => v a -> IO (UArray Int a)- toIArray v = do- let n = G.length v- mu <- M.newArray_ (0,n-1) :: MArray IOUArray a IO => IO (IOUArray Int a)- let go !i | i < n = M.writeArray mu i (G.unsafeIndex v i) >> go (i+1)- | otherwise = M.unsafeFreeze mu- go 0----- Generate a random, uniformly distributed vector of specified size over the--- range. For integral types the range is inclusive, for floating point numbers--- the range (a,b] is used, if one ignores rounding errors.----randomUArrayR- :: (Variate a, MArray IOUArray a IO, IArray UArray a)- => (a,a)- -> GenIO- -> Int- -> IO (UArray Int a)--randomUArrayR lim gen n = do- mu <- M.newArray_ (0,n-1) :: MArray IOUArray e IO => IO (IOUArray Int e)- let go !i | i < n = uniformR lim gen >>= M.writeArray mu i >> go (i+1)- | otherwise = M.unsafeFreeze mu- go 0----- Generate a uniformly distributed Data.Vector of specified range and size----randomVectorR :: (G.Vector v a, Variate a) => (a,a) -> GenIO -> Int -> IO (v a)-randomVectorR lim gen n = do- mu <- GM.unsafeNew n- let go !i | i < n = uniformR lim gen >>= GM.unsafeWrite mu i >> go (i+1)- | otherwise = G.unsafeFreeze mu- go 0--
− src/Test.hs
@@ -1,234 +0,0 @@-{-# LANGUAGE CPP, ExistentialQuantification #-}--module Test (-- Title, Description, Test(..), Status(..),- allTests, verifyTest, benchmarkTest--) where---- individual test implementations-import qualified Map-import qualified Zip-import qualified ZipWith-import qualified Fold-import qualified ScanSeg-import qualified Stencil-import qualified Stencil2-import qualified Permute-import qualified Backpermute--import qualified SASUM-import qualified SAXPY-import qualified DotP-import qualified Filter-import qualified SMVM-import qualified BlackScholes-import qualified Radix-import qualified SliceExamples--#ifdef ACCELERATE_IO-import qualified BlockCopy-#endif--import qualified Canny-import qualified IntegralImage-import qualified SharingRecovery---- friends-import Util-import Config-import Validate---- libraries-import Prelude hiding (catch)-import Criterion (Benchmark, bench, whnf)-import Data.Maybe-import Data.Array.IArray-import Control.Monad-import Control.Exception-import System.IO-import System.IO.Unsafe-import System.Console.CmdArgs (getVerbosity, Verbosity(..))--import Data.Array.Accelerate (Acc)-import qualified Data.Array.Accelerate as Acc-import qualified Data.Array.Accelerate.Interpreter as Interpreter--#ifdef ACCELERATE_CUDA_BACKEND-import qualified Data.Array.Accelerate.CUDA as CUDA-#endif---data Status- = Ok- | Skipped- | Failed String--instance Eq Status where- Ok == Ok = True- Skipped == Skipped = True- _ == _ = False--instance Show Status where- show Ok = "Ok"- show Skipped = "Skipped"- show (Failed s) = "Failed: " ++ s---type Title = String-type Description = String--data Test- -- A cannonical test program, where we have a reference implementation that- -- the Accelerate program must match. The 'convert' field is slightly magic:- -- we need to carry it around as a proof that ELtRepr sh ~ EltRepr ix.- --- = forall array ix sh e. (Similar e, Acc.Elt e, Acc.Shape sh, Show ix, Show e, IArray array e, Ix ix) => Test- { title :: Title- , description :: Description- , reference :: () -> array ix e- , accelerate :: () -> Acc (Acc.Array sh e)- , convert :: Acc.Array sh e -> array ix e- }-- -- No reference implementation, so the result can not be validated, but we can- -- check that no exceptions are thrown, and benchmark the operation.- --- | forall sh e. (Acc.Elt e, Acc.Shape sh) => TestNoRef- { title :: Title- , description :: Description- , accelerate :: () -> Acc (Acc.Array sh e)- }-- -- An IO action. Run once to verify that no exceptions are thrown, do not- -- benchmark.- --- | forall a. TestIO- { title :: Title- , description :: Description- , action :: IO a- }---allTests :: Config -> IO [Test]-allTests cfg = sequence'- [-- -- primitive functions- mkTest "map-abs" "absolute value of each element" $ Map.run "abs" n- , mkTest "map-plus" "add a constant to each element" $ Map.run "plus" n- , mkTest "map-square" "square of each element" $ Map.run "square" n- , mkTest "zip" "vector zip" $ Zip.run n- , mkTest "zipWith-plus" "element-wise addition" $ ZipWith.run "plus" n- , mkTest "fold-sum" "vector reduction: fold (+) 0" $ Fold.run "sum" n- , mkTest "fold-product" "vector product: fold (*) 1" $ Fold.run "product" n- , mkTest "fold-maximum" "maximum of a vector: fold1 max" $ Fold.run "maximum" n- , mkTest "fold-minimum" "minimum of a vector: fold1 min" $ Fold.run "minimum" n- , mkTest "fold-2d-sum" "reduction along innermost matrix dimension" $ Fold.run2d "sum-2d" n- , mkTest "fold-2d-product" "product along innermost matrix dimension" $ Fold.run2d "product-2d" n- , mkTest "scanseg-sum" "segmented reduction" $ ScanSeg.run "sum" n- , mkTest "stencil-1D" "3-element vector" $ Stencil.run "1D" n- , mkTest "stencil-2D" "3x3 pattern" $ Stencil.run2D "2D" n- , mkTest "stencil-3D" "3x3x3 pattern" $ Stencil.run3D "3D" n- , mkTest "stencil-3x3-cross" "3x3 cross pattern" $ Stencil.run2D "3x3-cross" n- , mkTest "stencil-3x3-pair" "3x3 non-symmetric pattern with pairs" $ Stencil.run2D "3x3-pair" n- , mkTest "stencil2-2D" "3x3 pattern" $ Stencil2.run2D "2D" n- , mkTest "permute-hist" "histogram" $ Permute.run "histogram" n- , mkTest "backpermute-reverse" "reverse a vector" $ Backpermute.run "reverse" n- , mkTest "backpermute-transpose" "transpose a matrix" $ Backpermute.run2d "transpose" n-- -- simple examples- , mkTest "sasum" "sum of absolute values" $ SASUM.run n- , mkTest "saxpy" "scalar alpha*x + y" $ SAXPY.run n- , mkTest "dotp" "vector dot-product" $ DotP.run n- , mkTest "filter" "return elements that satisfy a predicate" $ Filter.run n- , mkTest "smvm" "sparse-matrix vector multiplication" $ SMVM.run (cfgMatrix cfg)- , mkTest "black-scholes" "Black-Scholes option pricing" $ BlackScholes.run n- , mkTest "radixsort" "radix sort" $ Radix.run n--#ifdef ACCELERATE_IO- -- Array IO- , mkIO "io" "array IO test" $ BlockCopy.run-#endif-- -- image processing- , mkNoRef "canny" "canny edge detection" $ Canny.run img- , mkNoRef "integral-image" "image integral (2D scan)" $ IntegralImage.run img- -- slices- , mkTest "slices" "replicate (Z:.2:.All:.All)" $ SliceExamples.run1- , mkTest "slices" "replicate (Z:.All:.2:.All)" $ SliceExamples.run2- , mkTest "slices" "replicate (Z:.All:.All:.2)" $ SliceExamples.run3- , mkTest "slices" "replicate (Any:.2)" $ SliceExamples.run4 - , mkTest "slices" "replicate (Z:.2:.2:.2)" $ SliceExamples.run5- --- , mkIO "sharing-recovery" "simple" $ return (show SharingRecovery.simple)- , mkIO "sharing-recovery" "orderFail" $ return (show SharingRecovery.orderFail)- , mkIO "sharing-recovery" "testSort" $ return (show SharingRecovery.testSort)- , mkIO "sharing-recovery" "muchSharing" $ return (show $ SharingRecovery.muchSharing 20)- , mkIO "sharing-recovery" "bfsFail" $ return (show SharingRecovery.bfsFail)- , mkIO "sharing-recovery" "twoLetsSameLevel" $ return (show SharingRecovery.twoLetsSameLevel)- , mkIO "sharing-recovery" "twoLetsSameLevel2" $ return (show SharingRecovery.twoLetsSameLevel2)- , mkIO "sharing-recovery" "noLetAtTop" $ return (show SharingRecovery.noLetAtTop)- , mkIO "sharing-recovery" "noLetAtTop2" $ return (show SharingRecovery.noLetAtTop2)- , mkIO "sharing-recovery" "pipe" $ return (show SharingRecovery.pipe)- ]- where- n = cfgElements cfg- img = fromMaybe (error "no image file specified") (cfgImage cfg)- --- mkTest name desc builder = do- ~(ref,acc) <- unsafeInterleaveIO builder -- must be super lazy- return $ Test name desc ref acc Acc.toIArray-- mkNoRef name desc builder = do- acc <- unsafeInterleaveIO builder- return $ TestNoRef name desc acc-- mkIO name desc act = return $ TestIO name desc act----- How to evaluate Accelerate programs with the chosen backend?----backend :: Acc.Arrays a => Config -> Acc a -> a-backend cfg =- case cfgBackend cfg of- Interpreter -> Interpreter.run-#ifdef ACCELERATE_CUDA_BACKEND- CUDA -> CUDA.run-#endif----- Verify that the Accelerate and reference implementations yield the same--- result in the chosen backend----verifyTest :: Config -> Test -> IO Status-verifyTest cfg test = do- quiet <- (==Quiet) `fmap` getVerbosity- verify quiet `catch` \e -> let r = Failed (show (e :: SomeException))- in putStrLn (show r) >> return r- where- run acc = backend cfg $ acc ()- verify quiet = do- unless quiet $ putStr (title test ++ ": ") >> hFlush stdout- result <- case test of- Test _ _ ref acc cvt ->- return $ case validate (ref ()) (cvt $ run acc) of- [] -> Ok- errs -> Failed . unlines . ("":)- $ map (\(i,v) -> ">>> " ++ shows i " : " ++ show v) errs-- TestNoRef _ _ acc -> return $ run acc `seq` Ok- TestIO _ _ act -> act >>= \v -> v `seq` return Ok- --- unless quiet $ putStrLn (show result)- return result----- Benchmark a test with Criterion----benchmarkTest :: Config -> Test -> Maybe Benchmark-benchmarkTest cfg (Test name _ _ acc _) = Just . bench name $ whnf (backend cfg . acc) ()-benchmarkTest cfg (TestNoRef name _ acc) = Just . bench name $ whnf (backend cfg . acc) ()-benchmarkTest _ (TestIO _ _ _) = Nothing-
− src/Util.hs
@@ -1,17 +0,0 @@--module Util where--import System.IO.Unsafe---- Lazier version of 'Control.Monad.sequence'----sequence' :: [IO a] -> IO [a]-sequence' = foldr k (return [])- where k m ms = do { x <- m; xs <- unsafeInterleaveIO ms; return (x:xs) }--mapM' :: (a -> IO b) -> [a] -> IO [b]-mapM' f xs = sequence' $ map f xs--forM' :: [a] -> (a -> IO b) -> IO [b]-forM' = flip mapM'-
− src/Validate.hs
@@ -1,102 +0,0 @@-{-# LANGUAGE FlexibleContexts, ParallelListComp #-}-{-# OPTIONS_GHC -fno-warn-unused-binds #-}--module Validate (Similar(..), validate, validate') where--import Data.Int-import Data.Word-import Data.Array.IArray-import Foreign.C.Types-import Foreign.Storable-import Control.Exception (assert)-import Unsafe.Coerce--class Similar a where- sim :: a -> a -> Bool--instance Similar Int where sim = (==)-instance Similar Int8 where sim = (==)-instance Similar Int16 where sim = (==)-instance Similar Int32 where sim = (==)-instance Similar Int64 where sim = (==)-instance Similar Word where sim = (==)-instance Similar Word8 where sim = (==)-instance Similar Word16 where sim = (==)-instance Similar Word32 where sim = (==)-instance Similar Word64 where sim = (==)-instance Similar CShort where sim = (==)-instance Similar CUShort where sim = (==)-instance Similar CInt where sim = (==)-instance Similar CUInt where sim = (==)-instance Similar CLong where sim = (==)-instance Similar CULong where sim = (==)-instance Similar CLLong where sim = (==)-instance Similar CULLong where sim = (==)--instance Similar Bool where sim = (==)-instance Similar Char where sim = (==)-instance Similar CChar where sim = (==)-instance Similar CSChar where sim = (==)-instance Similar CUChar where sim = (==)--instance Similar Float where sim = absoluteOrRelative-instance Similar CFloat where sim = absoluteOrRelative-instance Similar Double where sim = absoluteOrRelative-instance Similar CDouble where sim = absoluteOrRelative--instance (Similar a, Similar b) => Similar (a,b) where- (x,y) `sim` (u,v) = x `sim` u && y `sim` v------- http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm-----absoluteOrRelative :: (Fractional a, Ord a) => a -> a -> Bool-absoluteOrRelative u v- | abs (u-v) < epsilonAbs = True- | abs u > abs v = abs ((u-v) / u) < epsilonRel- | otherwise = abs ((v-u) / v) < epsilonRel- where- epsilonRel = 0.001- epsilonAbs = 0.00001----- Comparisons using lexicographically ordered floating-point numbers--- reinterpreted as twos-complement integers.----lexicographic32 :: (Num a, Storable a) => Int -> a -> a -> Bool-lexicographic32 maxUlps a b- = assert (sizeOf a == 4 && maxUlps > 0 && maxUlps < 4 * 1024 * 1024)- $ intDiff < fromIntegral maxUlps- where- intDiff = abs (toInt a - toInt b)- toInt x | x' < 0 = 0x80000000 - x'- | otherwise = x'- where x' = unsafeCoerce x :: Int32---lexicographic64 :: (Num a, Storable a) => Int -> a -> a -> Bool-lexicographic64 maxUlps a b- = assert (sizeOf a == 8 && maxUlps > 0 && maxUlps < 8 * 1024 * 1024)- $ intDiff < fromIntegral maxUlps- where- intDiff = abs (toInt a - toInt b)- toInt x | x' < 0 = 0x8000000000000000 - x'- | otherwise = x'- where x' = unsafeCoerce x :: Int64----- Compare two vectors element-wise for equality, for a given measure of--- similarity. The index and values are returned for pairs that fail.----validate- :: (IArray array e, Ix ix, Similar e)- => array ix e- -> array ix e- -> [(ix,(e,e))]-validate ref arr = validate' (assocs ref) (elems arr)--validate' :: (Ix ix, Similar e) => [(ix,e)] -> [e] -> [(ix,(e,e))]-validate' ref arr =- filter (not . uncurry sim . snd) [ (i,(x,y)) | (i,x) <- ref | y <- arr ]-
− tests/image-processing/Canny.hs
@@ -1,117 +0,0 @@-{-# LANGUAGE TypeOperators #-}--module Canny where--import PGM--import Data.Array.Accelerate hiding (zipWith, unindex2)-import qualified Data.Array.Accelerate as Acc---type Image a = Array DIM2 a-type Stencil7x1 a = (Stencil3 a, Stencil7 a, Stencil3 a)-type Stencil1x7 a = (Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a, Stencil3 a)---convolve7x1 :: (Elt a, IsNum a) => [Exp a] -> Stencil7x1 a -> Exp a-convolve7x1 kernel (_, (a,b,c,d,e,f,g), _) =- sum $ zipWith (*) kernel [a,b,c,d,e,f,g]--convolve1x7 :: (Elt a, IsNum a) => [Exp a] -> Stencil1x7 a -> Exp a-convolve1x7 kernel ((_,a,_), (_,b,_), (_,c,_), (_,d,_), (_,e,_), (_,f,_), (_,g,_)) =- sum $ zipWith (*) kernel [a,b,c,d,e,f,g]----- Gaussian smoothing----gaussian :: (Elt a, IsFloating a) => [Exp a]-gaussian = [ 0.00442012927963- , 0.05384819825462- , 0.24133088157513- , 0.39788735772974- , 0.24133088157513- , 0.05384819825462- , 0.00442012927963 ]--gaussianX :: (Elt a, IsFloating a) => Acc (Image a) -> Acc (Image a)-gaussianX = stencil (convolve7x1 gaussian) (Constant 0)--gaussianY :: (Elt a, IsFloating a) => Acc (Image a) -> Acc (Image a)-gaussianY = stencil (convolve1x7 gaussian) (Constant 0)----- Gaussian derivative and gradient quantisation----gaussian' :: (Elt a, IsFloating a) => [Exp a]-gaussian' = [ 0.02121662054222- , 0.17231423441479- , 0.38612941052022- , 0.0- ,-0.38612941052022- ,-0.17231423441479- ,-0.02121662054222 ]--gradientX :: (Elt a, IsFloating a) => Acc (Image a) -> Acc (Image a)-gradientX = stencil (convolve7x1 gaussian') (Constant 0)--gradientY :: (Elt a, IsFloating a) => Acc (Image a) -> Acc (Image a)-gradientY = stencil (convolve1x7 gaussian') (Constant 0)--gradientMagnitude :: (Elt a, IsFloating a) => Acc (Image a) -> Acc (Image a) -> Acc (Image a)-gradientMagnitude = Acc.zipWith magdir- where- magdir dx dy = let mag = sqrt (dx*dx + dy*dy)- -- dir = atan2 dy dx- in mag -- lift (mag, dir)----- Non-maximum suppression----nonMaximumSuppression- :: (Elt a, IsFloating a)- => Exp a- -> Acc (Image a)- -> Acc (Image a)- -> Acc (Image a)- -> Acc (Image a)-nonMaximumSuppression threshold gradX gradY gradM =- generate (shape gradX) $ \ix ->- let dx = gradX ! ix- dy = gradY ! ix- mag = gradM ! ix- alpha = 1.3065629648763766 -- 0.5 / sin (pi / 8.0)- offsetx = Acc.round (alpha * dx / mag)- offsety = Acc.round (alpha * dy / mag)- --- (m,n) = unindex2 (shape gradX)- (x,y) = unindex2 ix- fwd = gradM ! lift (clamp (x+offsetx, y+offsety))- rev = gradM ! lift (clamp (x-offsetx, y-offsety))- --- unindex2 uv = let Z:.u:.v = unlift uv in (u,v)- clamp (u,v) = lift (Z:. 0 `Acc.max` u `Acc.min` (m-1) :. 0 `Acc.max` v `Acc.min` (n-1))- in- (mag <* threshold ||* fwd >* mag ||* rev >* mag) ? (0, 1)----- Canny edge detection----canny :: (Elt a, IsFloating a) => Image a -> Acc (Image a)-canny img =- let smooth = gaussianX . gaussianY $ use img- gradX = gradientX smooth- gradY = gradientY smooth- gradMag = gradientMagnitude gradX gradY- in- nonMaximumSuppression 0.1 gradX gradY gradMag----- Main--- -------- TLM: should compare to a pre-saved reference image-run :: FilePath -> IO (() -> Acc (Array DIM2 Float))-run file = do- pgm <- readPGM file- return (\() -> canny pgm)-
− tests/image-processing/IntegralImage.hs
@@ -1,49 +0,0 @@-{-# LANGUAGE ScopedTypeVariables, TypeOperators #-}--module IntegralImage where--import PGM--import Data.Array.Accelerate as Acc----- |The value of each element in an integral image is the sum of all input elements--- above and to the left, inclusive. It is calculated by performing an inclusive/post--- scan from left-to-right then top-to-bottom.----integralImage :: (Elt a, IsNum a) => Array DIM2 a -> Acc (Array DIM2 a)-integralImage img = sumTable- where- -- scan rows- rowArr = reshape (lift $ Z:.(w * h)) arr- rowSegs = Acc.replicate (lift $ Z:.h) $ unit w- rowSum = reshape (lift (Z:.w:.h)) $ Acc.scanl1Seg (+) rowArr rowSegs-- -- scan cols- colArr = reshape (lift $ Z:.(h * w)) $ transpose2D rowSum- colSegs = Acc.replicate (lift $ Z:.w) $ unit h- colSum = reshape (lift (Z:.h:.w)) $ Acc.scanl1Seg (+) colArr colSegs-- -- transpose back- sumTable = transpose2D colSum-- --- arr = use img- Z:.w:.h = unlift $ shape arr----- |Simple 2D matrix transpose.----transpose2D :: Elt a => Acc (Array DIM2 a) -> Acc (Array DIM2 a)-transpose2D arr = backpermute (swap $ shape arr) swap arr- where- swap = lift1 $ \(Z:.x:.y) -> Z:.y:.x :: Z :. Exp Int :. Exp Int----- Run integralImage over the input PGM----run :: FilePath -> IO (() -> Acc (Array DIM2 Float))-run file = do- pgm <- readPGM file- return (\() -> integralImage pgm)-
− tests/image-processing/PGM.hs
@@ -1,32 +0,0 @@------ Load a PGM file. MacOS X users might find the following quicklook plugin--- useful for viewing PGM files:------ http://code.google.com/p/quicklook-pfm/-----module PGM where--import Control.Applicative-import Graphics.Pgm--import Prelude as P-import Data.Array.Accelerate as Acc-import Data.Array.Unboxed hiding (Array)-import qualified Data.ByteString as B----- Read an 8-bit PGM file, and marshal to an Accelerate array as floating-point--- data in the range [0,1].----readPGM :: FilePath -> IO (Array DIM2 Float)-readPGM fp = do- img <- either (error . show) head . pgmsToArrays <$> B.readFile fp :: IO (UArray (Int,Int) Word8)- return . fromIArray $ amap (\x -> P.fromIntegral x / 255) img---writePGM :: FilePath -> Array DIM2 Float -> IO ()-writePGM fp img =- let arr = toIArray img :: UArray (Int,Int) Float- in arrayToFile fp $ amap (\x -> P.round (255 * x)) arr-
− tests/io/BlockCopy.hs
@@ -1,90 +0,0 @@-{-# LANGUAGE ForeignFunctionInterface, ScopedTypeVariables, TypeOperators #-}--module BlockCopy where---- standard libraries-import Prelude as P-import Foreign.Ptr-import Control.Monad-import Control.Exception---- friends-import Data.Array.Accelerate-import Data.Array.Accelerate.IO--assertEqual :: (Eq a, Show a) => String -> a -> a -> IO ()-assertEqual preface expected actual =- unless (actual == expected) (throw $ AssertionFailed msg)- where- msg = (if null preface then "" else preface ++ "\n") ++- "expected: " ++ show expected ++ "\n but got: " ++ show actual--run :: IO ()-run =- mapM_ (\(msg,act) -> putStrLn ("test: " ++ msg) >> act)- [ ("fromPtr Int", testBlockCopyPrim)- , ("fromPtr (Int,Double)", testBlockCopyTuples)- , ("toPtr Int16", testBlockCopyFromArrayInt16)- , ("toPtr Int32", testBlockCopyFromArrayInt32)- , ("toPtr Int64", testBlockCopyFromArrayInt64)- , ("fromArray Int", testBlockCopyFromArrayWithFunctions) ]---testBlockCopyPrim :: IO ()-testBlockCopyPrim = do- ptr <- oneToTen- (arr :: Vector Int32) <- fromPtr (Z :. 10) ((), ptr)- assertEqual "Not equal" [1..10] (toList arr)--testBlockCopyTuples :: IO ()-testBlockCopyTuples = do- intPtr <- oneToTen- doublePtr <- tenToOne- (arr :: Vector (Int32, Double)) <- fromPtr (Z :. 10) (((), intPtr), doublePtr)- assertEqual "Not equal" [ (x, P.fromIntegral (11 - x)) | x <- [1..10]] (toList arr)--testBlockCopyFromArrayWithFunctions :: IO ()-testBlockCopyFromArrayWithFunctions = do- let n = 5^(3::Int)- let (arr :: Array (Z:.Int:.Int:.Int) Int32) = fromList (Z:.5:.5:.5) [2*x | x <- [0..n-1]]- ohi <- nInt32s (P.fromIntegral n)- fromArray arr ((), memcpy ohi)- b <- isFilledWithEvens32 ohi (P.fromIntegral n)- assertEqual "Not equal" 1 b--testBlockCopyFromArrayInt16 :: IO ()-testBlockCopyFromArrayInt16 = do- let n = 50- let (arr :: Vector Int16) = fromList (Z:.n) [2 * P.fromIntegral x | x <- [0..n-1]]- ohi <- nInt16s (P.fromIntegral n)- toPtr arr ((), ohi)- b <- isFilledWithEvens16 ohi (P.fromIntegral n)- assertEqual "Not equal" 1 b--testBlockCopyFromArrayInt32 :: IO ()-testBlockCopyFromArrayInt32 = do- let (arr :: Array (Z:.Int:.Int) Int32) = fromList (Z:.10:.10) [2*x | x <- [0..99]]- ohi <- nInt32s 100- toPtr arr ((), ohi)- b <- isFilledWithEvens32 ohi 100- assertEqual "Not equal" 1 b--testBlockCopyFromArrayInt64 :: IO ()-testBlockCopyFromArrayInt64 = do- let n = 73- let (arr :: Vector Int64) = fromList (Z:.n) [2 * P.fromIntegral x | x <- [0..n-1]]- ohi <- nInt64s (P.fromIntegral n)- toPtr arr ((), ohi)- b <- isFilledWithEvens64 ohi (P.fromIntegral n)- assertEqual "Not equal" 1 b--foreign import ccall "one_to_ten" oneToTen :: IO (Ptr Int32)-foreign import ccall "ten_to_one" tenToOne :: IO (Ptr Double)-foreign import ccall "n_int_16s" nInt16s :: CInt -> IO (Ptr Int16)-foreign import ccall "n_int_32s" nInt32s :: CInt -> IO (Ptr Int32)-foreign import ccall "n_int_64s" nInt64s :: CInt -> IO (Ptr Int64)-foreign import ccall "is_filled_with_evens_16" isFilledWithEvens16 :: Ptr Int16 -> CInt -> IO CInt-foreign import ccall "is_filled_with_evens_32" isFilledWithEvens32 :: Ptr Int32 -> CInt -> IO CInt-foreign import ccall "is_filled_with_evens_64" isFilledWithEvens64 :: Ptr Int64 -> CInt -> IO CInt-foreign import ccall memcpy :: Ptr a -> Ptr b -> Int -> IO ()-
− tests/io/Vector.hs
@@ -1,75 +0,0 @@-{-# LANGUAGE TemplateHaskell, TypeFamilies #-}--module Vector where--import Control.Applicative--import Data.Array.Accelerate hiding (fromList)-import Data.Array.Accelerate.Array.Sugar (EltRepr)-import Data.Array.Accelerate.IO--import Data.Vector.Storable--import Foreign--import Test.QuickCheck-import Test.QuickCheck.All-import Test.QuickCheck.Monadic--roundtrip :: ( Arbitrary a- , Eq a- , Elt a- , Storable a- , BlockPtrs (EltRepr a) ~ ((), Ptr a) )- => [a] -> Property-roundtrip xs = monadicIO $ do- let xsv = fromList xs- xsarr <- run $ fromVectorIO xsv- xsv' <- run $ toVectorIO xsarr- assert (xsv == xsv')--unsaferoundtrip :: ( Arbitrary a- , Eq a- , Elt a- , Storable a- , BlockPtrs (EltRepr a) ~ ((), Ptr a) )- => [a] -> Bool-unsaferoundtrip xs = xsv == (toVector (fromVector xsv))- where xsv = fromList xs--prop_Int8_roundtrip :: [Int8] -> Property-prop_Int8_roundtrip = roundtrip-prop_Int8_unsaferoundtrip :: [Int8] -> Bool-prop_Int8_unsaferoundtrip = unsaferoundtrip--prop_Int16_roundtrip :: [Int16] -> Property-prop_Int16_roundtrip = roundtrip-prop_Int16_unsaferoundtrip :: [Int16] -> Bool-prop_Int16_unsaferoundtrip = unsaferoundtrip--prop_Int32_roundtrip :: [Int32] -> Property-prop_Int32_roundtrip = roundtrip-prop_Int32_unsaferoundtrip :: [Int32] -> Bool-prop_Int32_unsaferoundtrip = unsaferoundtrip--prop_Int64_roundtrip :: [Int64] -> Property-prop_Int64_roundtrip = roundtrip-prop_Int64_unsaferoundtrip :: [Int64] -> Bool-prop_Int64_unsaferoundtrip = unsaferoundtrip--prop_Int_roundtrip :: [Int] -> Property-prop_Int_roundtrip = roundtrip-prop_Int_unsaferoundtrip :: [Int] -> Bool-prop_Int_unsaferoundtrip = unsaferoundtrip--prop_Float_roundtrip :: [Float] -> Property-prop_Float_roundtrip = roundtrip-prop_Float_unsaferoundtrip :: [Float] -> Bool-prop_Float_unsaferoundtrip = unsaferoundtrip--prop_Double_roundtrip :: [Double] -> Property-prop_Double_roundtrip = roundtrip-prop_Double_unsaferoundtrip :: [Double] -> Bool-prop_Double_unsaferoundtrip = unsaferoundtrip--test = $quickCheckAll
− tests/io/fill_with_values.cpp
@@ -1,81 +0,0 @@-#include <stdio.h>-#include <stdlib.h>-#include <stdint.h>--/* Returns one if it's filled with even values starting at 0 */-template <typename T>-int is_filled_with_evens(T *p, int size) {- T prev = 0;- int result = 1; // default to true- int i;-- if (p[0] != 0) {- result = 0;- }-- for (i=1; result && i < size; i++) {- if (p[i] != prev + 2) {- result = 0;- }- else {- prev = p[i];- }- }-- return result;-}---#ifdef __cplusplus-extern "C" {-#endif--int32_t *one_to_ten() {- int32_t *p = (int32_t*) malloc(sizeof(int32_t) * 10);- int i;- for (i=0; i<10; i++) {- p[i] = i+1;- }- return p;-}--double *ten_to_one() {- double *p = (double*) malloc(sizeof(double) * 10);- int i;- for (i=0; i< 10; i++) {- p[i] = 10.0 - (double) i;- }- return p;-}--int32_t *n_int_32s (int n) {- return (int32_t*) malloc(sizeof(int32_t) * n);-}--int16_t *n_int_16s(int n) {- return (int16_t*) malloc(sizeof(int16_t) * n);-}--int64_t *n_int_64s(int n) {- return (int64_t*) malloc(sizeof(int64_t) * n);-}--int is_filled_with_evens_16(int16_t *p, int size)-{- return is_filled_with_evens(p, size);-}--int is_filled_with_evens_32(int32_t *p, int size)-{- return is_filled_with_evens(p, size);-}--int is_filled_with_evens_64(int64_t *p, int size)-{- return is_filled_with_evens(p, size);-}--#ifdef __cplusplus-}-#endif-
− tests/primitives/Backpermute.hs
@@ -1,69 +0,0 @@-{-# LANGUAGE TypeOperators #-}--module Backpermute where--import Random--import Control.Monad-import Control.Exception-import System.Random.MWC-import Data.Array.Unboxed-import Data.Array.Accelerate as Acc-import Prelude as P----- Tests--- -------reverseAcc :: Vector Float -> Acc (Vector Float)-reverseAcc xs =- let xs' = use xs- len = unindex1 (shape xs')- in- backpermute (shape xs') (\ix -> index1 $ len - (unindex1 ix) - 1) xs'--reverseRef :: UArray Int Float -> UArray Int Float-reverseRef xs = listArray (bounds xs) (reverse (elems xs))---transposeAcc :: Acc.Array DIM2 Float -> Acc (Acc.Array DIM2 Float)-transposeAcc mat =- let mat' = use mat- swap = lift1 $ \(Z:.x:.y) -> Z:.y:.x :: Z:.Exp Int:.Exp Int- in- backpermute (swap $ shape mat') swap mat'--transposeRef :: UArray (Int,Int) Float -> UArray (Int,Int) Float-transposeRef mat =- let swap (x,y) = (y,x)- (u,v) = bounds mat- in- array (swap u, swap v) [(swap ix, e) | (ix, e) <- assocs mat]----- Main--- ------run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))-run alg n = withSystemRandom $ \gen -> do- vec <- randomUArrayR (-1,1) gen n- vec' <- convertUArray vec- --- let go f g = return (\() -> f vec, \() -> g vec')- case alg of- "reverse" -> go reverseRef reverseAcc- _ -> error $ "unknown variant: " ++ alg--run2d :: String -> Int -> IO (() -> UArray (Int,Int) Float, () -> Acc (Acc.Array DIM2 Float))-run2d alg n = withSystemRandom $ \gen -> do- let n' = P.round $ sqrt (P.fromIntegral n :: Double)- (u,v) = (n'*2, n'`div`2)- mat <- listArray ((0,0), (u-1,v-1)) `fmap` replicateM (u*v) (uniformR (-1,1) gen)- mat' <- let m = fromIArray mat :: Acc.Array DIM2 Float- in evaluate (m `Acc.indexArray` (Z:.0:.0)) >> return m- --- let go f g = return (\() -> f mat, \() -> g mat')- case alg of- "transpose" -> go transposeRef transposeAcc- _ -> error $ "unknown variant: " ++ alg-
− tests/primitives/Fold.hs
@@ -1,84 +0,0 @@-{-# LANGUAGE FlexibleContexts, TypeOperators #-}--module Fold where--import Random--import Control.Monad-import Control.Exception-import System.Random.MWC-import Data.Array.Unboxed hiding (Array)-import Data.Array.Accelerate as Acc-import Prelude as P----- one-dimension ah-ha-ha--- ------------------------toUA :: (IArray UArray a, IArray UArray b) => ([a] -> b) -> UArray Int a -> UArray () b-toUA f = listArray ((),()) . return . f . elems---sumAcc, prodAcc, maxAcc, minAcc :: Shape ix => Array (ix:.Int) Float -> Acc (Array ix Float)-sumAcc = Acc.fold (+) 0 . Acc.use-prodAcc = Acc.fold (*) 1 . Acc.use-maxAcc = Acc.fold1 Acc.max . Acc.use-minAcc = Acc.fold1 Acc.min . Acc.use--sumRef, prodRef, maxRef, minRef :: UArray Int Float -> UArray () Float-sumRef = toUA sum-prodRef = toUA product-maxRef = toUA maximum-minRef = toUA minimum----- two-dimensions ah-ha-ha--- -------------------------foldU2D :: IArray UArray a => (a -> a -> a) -> a -> UArray (Int,Int) a -> UArray Int a-foldU2D f z arr =- let (_,(m,_)) = bounds arr- in accumArray f z (0,m) [ (i,e) | ((i,_),e) <- assocs arr ]--sum2DRef, prod2DRef :: UArray (Int,Int) Float -> UArray Int Float-sum2DRef = foldU2D (+) 0-prod2DRef = foldU2D (*) 1----- Main--- -----run :: String -> Int -> IO (() -> UArray () Float, () -> Acc (Scalar Float))-run alg n = withSystemRandom $ \gen -> do- vec <- randomUArrayR (-1,1) gen n- vec' <- convertUArray vec- --- let go f g = return (run_ref f vec, run_acc g vec')- case alg of- "sum" -> go sumRef sumAcc- "product" -> go prodRef prodAcc- "maximum" -> go maxRef maxAcc- "minimum" -> go minRef minAcc- x -> error $ "unknown variant: " ++ x- where- {-# NOINLINE run_ref #-}- run_ref f xs () = f xs- run_acc f xs () = f xs--run2d :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))-run2d alg n = withSystemRandom $ \gen -> do- let u = P.floor . sqrt $ (P.fromIntegral n :: Double)- v = 2*u+1 :: Int- mat <- listArray ((0,0), (u-1,v-1)) `fmap` replicateM (u*v) (uniformR (-1,1) gen)- mat' <- let m = fromIArray mat :: Array DIM2 Float- in evaluate (m `Acc.indexArray` (Z:.0:.0)) >> return m- --- let go f g = return (run_ref f mat, run_acc g mat')- case alg of- "sum-2d" -> go sum2DRef sumAcc- "product-2d" -> go prod2DRef prodAcc- x -> error $ "unknown variant: " ++ x- where- {-# NOINLINE run_ref #-}- run_ref f xs () = f xs- run_acc f xs () = f xs-
− tests/primitives/Map.hs
@@ -1,52 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}--module Map where--import Random--import System.Random.MWC-import Data.Array.Unboxed-import Data.Array.Accelerate as Acc----- Tests--- ------sqAcc, absAcc :: Vector Float -> Acc (Vector Float)-absAcc = Acc.map abs . Acc.use-sqAcc = Acc.map (\x -> x * x) . Acc.use--plusAcc :: Exp Float -> Vector Float -> Acc (Vector Float)-plusAcc alpha = Acc.map (+ alpha) . Acc.use---toUA :: (IArray UArray a, IArray UArray b) => ([a] -> [b]) -> UArray Int a -> UArray Int b-toUA f xs = listArray (bounds xs) $ f (elems xs)--sqRef, absRef :: UArray Int Float -> UArray Int Float-absRef = toUA $ Prelude.map abs-sqRef = toUA $ Prelude.map (\x -> x*x)--plusRef :: Float -> UArray Int Float -> UArray Int Float-plusRef alpha = toUA $ Prelude.map (+alpha)----- Main--- -----run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))-run alg n = withSystemRandom $ \gen -> do- vec <- randomUArrayR (-1,1) gen n- vec' <- convertUArray vec- alpha <- uniform gen- --- let go f g = return (run_ref f vec, run_acc g vec')- case alg of- "abs" -> go absRef absAcc- "plus" -> go (plusRef alpha) (plusAcc $ constant alpha)- "square" -> go sqRef sqAcc- x -> error $ "unknown variant: " ++ x-- where- {-# NOINLINE run_ref #-}- run_ref f xs () = f xs- run_acc f xs () = f xs-
− tests/primitives/Permute.hs
@@ -1,39 +0,0 @@-module Permute where--import Random--import System.Random.MWC-import Data.Array.Unboxed-import Data.Array.Accelerate as Acc-import Prelude as P----- Tests--- -------histogramAcc :: (Int,Int) -> Vector Float -> Acc (Vector Int)-histogramAcc (m,n) vec =- let vec' = use vec- zeros = generate (constant (Z:. n-m)) (const 0)- ones = generate (shape vec') (const 1)- in- permute (+) zeros (\ix -> index1 $ Acc.floor (vec' Acc.! ix)) ones--histogramRef :: (Int,Int) -> UArray Int Float -> UArray Int Int-histogramRef (m,n) vec =- accumArray (+) 0 (0,n-m-1) [(P.floor e, 1) | e <- elems vec]----- Main--- -----run :: String -> Int -> IO (() -> UArray Int Int, () -> Acc (Vector Int))-run alg n = withSystemRandom $ \gen -> do- vec <- randomUArrayR (0,100::Float) gen n- vec' <- convertUArray vec- --- let go f g = return (\() -> f vec, \() -> g vec')- case alg of- "histogram" -> go (histogramRef (0,100)) (histogramAcc (0,100))- _ -> error $ "unknown variant: " ++ alg--
− tests/primitives/ScanSeg.hs
@@ -1,58 +0,0 @@--module ScanSeg where--import Random--import System.IO-import System.Random.MWC-import Data.Array.Unboxed-import Data.Array.Accelerate as Acc-import Prelude as P----- Segmented prefix-sum--- ---------------------prefixSumSegAcc :: Vector Float -> Segments -> Acc (Vector Float)-prefixSumSegAcc xs seg- = let- xs' = use xs- seg' = use seg- in- prescanlSeg (+) 0 xs' seg'---prefixSumSegRef :: UArray Int Float -> UArray Int Int -> UArray Int Float-prefixSumSegRef xs seg- = listArray (bounds xs)- $ list_prescanlSeg (+) 0 (elems xs) (elems seg)--list_prescanlSeg :: (a -> a -> a) -> a -> [a] -> [Int] -> [a]-list_prescanlSeg f x xs seg = concatMap (init . P.scanl f x) (split seg xs)- where- split [] _ = []- split _ [] = []- split (i:is) vs =- let (h,t) = splitAt i vs- in h : split is t----- Main--- -----run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))-run alg m = withSystemRandom $ \gen -> do- let n = P.round . sqrt $ (P.fromIntegral m :: Double)- seg <- randomUArrayR (0,n) gen n- seg' <- convertUArray seg- let ne = sum (elems seg)- vec <- randomUArrayR (-1,1) gen ne- vec' <- convertUArray vec- --- let go f g = return (run_ref f vec seg, run_acc g vec' seg')- case alg of- "sum" -> go prefixSumSegRef prefixSumSegAcc- x -> error $ "unknown variant: " ++ x- where- {-# NOINLINE run_ref #-}- run_ref f xs seg () = f xs seg- run_acc f xs seg () = f xs seg-
− tests/primitives/Stencil.hs
@@ -1,229 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}--module Stencil where--import Random--import Control.Monad-import Control.Exception-import System.Random.MWC--import Data.Array.Unboxed hiding (Array)-import qualified Data.Array.IArray as IArray--import Data.Array.Accelerate hiding (min, max, round, fromIntegral)-import qualified Data.Array.Accelerate as Acc------ Stencil Tests--- ----------------- 1D ----------------------------------------------------------------------------stencil1D :: Floating a- => (a, a, a) -> a-stencil1D (x, y, z) = (x + z - 2 * y) / 2--test_stencil1D :: Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))-test_stencil1D n = withSystemRandom $ \gen -> do- vec <- randomUArrayR (-1,1) gen n- vec' <- convertUArray vec- return (\() -> run_ref vec, \() -> run_acc vec')- where- run_acc = stencil stencil1D Clamp . use- run_ref v =- let (minx,maxx) = bounds v- clamp x = minx `max` x `min` maxx-- f ix = let x = v IArray.! clamp (ix-1)- y = v IArray.! ix- z = v IArray.! clamp (ix+1)- in- (x + z - 2 * y) / 2- in- array (bounds v) [(ix, f ix) | ix <- indices v]----- 2D ----------------------------------------------------------------------------stencil2D :: Floating (Exp a)- => Stencil3x3 a -> Exp a-stencil2D ( (t1, t2, t3)- , (l , m, r )- , (b1, b2, b3)- )- = (t1/2 + t2 + t3/2 + l + r + b1/2 + b2 + b3/2 - 4 * m) / 4--test_stencil2D :: Int -> IO (() -> IArray.Array (Int,Int) Float, () -> Acc (Array DIM2 Float))-test_stencil2D n2 = withSystemRandom $ \gen -> do- let n = round . (/3) . sqrt $ (fromIntegral n2 :: Double)- m = n * 4- mat <- listArray ((0,0),(n-1,m-1)) `fmap` replicateM (n*m) (uniformR (-1,1) gen) :: IO (IArray.Array (Int,Int) Float)- mat' <- let v = fromIArray mat :: Array DIM2 Float- in evaluate (v `indexArray` (Z:.0:.0)) >> return v- --- return (\() -> run_ref mat, \() -> run_acc mat')- where- run_acc = stencil stencil2D (Constant 0) . use- run_ref arr =- let get ix- | inRange (bounds arr) ix = arr IArray.! ix- | otherwise = 0-- f (x,y) = let t1 = get (x-1,y-1)- t2 = get (x, y-1)- t3 = get (x+1,y-1)- l = get (x-1,y)- m = get (x, y)- r = get (x+1,y)- b1 = get (x-1,y+1)- b2 = get (x, y+1)- b3 = get (x+1,y+1)- in- (t1/2 + t2 + t3/2 + l + r + b1/2 + b2 + b3/2 - 4 * m) / 4- in- array (bounds arr) [(ix, f ix) | ix <- indices arr]----stencil2D5 :: Floating (Exp a)- => Stencil3x3 a -> Exp a-stencil2D5 ( (_, t, _)- , (l, m, r)- , (_, b, _)- )- = (t + l + r + b - 4 * m) / 4--test_stencil2D5 :: Int -> IO (() -> IArray.Array (Int,Int) Float, () -> Acc (Array DIM2 Float))-test_stencil2D5 n2 = withSystemRandom $ \gen -> do- let n = round . sqrt $ (fromIntegral n2 :: Double)- mat <- listArray ((0,0),(n-1,n-1)) `fmap` replicateM (n*n) (uniformR (-1,1) gen) :: IO (IArray.Array (Int,Int) Float)- mat' <- let m = fromIArray mat :: Array DIM2 Float- in evaluate (m `indexArray` (Z:.0:.0)) >> return m- --- return (\() -> run_ref mat, \() -> run_acc mat')- where- run_acc = stencil stencil2D5 Clamp . use- run_ref arr =- let ((minx,miny),(maxx,maxy)) = bounds arr- clamp (x,y) = (minx `max` x `min` maxx- ,miny `max` y `min` maxy)- f (x,y) = let t = arr IArray.! clamp (x,y-1)- b = arr IArray.! clamp (x,y+1)- l = arr IArray.! clamp (x-1,y)- r = arr IArray.! clamp (x+1,y)- m = arr IArray.! (x,y)- in- (t + l + r + b - 4 * m) / 4- in- array (bounds arr) [(ix, f ix) | ix <- indices arr]----stencil2Dpair :: Stencil3x3 (Int,Float) -> Exp Float-stencil2Dpair ( (_, _, _)- , (x, _, _)- , (y, _, z)- )- = let (x1,x2) = unlift x :: (Exp Int, Exp Float)- (y1,y2) = unlift y- (z1,z2) = unlift z- in- (x2 * Acc.fromIntegral x1 + y2 * Acc.fromIntegral z1 - z2 * Acc.fromIntegral y1)--test_stencil2Dpair :: Int -> IO (() -> IArray.Array (Int,Int) Float, () -> Acc (Array DIM2 Float))-test_stencil2Dpair n2 = withSystemRandom $ \gen -> do- let n = round (fromIntegral n2 ** 0.5 :: Double)- m = 2 * n- mat <- listArray ((0,0),(n-1,m-1)) `fmap` replicateM (n*m) (uniformR ((-100,0), (100,0)) gen) :: IO (IArray.Array (Int,Int) (Int,Float))- mat' <- let a = fromIArray mat- in evaluate (a `indexArray` (Z:.0:.0)) >> return a- --- return (\() -> run_ref mat, \() -> run_acc mat')- where- run_acc = stencil stencil2Dpair Wrap . use- run_ref arr =- let ((minx,miny),(maxx,maxy)) = bounds arr- wrap (m,n) i- | i < m = n + (i-m)- | i > n = i - n + m- | otherwise = i-- get (x,y) = arr IArray.! ( wrap (minx,maxx) x, wrap (miny,maxy) y)- f (x,y) = let (a1,a2) = get (x-1,y)- (b1,b2) = get (x-1,y+1)- (c1,c2) = get (x+1,y+1)- in- (a2 * fromIntegral a1 + b2 * fromIntegral c1 - c2 * fromIntegral b1)- in- array (bounds arr) [(ix, f ix) | ix <- indices arr]----- 3D ----------------------------------------------------------------------------stencil3D :: Num (Exp a)- => Stencil3x3x3 a -> Exp a-stencil3D (front, back, _) = -- 'b4' is the focal point- let ((f1, f2, _),- (f3, f4, _),- _ ) = front- ((b1, b2, _),- (b3, b4, _),- _ ) = back- in- f1 + f2 + f3 + f4 + b1 + b2 + b3 + b4--test_stencil3D :: Int -> IO (() -> UArray (Int,Int,Int) Float, () -> Acc (Array DIM3 Float))-test_stencil3D n3 = withSystemRandom $ \gen -> do- let u = round (fromIntegral n3 ** (1/3) :: Double)- v = u `div` 2- w = u * 3- arr <- listArray ((0,0,0), (u-1, v-1, w-1)) `fmap` replicateM (u*v*w) (uniformR (-1,1) gen) :: IO (UArray (Int,Int,Int) Float)- arr' <- let a = fromIArray arr- in evaluate (a `indexArray` (Z:.0:.0:.0)) >> return a- --- return (\() -> run_ref arr, \() -> run_acc arr')- where- run_acc = stencil stencil3D Mirror . use- run_ref arr =- let ((minx,miny,minz),(maxx,maxy,maxz)) = bounds arr- mirror (m,n) i- | i < m = -i + m- | i > n = n - (i-n+2)- | otherwise = i-- get (x,y,z) = arr IArray.! ( mirror (minx,maxx) x, mirror (miny,maxy) y, mirror (minz,maxz) z)- f (x,y,z) = let f1 = get (x-1,y-1,z-1)- f2 = get (x, y-1,z-1)- f3 = get (x-1,y, z-1)- f4 = get (x, y, z-1)- b1 = get (x-1,y-1,z )- b2 = get (x, y-1,z )- b3 = get (x-1,y, z )- b4 = get (x, y, z )- in- f1 + f2 + f3 + f4 + b1 + b2 + b3 + b4- in- array (bounds arr) [(ix, f ix) | ix <- indices arr]----- Main--- ------run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))-run "1D" = test_stencil1D-run x = error $ "unknown variant: " ++ x---run2D :: String -> Int -> IO (() -> IArray.Array (Int,Int) Float, () -> Acc (Array DIM2 Float))-run2D "2D" = test_stencil2D-run2D "3x3-cross" = test_stencil2D5-run2D "3x3-pair" = test_stencil2Dpair-run2D x = error $ "unknown variant: " ++ x---run3D :: String -> Int -> IO (() -> UArray (Int,Int,Int) Float, () -> Acc (Array DIM3 Float))-run3D "3D" = test_stencil3D-run3D x = error $ "unknown variant: " ++ x-
− tests/primitives/Stencil2.hs
@@ -1,70 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}--module Stencil2 where--import Control.Monad-import Control.Exception-import System.Random.MWC-import Data.Array.Unboxed hiding (Array)-import Data.Array.Accelerate hiding (round, min, max, fromIntegral)-import qualified Data.Array.IArray as IArray----stencil2D2 :: Floating (Exp a) => Stencil3x3 a -> Stencil3x3 a -> Exp a-stencil2D2 ((_,t,_), (_,x,_), (_,b,_))- ((_,_,_), (l,y,r), (_,_,_)) = t + b + l + r - ((x+y) / 2)---test_stencil2_2D :: Int -> IO (() -> UArray (Int,Int) Float, () -> Acc (Array DIM2 Float))-test_stencil2_2D n2 = withSystemRandom $ \gen -> do- let n = round $ sqrt (fromIntegral n2 :: Double)- m = n * 2- u = m `div` 3- v = n + m- m1 <- listArray ((0,0),(n-1,m-1)) `fmap` replicateM (n*m) (uniformR (-1,1) gen) :: IO (UArray (Int,Int) Float)- m2 <- listArray ((0,0),(u-1,v-1)) `fmap` replicateM (u*v) (uniformR (-1,1) gen) :: IO (UArray (Int,Int) Float)- m1' <- let m1' = fromIArray m1 in evaluate (m1' `indexArray` (Z:.0:.0)) >> return m1'- m2' <- let m2' = fromIArray m2 in evaluate (m2' `indexArray` (Z:.0:.0)) >> return m2'- --- return (\() -> run_ref m1 m2, \() -> run_acc m1' m2')- where- run_acc xs ys = stencil2 stencil2D2 Mirror (use xs) Wrap (use ys)- run_ref xs ys =- let (_,(n,m)) = bounds xs- (_,(u,v)) = bounds ys- sh = ((0,0), (n `min` u, m `min` v))-- -- boundary conditions are placed on the *source* arrays- --- get1 (x,y) = xs IArray.! (mirror n x, mirror m y)- get2 (x,y) = ys IArray.! (wrap u x, wrap v y)-- mirror sz i- | i < 0 = -i- | i > sz = sz - (i-sz)- | otherwise = i-- wrap sz i- | i < 0 = sz + i + 1- | i > sz = i - sz - 1- | otherwise = i-- f (ix,iy) = let t = get1 (ix, iy-1)- b = get1 (ix, iy+1)- x = get1 (ix, iy)- l = get2 (ix-1,iy)- r = get2 (ix+1,iy)- y = get2 (ix, iy)- in- t + b + l + r - ((x+y) / 2)- in- array sh [(ix, f ix) | ix <- range sh]---- Main--- ------run2D :: String -> Int -> IO (() -> UArray (Int,Int) Float, () -> Acc (Array DIM2 Float))-run2D "2D" = test_stencil2_2D-run2D x = error $ "unknown variant: " ++ x-
− tests/primitives/Zip.hs
@@ -1,35 +0,0 @@--module Zip where--import Random--import System.Random.MWC-import Data.Array.Unboxed as IArray-import Data.Array.Accelerate as Acc hiding (min)----- Tests--- -------zipAcc :: Vector Float -> Vector Int -> Acc (Vector (Float,Int))-zipAcc xs ys = Acc.zip (use xs) (use ys)---zipRef :: UArray Int Float -> UArray Int Int -> IArray.Array Int (Float,Int)-zipRef xs ys =- let mn = bounds xs- uv = bounds ys- newSize = (0, (rangeSize mn `min` rangeSize uv) - 1)- in- listArray newSize $ Prelude.zip (elems xs) (elems ys)---- Main--- -----run :: Int -> IO (() -> IArray.Array Int (Float,Int), () -> Acc (Vector (Float,Int)))-run n = withSystemRandom $ \gen -> do- xs <- randomUArrayR (-1,1) gen n- ys <- randomUArrayR (-1,1) gen n- xs' <- convertUArray xs- ys' <- convertUArray ys- return $ (\() -> zipRef xs ys, \() -> zipAcc xs' ys')-
− tests/primitives/ZipWith.hs
@@ -1,42 +0,0 @@-{-# LANGUAGE ParallelListComp #-}--module ZipWith where--import Random--import System.Random.MWC-import Data.Array.Unboxed-import Data.Array.Accelerate as Acc hiding (min)----- Tests--- -------plusAcc :: Vector Float -> Vector Float -> Acc (Vector Float)-plusAcc xs ys = Acc.zipWith (+) (use xs) (use ys)--plusRef :: UArray Int Float -> UArray Int Float -> UArray Int Float-plusRef = zipWithRef (+)--zipWithRef :: (IArray array a, IArray array b, IArray array c)- => (a -> b -> c) -> array Int a -> array Int b -> array Int c-zipWithRef f xs ys =- let mn = bounds xs- uv = bounds ys- newSize = (0, (rangeSize mn `min` rangeSize uv) - 1)- in- listArray newSize [f x y | x <- elems xs | y <- elems ys]---- Main--- -----run :: String -> Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))-run alg n = withSystemRandom $ \gen -> do- xs <- randomUArrayR (-1,1) gen n- ys <- randomUArrayR (-1,1) gen n- xs' <- convertUArray xs- ys' <- convertUArray ys- let go f g = return (\() -> f xs ys, \() -> g xs' ys')- case alg of- "plus" -> go plusRef plusAcc- _ -> error $ "unknown variant: " ++ alg-
− tests/simple/BlackScholes.hs
@@ -1,88 +0,0 @@--module BlackScholes where--import Random--import Prelude as P-import System.Random.MWC-import Data.Array.IArray as IArray-import Data.Array.Accelerate as Acc---riskfree, volatility :: Float-riskfree = 0.02-volatility = 0.30---- Black-Scholes option pricing----------------------------------horner :: Num a => [a] -> a -> a-horner coeff x = foldr1 madd coeff- where- madd a b = b*x + a--cnd' :: Floating a => a -> a-cnd' d =- let poly = horner coeff- coeff = [0.0,0.31938153,-0.356563782,1.781477937,-1.821255978,1.330274429]- rsqrt2pi = 0.39894228040143267793994605993438- k = 1.0 / (1.0 + 0.2316419 * abs d)- in- rsqrt2pi * exp (-0.5*d*d) * poly k---blackscholesAcc :: Vector (Float, Float, Float) -> Acc (Vector (Float, Float))-blackscholesAcc xs = Acc.map go (Acc.use xs)- where- go x =- let (price, strike, years) = Acc.unlift x- r = Acc.constant riskfree- v = Acc.constant volatility- sqrtT = sqrt years- d1 = (log (price / strike) + (r + 0.5 * v * v) * years) / (v * sqrtT)- d2 = d1 - v * sqrtT- cnd d = d >* 0 ? (1.0 - cnd' d, cnd' d)- cndD1 = cnd d1- cndD2 = cnd d2- expRT = exp (-r * years)- in- Acc.lift ( price * cndD1 - strike * expRT * cndD2- , strike * expRT * (1.0 - cndD2) - price * (1.0 - cndD1))---blackscholesRef :: IArray.Array Int (Float,Float,Float) -> IArray.Array Int (Float,Float)-blackscholesRef xs = listArray (bounds xs) [ go x | x <- elems xs ]- where- go (price, strike, years) =- let r = riskfree- v = volatility- sqrtT = sqrt years- d1 = (log (price / strike) + (r + 0.5 * v * v) * years) / (v * sqrtT)- d2 = d1 - v * sqrtT- cnd d = if d > 0 then 1.0 - cnd' d else cnd' d- cndD1 = cnd d1- cndD2 = cnd d2- expRT = exp (-r * years)- in- ( price * cndD1 - strike * expRT * cndD2- , strike * expRT * (1.0 - cndD2) - price * (1.0 - cndD1))----- Main--- ------run :: Int -> IO (() -> IArray.Array Int (Float,Float), () -> Acc (Vector (Float,Float)))-run n = withSystemRandom $ \gen -> do- v_sp <- randomUArrayR (5,30) gen n- v_os <- randomUArrayR (1,100) gen n- v_oy <- randomUArrayR (0.25,10) gen n-- let v_psy = listArray (0,n-1) $ P.zip3 (elems v_sp) (elems v_os) (elems v_oy)- a_psy = Acc.fromIArray v_psy- --- return (run_ref v_psy, run_acc a_psy)- where- {-# NOINLINE run_ref #-}- run_ref psy () = blackscholesRef psy- run_acc psy () = blackscholesAcc psy-
− tests/simple/DotP.hs
@@ -1,44 +0,0 @@-{-# LANGUAGE ParallelListComp #-}--module DotP where--import Random--import System.Random.MWC-import Data.Array.Unboxed-import Data.Array.Accelerate as Acc----- Dot product--- ------------dotpAcc :: Vector Float -> Vector Float -> Acc (Scalar Float)-dotpAcc xs ys- = let- xs' = use xs- ys' = use ys- in- Acc.fold (+) 0 (Acc.zipWith (*) xs' ys')--dotpRef :: UArray Int Float- -> UArray Int Float- -> UArray () Float-dotpRef xs ys- = listArray ((), ()) [sum [x * y | x <- elems xs | y <- elems ys]]----- Main--- ------run :: Int -> IO (() -> UArray () Float, () -> Acc (Scalar Float))-run n = withSystemRandom $ \gen -> do- v1 <- randomUArrayR (-1,1) gen n- v2 <- randomUArrayR (-1,1) gen n- v1' <- convertUArray v1- v2' <- convertUArray v2- --- return (run_ref v1 v2, run_acc v1' v2')- where- {-# NOINLINE run_ref #-}- run_ref xs ys () = dotpRef xs ys- run_acc xs ys () = dotpAcc xs ys-
− tests/simple/Filter.hs
@@ -1,55 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}--module Filter where--import Random--import System.Random.MWC-import Data.Array.Unboxed (IArray, UArray, elems, listArray)-import Data.Array.Accelerate as Acc----- Filter--- -------filterAcc :: Elt a- => (Exp a -> Exp Bool)- -> Vector a- -> Acc (Vector a)-filterAcc p vec- = let arr = Acc.use vec- flags = Acc.map (boolToInt . p) arr- (targetIdx, len) = Acc.scanl' (+) 0 flags- arr' = Acc.backpermute (index1 $ the len) id arr- in- Acc.permute const arr' (\ix -> flags!ix ==* 0 ? (ignore, index1 $ targetIdx!ix)) arr- -- FIXME: This is abusing 'permute' in that the first two arguments are- -- only justified because we know the permutation function will- -- write to each location in the target exactly once.- -- Instead, we should have a primitive that directly encodes the- -- compaction pattern of the permutation function.---filterRef :: IArray UArray e- => (e -> Bool)- -> UArray Int e- -> UArray Int e-filterRef p xs- = let xs' = Prelude.filter p (elems xs)- in- listArray (0, Prelude.length xs' - 1) xs'----- Main--- ------run :: Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))-run n = withSystemRandom $ \gen -> do- vec <- randomUArrayR (-1,1) gen n- vec' <- convertUArray vec- --- return (run_ref vec, run_acc vec')- where- {-# NOINLINE run_ref #-}- run_ref xs () = filterRef (> 0) xs- run_acc xs () = filterAcc (>*0) xs-
− tests/simple/Radix.hs
@@ -1,86 +0,0 @@------ Radix sort for a subclass of element types-----module Radix where--import Random--import qualified Prelude-import Prelude hiding (zip, map, scanl, scanr, zipWith, fst)-import Data.Bits hiding (shiftL, shiftR, bit, testBit)-import Data.Array.Accelerate as Acc--import Data.List (sort)-import Data.Array.Unboxed (IArray, UArray, listArray, bounds, elems)-import System.Random.MWC-import Unsafe.Coerce----- Radix sort--- ------------class Elt e => Radix e where- passes :: Exp e -> Int -- Haskell-side control needs to know this- radix :: Exp Int -> Exp e -> Exp Int--instance Radix Int where -- may be 32- or 64-bit- passes = bitSize . (undefined :: Exp t -> t)- radix i e = i ==* (passes' e - 1) ? (radix' (e `xor` minBound), radix' e)- where- radix' x = (x `shiftR` i) .&. 1- passes' = constant . passes---- For IEEE-754 floating-point representation. Unsafe, but widely supported.----instance Radix Float where- passes _ = 32- radix i e = let x = (unsafeCoerce e :: Exp Int32)- in i ==* 31 ? (radix' (x `xor` minBound), radix' (floatFlip x))- where- floatFlip x = x `testBit` 31 ? (complement x, x) -- twos-complement negative numbers- radix' x = x `testBit` i ? (1,0)-------- A simple (parallel) radix sort implementation [1].------ [1] G. E. Blelloch. "Prefix sums and their applications." Technical Report--- CMU-CS-90-190. Carnegie Mellon University. 1990.----sortAcc :: Radix a => Vector a -> Acc (Vector a)-sortAcc = sortAccBy id--sortAccBy :: (Elt a, Radix r) => (Exp a -> Exp r) -> Vector a -> Acc (Vector a)-sortAccBy rdx arr = foldr1 (>->) (Prelude.map radixPass [0..p-1]) (use arr)- where- n = constant $ (arraySize $ arrayShape arr) - 1- p = passes . rdx . (undefined :: Vector e -> Exp e) $ arr-- deal f x = let (a,b) = unlift x in (f ==* 0) ? (a,b)- radixPass k v = let flags = map (radix (constant k) . rdx) v- idown = prescanl (+) 0 . map (xor 1) $ flags- iup = map (n-) . prescanr (+) 0 $ flags- index = zipWith deal flags (zip idown iup)- in- permute const v (\ix -> index1 (index!ix)) v---sortRef :: UArray Int Int -> UArray Int Int-sortRef xs = listArray (bounds xs) $ sort (elems xs)----- Main--- ------run :: Int -> IO (() -> UArray Int Int, () -> Acc (Vector Int))-run n = withSystemRandom $ \gen -> do- vec <- randomUArrayR (minBound,maxBound) gen n- vec' <- convertUArray vec- --- return (run_ref vec, run_acc vec')- where- {-# NOINLINE run_ref #-}- run_ref xs () = sortRef xs- run_acc xs () = sortAcc xs-
− tests/simple/SASUM.hs
@@ -1,35 +0,0 @@--module SASUM where--import Random--import System.Random.MWC-import Data.Array.Unboxed-import Data.Array.Accelerate as Acc----- Sum of absolute values--- -----------------------sasumAcc :: Vector Float -> Acc (Scalar Float)-sasumAcc xs- = Acc.fold (+) 0 . Acc.map abs $ Acc.use xs--sasumRef :: UArray Int Float -> UArray () Float-sasumRef xs- = listArray ((), ()) [Prelude.sum . Prelude.map abs $ elems xs]----- Main--- ------run :: Int -> IO (() -> UArray () Float, () -> Acc (Scalar Float))-run n = withSystemRandom $ \gen -> do- vec <- randomUArrayR (-1,1) gen n- vec' <- convertUArray vec- --- return (run_ref vec, run_acc vec')- where- {-# NOINLINE run_ref #-}- run_ref xs () = sasumRef xs- run_acc xs () = sasumAcc xs-
− tests/simple/SAXPY.hs
@@ -1,42 +0,0 @@-{-# LANGUAGE ParallelListComp #-}--module SAXPY where--import Random--import System.Random.MWC-import Data.Array.Unboxed-import Data.Array.Accelerate as Acc---- SAXPY--- ------saxpyAcc :: Float -> Vector Float -> Vector Float -> Acc (Vector Float)-saxpyAcc alpha xs ys- = let- xs' = use xs- ys' = use ys- in- Acc.zipWith (\x y -> constant alpha * x + y) xs' ys'--saxpyRef :: Float -> UArray Int Float -> UArray Int Float -> UArray Int Float-saxpyRef alpha xs ys- = listArray (bounds xs) [alpha * x + y | x <- elems xs | y <- elems ys]----- Main--- ------run :: Int -> IO (() -> UArray Int Float, () -> Acc (Vector Float))-run nelements = withSystemRandom $ \gen -> do- v1 <- randomUArrayR (-1,1) gen nelements- v2 <- randomUArrayR (-1,1) gen nelements- v1' <- convertUArray v1- v2' <- convertUArray v2- alpha <- uniform gen- --- return (run_ref alpha v1 v2, run_acc alpha v1' v2')- where- {-# NOINLINE run_ref #-}- run_ref alpha xs ys () = saxpyRef alpha xs ys- run_acc alpha xs ys () = saxpyAcc alpha xs ys-
− tests/simple/SMVM.hs
@@ -1,78 +0,0 @@-{-# LANGUAGE FlexibleContexts #-}--module SMVM where--import Random-import SMVM.Matrix--import System.Random.MWC-import Data.Array.Unboxed-import Data.Array.Accelerate (Vector, Segments, Acc)-import qualified Data.Array.Accelerate as Acc-import qualified Data.Vector.Unboxed as V----- Sparse-matrix vector multiplication--- -------------------------------------type SparseVector a = (Vector Int, Vector a)-type SparseMatrix a = (Segments, SparseVector a)--smvmAcc :: SparseMatrix Float -> Vector Float -> Acc (Vector Float)-smvmAcc (segd', (inds', vals')) vec'- = let- segd = Acc.use segd'- inds = Acc.use inds'- vals = Acc.use vals'- vec = Acc.use vec'- ---- vecVals = Acc.backpermute (Acc.shape inds) (\i -> Acc.index1 $ inds Acc.! i) vec- products = Acc.zipWith (*) vecVals vals- in- Acc.foldSeg (+) 0 products segd----- The reference version will be slow, with many conversions between--- array/vector/list representations. This will likely skew heap usage--- calculations, but oh well...----type USparseMatrix a = (UArray Int Int, (UArray Int Int, UArray Int a))--smvmRef :: USparseMatrix Float -> UArray Int Float -> UArray Int Float-smvmRef (segd, (inds, values)) vec- = listArray (0, rangeSize (bounds segd) - 1)- [sum [ values!i * vec!(inds!i) | i <- range seg] | seg <- segd' ]- where- segbegin = scanl (+) 0 $ elems segd- segend = scanl1 (+) $ elems segd- segd' = zipWith (\x y -> (x,y-1)) segbegin segend----- Main--- ------run :: Maybe FilePath -> IO (() -> UArray Int Float, () -> Acc (Vector Float))-run f = withSystemRandom $ \gen -> do- -- sparse-matrix- (segd', smat') <- maybe (randomCSRMatrix gen 512 512) (readCSRMatrix gen) f- let (ind',val') = V.unzip smat'-- segd <- convertVector segd'- ind <- convertVector ind'- val <- convertVector val'- let smat = (segd, (ind,val))-- -- vector- vec' <- uniformVector gen (V.length segd')- vec <- convertVector vec'-- -- multiply!- return (run_ref (v2a segd', (v2a ind',v2a val')) (v2a vec'), run_acc smat vec)- where- {-# NOINLINE run_ref #-}- run_ref smat vec () = smvmRef smat vec- run_acc smat vec () = smvmAcc smat vec- --- v2a :: (V.Unbox a, IArray UArray a) => V.Vector a -> UArray Int a- v2a vec = listArray (0, V.length vec - 1) $ V.toList vec-
− tests/simple/SMVM/Matrix.hs
@@ -1,75 +0,0 @@-{-# LANGUAGE BangPatterns, TupleSections #-}--module SMVM.Matrix (readCSRMatrix, randomCSRMatrix) where--import Random-import SMVM.MatrixMarket-import System.Random.MWC-import System.IO.Unsafe--import Data.Vector.Unboxed (Vector)-import qualified Data.Vector.Unboxed as V-import qualified Data.Vector.Unboxed.Mutable as M-import qualified Data.Vector.Algorithms.Intro as V--type CSRMatrix a = (Vector Int, Vector (Int,a))----- Read a sparse matrix from a MatrixMarket file. Pattern matrices are filled--- with random numbers in the range (-1,1).----{-# INLINE readCSRMatrix #-}-readCSRMatrix :: GenIO -> FilePath -> IO (CSRMatrix Float)-readCSRMatrix gen file = do- mtx <- readMatrix file- case mtx of- (RealMatrix dim l vals) -> csr dim l vals- (PatternMatrix dim l ix) -> csr dim l =<< mapM' (\(a,b) -> (a,b,) `fmap` uniformR (-1,1) gen) ix- (IntMatrix _ _ _) -> error "IntMatrix type not supported"- (ComplexMatrix _ _ _) -> error "ComplexMatrix type not supported"----- A randomly generated matrix of given size----{-# INLINE randomCSRMatrix #-}-randomCSRMatrix :: GenIO -> Int -> Int -> IO (CSRMatrix Float)-randomCSRMatrix gen rows cols = do- segd <- randomVectorR ( 0,cols`div`3) gen rows- let nnz = V.sum segd- inds <- randomVectorR ( 0,cols-1) gen nnz- vals <- randomVectorR (-1,1) gen nnz- return (segd, V.zip inds vals)----- Read elements into unboxed arrays, convert to zero-indexed compress sparse--- row format.----{-# INLINE csr #-}-csr :: (Int,Int) -> Int -> [(Int,Int,Float)] -> IO (Vector Int, Vector (Int,Float))-csr (m,_) l elems = do- mu <- M.new l- let goe _ [] = return ()- goe !n (x:xs) = let (i,j,v) = x in M.unsafeWrite mu n (i-1,j-1,v) >> goe (n+1) xs- goe 0 elems-- let cmp (x1,y1,_) (x2,y2,_) | x1 == x2 = compare y1 y2- | otherwise = compare x1 x2- V.sortBy cmp mu-- (i,j,v) <- V.unzip3 `fmap` V.unsafeFreeze mu- mseg <- M.new m- let gos !n rows | n < m = let (s,ss) = V.span (==n) rows in M.unsafeWrite mseg n (V.length s) >> gos (n+1) ss- | otherwise = V.unsafeFreeze mseg- seg <- gos 0 i- return (seg , V.zip j v)----- Lazier versions of things in Control.Monad----sequence' :: [IO a] -> IO [a]-sequence' ms = foldr k (return []) ms- where k m m' = do { x <- m; xs <- unsafeInterleaveIO m'; return (x:xs) }--mapM' :: (a -> IO b) -> [a] -> IO [b]-mapM' f as = sequence' (map f as)-
− tests/simple/SMVM/MatrixMarket.hs
@@ -1,133 +0,0 @@-{-# LANGUAGE OverloadedStrings, GADTs, StandaloneDeriving #-}--module SMVM.MatrixMarket (Matrix(..), readMatrix) where--import Control.Applicative hiding (many)--import Data.Complex-import Data.Attoparsec.Char8 hiding (parse, Result(..))-import Data.Attoparsec.Lazy (parse, Result(..))-import Data.ByteString.Lex.Double-import qualified Data.ByteString.Lazy as L----- | Specifies the element type. Pattern matrices do not have any elements,--- only indices, and only make sense for coordinate matrices and vectors.----data Field = Real | Complex | Integer | Pattern- deriving (Eq, Show)---- | Specifies either sparse or dense storage. In sparse (\"coordinate\")--- storage, elements are given in (i,j,x) triplets for matrices (or (i,x) for--- vectors). Indices are 1-based, so that A(1,1) is the first element of a--- matrix, and x(1) is the first element of a vector.------ In dense (\"array\") storage, elements are given in column-major order.------ In both cases, each element is given on a separate line.----data Format = Coordinate | Array - deriving (Eq, Show)---- | Specifies any special structure in the matrix. For symmetric and hermition--- matrices, only the lower-triangular part of the matrix is given. For skew--- matrices, only the entries below the diagonal are stored.----data Structure = General | Symmetric | Hermitian | Skew - deriving (Eq, Show)----- We really want a type parameter to Matrix, but I think that requires some--- kind of dynamic typing so that we can determine (a ~ Integral) or (a ~--- RealFloat), and so forth, depending on the file being read. This will do for--- our purposes...------ Format is: (rows,columns) nnz [(row,column,value)]----data Matrix where- PatternMatrix :: (Int,Int) -> Int -> [(Int,Int)] -> Matrix- IntMatrix :: (Int,Int) -> Int -> [(Int,Int,Int)] -> Matrix- RealMatrix :: (Int,Int) -> Int -> [(Int,Int,Float)] -> Matrix- ComplexMatrix :: (Int,Int) -> Int -> [(Int,Int,Complex Float)] -> Matrix--deriving instance Show Matrix-------------------------------------------------------------------------------------- Combinators-----------------------------------------------------------------------------------comment :: Parser ()-comment = char '%' *> skipWhile (not . eol) *> endOfLine- where eol w = w `elem` "\n\r"--floating :: Fractional a => Parser a-floating = do- mv <- readDouble <$> (skipSpace *> takeTill isSpace) -- readDouble does the fancy stuff- case mv of- Just (v,_) -> return . realToFrac $ v- Nothing -> fail "floating-point number"--integral :: Integral a => Parser a-integral = skipSpace *> decimal--format :: Parser Format-format = string "coordinate" *> pure Coordinate- <|> string "array" *> pure Array- <?> "matrix format"--field :: Parser Field-field = string "real" *> pure Real- <|> string "complex" *> pure Complex- <|> string "integer" *> pure Integer- <|> string "pattern" *> pure Pattern- <?> "matrix field"--structure :: Parser Structure-structure = string "general" *> pure General- <|> string "symmetric" *> pure Symmetric- <|> string "hermitian" *> pure Hermitian- <|> string "skew-symmetric" *> pure Skew- <?> "matrix structure"--header :: Parser (Format,Field,Structure)-header = string "%%MatrixMarket matrix"- >> (,,) <$> (skipSpace *> format)- <*> (skipSpace *> field)- <*> (skipSpace *> structure)- <* endOfLine- <?> "MatrixMarket header"--extent :: Parser (Int,Int,Int)-extent = do- [m,n,l] <- skipWhile isSpace *> count 3 integral <* endOfLine- return (m,n,l)--line :: Parser a -> Parser (Int,Int,a)-line f = (,,) <$> integral- <*> integral- <*> f- <* endOfLine------------------------------------------------------------------------------------- Matrix Market-----------------------------------------------------------------------------------matrix :: Parser Matrix-matrix = do- (_,t,_) <- header- (m,n,l) <- skipMany comment *> extent- case t of- Real -> RealMatrix (m,n) l `fmap` many (line floating)- Complex -> ComplexMatrix (m,n) l `fmap` many (line ((:+) <$> floating <*> floating))- Integer -> IntMatrix (m,n) l `fmap` many (line integral)- Pattern -> PatternMatrix (m,n) l `fmap` many ((,) <$> integral <*> integral)---readMatrix :: FilePath -> IO Matrix-readMatrix file = do- chunks <- L.readFile file- case parse matrix chunks of- Fail _ _ msg -> error $ file ++ ": " ++ msg- Done _ mtx -> return mtx-
− tests/simple/SharingRecovery.hs
@@ -1,177 +0,0 @@-{-# LANGUAGE TypeOperators, ScopedTypeVariables #-}-------- Some tests to make sure that sharing recovery is working.----module SharingRecovery where--import Prelude hiding (zip3)--import Data.Array.Accelerate as Acc---mkArray :: Int -> Acc (Array DIM1 Int)-mkArray n = use $ fromList (Z:.1) [n]--muchSharing :: Int -> Acc (Array DIM1 Int)-muchSharing 0 = (mkArray 0)-muchSharing n = Acc.map (\_ -> newArr ! (lift (Z:.(0::Int))) +- newArr ! (lift (Z:.(1::Int)))) (mkArray n)- where- newArr = muchSharing (n-1)--idx :: Int -> Exp DIM1-idx i = lift (Z:.i)--bfsFail :: Acc (Array DIM1 Int)-bfsFail = Acc.map (\x -> (map2 ! (idx 1)) + (map1 ! (idx 2)) + x) arr- where- map1 :: Acc (Array DIM1 Int)- map1 = Acc.map (\y -> (map2 ! (idx 3)) + y) arr- map2 :: Acc (Array DIM1 Int)- map2 = Acc.map (\z -> z + 1) arr- arr :: Acc (Array DIM1 Int)- arr = mkArray 666--twoLetsSameLevel :: Acc (Array DIM1 Int)-twoLetsSameLevel =- let arr1 = mkArray 1- in let arr2 = mkArray 2- in Acc.map (\_ -> arr1!(idx 1) + arr1!(idx 2) + arr2!(idx 3) + arr2!(idx 4)) (mkArray 3)--twoLetsSameLevel2 :: Acc (Array DIM1 Int)-twoLetsSameLevel2 =- let arr2 = mkArray 2- in let arr1 = mkArray 1- in Acc.map (\_ -> arr1!(idx 1) + arr1!(idx 2) + arr2!(idx 3) + arr2!(idx 4)) (mkArray 3)------- These two programs test that lets can be introduced not just at the top of a AST--- but in intermediate nodes.----noLetAtTop :: Acc (Array DIM1 Int)-noLetAtTop = Acc.map (\x -> x + 1) bfsFail--noLetAtTop2 :: Acc (Array DIM1 Int)-noLetAtTop2 = Acc.map (\x -> x + 2) $ Acc.map (\x -> x + 1) bfsFail-----------simple :: Acc (Array DIM1 (Int,Int))-simple = Acc.map (\_ -> a ! (idx 1)) d- where- c = use $ Acc.fromList (Z :. 3) [1..]- d = Acc.map (+1) c- a = Acc.zip d c---------------------------------------------------------------------------------------- sortKey is a real program that Ben Lever wrote. It has some pretty interesting--- sharing going on.----sortKey :: (Elt e)- => (Exp e -> Exp Int) -- ^mapping function to produce key array from input array- -> Acc (Vector e)- -> Acc (Vector e)-sortKey keyFun arr = foldl sortOneBit arr (Prelude.map lift ([0..31] :: [Int]))- where- sortOneBit inArr bitNum = outArr- where- keys = Acc.map keyFun inArr-- bits = Acc.map (\a -> (Acc.testBit a bitNum) ? (1, 0)) keys- bitsInv = Acc.map (\b -> (b ==* 0) ? (1, 0)) bits-- (falses, numZeroes) = Acc.scanl' (+) 0 bitsInv- trues = Acc.map (\x -> (Acc.the numZeroes) + (Acc.fst x) - (Acc.snd x)) $- Acc.zip ixs falses-- dstIxs = Acc.map (\x -> let (b, t, f) = unlift x in (b ==* (constant (0::Int))) ? (f, t)) $- zip3 bits trues falses- outArr = scatter dstIxs inArr inArr -- just use input as default array- --(we're writing over everything anyway)- --- ixs = enumeratedArray (shape arr)---- | Copy elements from source array to destination array according to a map. For--- example:------ default = [0, 0, 0, 0, 0, 0, 0, 0, 0]--- map = [1, 3, 7, 2, 5, 8]--- input = [1, 9, 6, 4, 4, 2, 5]------ output = [0, 1, 4, 9, 0, 4, 0, 6, 2]------ Note if the same index appears in the map more than once, the result is--- undefined. The map vector cannot be larger than the input vector.----scatter :: (Elt e)- => Acc (Vector Int) -- ^map- -> Acc (Vector e) -- ^default- -> Acc (Vector e) -- ^input- -> Acc (Vector e) -- ^output-scatter mapV defaultV inputV = Acc.permute (const) defaultV pF inputV- where- pF ix = lift (Z :. (mapV ! ix))----- | Create an array where each element is the value of its corresponding row-major--- index.------enumeratedArray :: (Shape sh) => Exp sh -> Acc (Array sh Int)---enumeratedArray sh = Acc.reshape sh--- $ Acc.generate (index1 $ shapeSize sh) unindex1--enumeratedArray :: Exp DIM1 -> Acc (Array DIM1 Int)-enumeratedArray sh = Acc.generate sh unindex1--unzip3 :: forall sh. forall e1. forall e2. forall e3. (Shape sh, Elt e1, Elt e2, Elt e3)- => Acc (Array sh (e1, e2, e3))- -> (Acc (Array sh e1), Acc (Array sh e2), Acc (Array sh e3))-unzip3 abcs = (as, bs, cs)- where- (bs, cs) = Acc.unzip bcs- (as, bcs) = Acc.unzip- $ Acc.map (\abc -> let (a, b, c) = unlift abc :: (Exp e1, Exp e2, Exp e3)- in lift (a, lift (b, c))) abcs--testSort :: Acc (Vector Int)-testSort = sortKey id $ use $ fromList (Z:.10) [9,8,7,6,5,4,3,2,1,0]------------------------------------------------------------------------------- map1 has children map3 and map2.--- map2 has child map3.--- Back when we still used a list for the NodeCounts data structure this mean that--- you would be merging [1,3,2] with [2,3] which violated precondition of (+++).--- This tests that the new algorithm works just fine on this.----orderFail :: Acc (Array DIM1 Int)-orderFail = Acc.map (\_ -> map1 ! (idx 1) + map2 ! (idx 1)) arr- where- map1 = Acc.map (\_ -> map3 ! (idx 1) + map2 ! (idx 2)) arr- map2 = Acc.map (\_ -> map3 ! (idx 3)) arr- map3 = Acc.map (+1) arr- arr = mkArray 42---------------------------------------------------------------------------- Tests array-valued lambdas in conjunction with sharing recovery.----pipe :: Acc (Vector Int)-pipe = (acc1 >-> acc2) xs- where- z :: Acc (Scalar Int)- z = unit 0-- xs :: Acc (Vector Int)- xs = use $ fromList (Z:.10) [0..]-- acc1 :: Acc (Vector Int) -> Acc (Vector Int)- acc1 = Acc.map (\_ -> the z)-- acc2 :: Acc (Vector Int) -> Acc (Vector Int)- acc2 arr = let arr2 = use $ fromList (Z:.10) [10..] in Acc.map (\_ -> arr2!constant (Z:.(0::Int))) (Acc.zip arr arr2)
− tests/simple/SliceExamples.hs
@@ -1,114 +0,0 @@-{-# LANGUAGE TypeOperators, ScopedTypeVariables #-}-module SliceExamples where--import Data.Array.Accelerate as Acc-import qualified Data.Array.Unboxed as UA---- y--- ^--- | 3 4 --- | 1 2--- -------> x----arr :: Acc (Array DIM2 Int)-arr = use $ fromList (Z:.2:.2) [1,2,3,4]--slice1 :: Exp (Z:.Int:.All:.All)-slice1 = lift $ Z:.(2::Int):.All:.All--slice2 :: Exp (Z:.All:.Int:.All)-slice2 = lift $ Z:.All:.(2::Int):.All--slice3 :: Exp (Z:.All:.All:.Int)-slice3 = lift $ Z:.All:.All:.(2::Int)---- Replicate into z-axis--- should produce [1,2,3,4,1,2,3,4]-test1 :: Acc (Array DIM3 Int)-test1 = Acc.replicate slice1 arr---- Replicate into y-axis--- should produce [1,2,1,2,3,4,3,4]-test2 :: Acc (Array DIM3 Int)-test2 = Acc.replicate slice2 arr---- Replicate into x-axis--- should produce [1,1,2,2,3,3,4,4]-test3 :: Acc (Array DIM3 Int)-test3 = Acc.replicate slice3 arr------- repN. Replicates an array into the rightmost dimension of--- the result array.----repN :: forall sh e. (Shape sh, Elt e)- => Int - -> Acc (Array sh e)- -> Acc (Array (sh:.Int) e)-repN n a = Acc.replicate (lift (Any:.n :: Any sh:.Int)) a--repExample :: Acc (Array DIM2 Int) -> Acc (Array DIM3 Int)-repExample = repN 2--repExample' :: Acc (Array DIM2 Int) -> Acc (Array DIM3 Int)-repExample' = Acc.replicate (lift (Z:.All:.All:.(2::Int)))--slice1' :: Any (Z:.Int:.Int) :. Int-slice1' = Any:.2--slice2' :: Z:.All:.All:.Int-slice2' = Z:.All:.All:.2--run1 :: IO (() -> UA.UArray (Int,Int,Int) Int, () -> Acc (Array DIM3 Int))-run1 = return (\() -> UA.array ((0,0,0),(1,1,1)) [ ((0,0,0), 1)- , ((0,0,1), 2)- , ((0,1,0), 3)- , ((0,1,1), 4)- , ((1,0,0), 1)- , ((1,0,1), 2)- , ((1,1,0), 3)- , ((1,1,1), 4) ]- ,\() -> test1)--run2 :: IO (() -> UA.UArray (Int,Int,Int) Int, () -> Acc (Array DIM3 Int))-run2 = return (\() -> UA.array ((0,0,0),(1,1,1)) [ ((0,0,0), 1)- , ((0,0,1), 2)- , ((0,1,0), 1)- , ((0,1,1), 2)- , ((1,0,0), 3)- , ((1,0,1), 4)- , ((1,1,0), 3)- , ((1,1,1), 4) ]- ,\() -> test2)--run3 :: IO (() -> UA.UArray (Int,Int,Int) Int, () -> Acc (Array DIM3 Int))-run3 = return (\() -> UA.array ((0,0,0),(1,1,1)) [ ((0,0,0), 1)- , ((0,0,1), 1)- , ((0,1,0), 2)- , ((0,1,1), 2)- , ((1,0,0), 3)- , ((1,0,1), 3)- , ((1,1,0), 4)- , ((1,1,1), 4) ]- ,\() -> test3)-run4 :: IO (() -> UA.UArray (Int,Int,Int) Int, () -> Acc (Array DIM3 Int))-run4 = return (\() -> UA.array ((0,0,0),(1,1,1)) [ ((0,0,0), 1)- , ((0,0,1), 1)- , ((0,1,0), 2)- , ((0,1,1), 2)- , ((1,0,0), 3)- , ((1,0,1), 3)- , ((1,1,0), 4)- , ((1,1,1), 4) ]- ,\() -> repExample arr)--run5 :: IO (() -> UA.UArray (Int,Int,Int) Int, () -> Acc (Array DIM3 Int))-run5 = return (\() -> UA.array ((0,0,0),(1,1,1)) [ ((0,0,0), 1)- , ((0,0,1), 1)- , ((0,1,0), 2)- , ((0,1,1), 2)- , ((1,0,0), 3)- , ((1,0,1), 3)- , ((1,1,0), 4)- , ((1,1,1), 4) ]- ,\() -> repExample' arr)