AccelerateHS / AccelerateHS/accelerate

Performance issues

Open
#305 14 comments 0 reactions 0 assignees View on GitHub
llvm backend
Dominant language
Haskell
Stars
1k
Forks
135
PR merge metrics
No merged PRs in 30d

Description

I'm trying to use accelerate to get better-than-hmatrix performance on a program similar to this one:

``` haskell
module Main where

import Data.IORef
import Data.Array.Accelerate
import Data.Array.Accelerate.CUDA
--import Data.Array.Accelerate.Interpreter

import Prelude hiding (zipWith, replicate, (++), sum, map)

type Matrix e = Array DIM2 e

dot :: (Elt a, IsNum a) => Acc (Vector a) -> Acc (Vector a) -> Acc (Scalar a)
dot xs ys = fold1 (+) (zipWith (*) xs ys)

norm xs = map sqrt (dot xs xs)

mult
:: (Elt a, IsNum a) =>
Acc (Matrix a) -> Acc (Vector a) -> Acc (Vector a)

mult m v = fold1 (+) (zipWith (*) m vs)
where
n = indexHead . indexTail $ shape m
vs = replicate (lift $ Z :. n :. All) v

main = do
let n = 1000 :: Int

let m = fill (constant $ Z :. n :. n) (constant (1 :: Float))
vRef <- newIORef $ fill (constant $ Z :. n) (constant 1)

let iterate = do
v <- readIORef vRef
let mv = mult m v
vv = norm v
v' = map (/ the vv) mv
--writeIORef vRef (compute v')
writeIORef vRef v'

traverse (const iterate) [1..1000]

v <- readIORef vRef
print $ run (norm v)
```

Here's the output of profiling:

```
Tue Feb 9 14:27 2016 Time and Allocation Profiling Report (Final)

TestAccelerate +RTS -p -h -s -RTS

total time = 4.03 secs (4032 ticks @ 1000 us, 1 processor)
total alloc = 4,114,779,024 bytes (excludes profiling overheads)

COST CENTRE MODULE %time %alloc

compile.code Data.Array.Accelerate.CUDA.Compile 15.1 33.1
ppr Data.Array.Accelerate.CUDA.CodeGen.Base 10.1 11.1
hashWithSalt Data.Array.Accelerate.CUDA.CodeGen.Monad 2.8 5.3
lookup/go Data.HashTable.ST.Basic 1.6 0.1
compile.key Data.Array.Accelerate.CUDA.Compile 1.5 3.7
rebuildPreOpenExp Data.Array.Accelerate.Trafo.Substitution 1.4 1.3
== Data.Array.Accelerate.Trafo.Sharing 1.4 1.8
codegenOpenExp.cvtE Data.Array.Accelerate.CUDA.CodeGen 1.2 1.2
withLifetime Data.Array.Accelerate.Lifetime 1.1 0.1
insert Data.HashTable.ST.Basic 1.1 0.3
readDelLoad Data.HashTable.ST.Basic 1.1 0.6
blockSize Data.Array.Accelerate.CUDA.Analysis.Launch 0.8 1.7
fmap Data.Array.Accelerate.Trafo.Substitution 0.8 1.2
readArray Data.HashTable.Internal.IntArray 0.7 1.0
```

And here's the output of -s:

```
6,372,076,320 bytes allocated in the heap
3,751,952,272 bytes copied during GC
164,069,960 bytes maximum residency (49 sample(s))
2,371,928 bytes maximum slop
328 MB total memory in use (0 MB lost due to fragmentation)

Tot time (elapsed) Avg pause Max pause
Gen 0 12011 colls, 0 par 3.477s 3.440s 0.0003s 0.0012s
Gen 1 49 colls, 0 par 5.114s 5.071s 0.1035s 0.2412s

TASKS: 6 (2 bound, 4 peak workers (4 total), using -N1)

SPARKS: 0 (0 converted, 0 overflowed, 0 dud, 0 GC'd, 0 fizzled)

INIT time 0.002s ( 0.002s elapsed)
MUT time 4.539s ( 6.391s elapsed)
GC time 6.669s ( 6.604s elapsed)
RP time 0.000s ( 0.000s elapsed)
PROF time 1.922s ( 1.907s elapsed)
EXIT time 0.003s ( 0.003s elapsed)
Total time 13.140s ( 12.999s elapsed)

Alloc rate 1,403,793,613 bytes per MUT second

Productivity 34.6% of total user, 35.0% of total elapsed

gc_alloc_block_sync: 0
whitehole_spin: 0
gen[0].sync: 0
gen[1].sync: 0
```

As you can see, a huge amount of time is spent in GC. That clearly should not be the case for a program that's just number crunching.

An obvious potential issue is that I'm building a very large kernel with each iteration and then running only at the end. The solution would be to express the iteration as an Acc -> Acc function and then use awhile to run it a fixed number of times. Unfortunately, it is very difficult for me to turn my real program into a pure Acc -> Acc function, since it does a large graph traversal that relies on IORefs. I've also tried inserting a compute (`id >-> id`) into each iteration, with no effect.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.