Summary

QuickHull: vectorised.par.N1 version is 6x slower than the immutable Data.Vector version in absolute terms.

QuickSort: vectorised.seq version doesn't compile due to a blow-up in SpecConstr.

SMVM: appears to have rotted since the change to Data.Vector. Doesn't appear to read the input files properly.

BarnesHut: builds but runs very slowly. The immediate problem is that some dictionaries are recursive, their methods don't inlined, so fusion doesn't work.

ToDo

Benchmarks are currently being run with -fasm, and not via the LLVM backend. This will affect comparisons with C, but not with Data.Vector as it uses the same backend.

Flat Parallelism

Flat parallel programs are ones in which parallel computations do not invoke further parallel computations. For Repa, this means that the value of each element in a given array can be computed independently of the others. These should run as fast as equivalent programs using immutable Data.Vector. We'd also hope to get close to the performance of C programs using equivalent algorithms, though this is a harder comparison due to differences in the back-end code generator.

Performs high-pass filtering using 2D and 3D FFTs. These are naive benchmarks used for regression testing only. They divide right down to (rank generalise) two-point vectors and construct the result using copying append. Using an inplace algorithm (like with FFTW) would be significantly faster.

ToDo: Runs ok, but need other versions for comparison.

Statically Nested Parallelism

Statically nested parallelism is where the parallelism has a fixed, finite depth. For example mapP f (filterP g xs). Statically nested programs are easier to vectorise than dynamically nested programs. At present, single threaded statically nested programs should run as fast as equivalent Data.Vector programs. Parallel versions should display a good speedup.

A: The core for the vectorised.seq version is equivalent to the vector version. We expect the backend has compiled it differently. Check this again with LLVM.
B: The vectorised.par version runs faster than vectorised.seq because the latter has a duplicate counter in the inner loop. We need a duplicate-loop-counter removal optimisation.

The Sieve of Eratosthenes using parallel writes into a sieve structure represented as an array of Bools.

Todo: We currently don't have a proper parallel implementation of this benchmark, as we are missing a parallel version of default backpermute. The problem is that we need to make the representation of parallel arrays of Bool dependent on whether the hardware supports atomic writes of bytes. Investigate whether any of the architectures relevant for DPH actually do have trouble with atomic writes of bytes (aka Word8).

Sort a vector of doubles by recursively splitting it and sorting the two halves. This is a naive benchmark used for regression testing only. We divide right down to two-point vectors and construct the result using copying append. A production algorithm would switch to an in-place sort once the size of the vector reaches a few thousand elements. N=100k.

name

runtime

speedup

efficiency

notes

dph.quicksort.vectorised.par.N1

428ms

1

1

dph.quicksort.vectorised.par.N2

417ms

1.02

dph.quicksort.vectorised.par.N4

422ms

1.01

Status: Sequential vectorised version does not compile due to a blowup in SpecConstr.

Given a set of points in the plane, compute the sequence of points that encloses all points in the set. This benchmark is interesting as it is the simplest code that exploits the ability to implement divide-and-conquer algorithms with nested data parallelism. N=1M.

Status: Benchmark scales but single threaded vectorised.par version is 6x slower than version using immutable Data.Vectors. QuickHull is based around filtering operations, so the fact that Evens is also slow is probably related.

Dynamically Nested Parallelism with Algebraic Data Types

These programs also use user defined algebraic data types. Vectorization of these programs is still a work in progress.

Counts the number of words in a string. This is a naive divide-and-conquer benchmark that divides right down to a single character. A production program would switch to a simple sequential algorithm once the string chunks were small enough. It's a good stress test for the vectoriser though.

Status: Sequential vectorised version does not compile due to blowup in SpecConstr.Todo: Generate some larger test data. Right now it's just got a small test string baked into the program.

This benchmark implements the Barnes-Hut algorithm to solve the n-body problem in two dimensions. There is a naive O(n2) version in the same package.

name

runtime

speedup

efficiency

notes

dph.nbody.vector.seq.N4

100ms

1

A

dph.nbody.vectorised.seq.N4

4681ms

~50x slower

dph.nbody.vectorised.par.N1

2381ms

~25x slower

A : Time stated is end-to-end, not just for the kernel.

Status: Compiles, but fusion doesn't work so it's very slow. ToDo: Make the vectorised version give the same output as the vector version. The benchmark setup is a bit different. Fixing this won't cause a 50x speed difference though.

vector-immutable means the same as vector and is used when there is also an mutable version.

parallelism

Whether a benchmark is natively parallel or sequential.

Parallel versions are also run single threaded (with -N1) and sequential versions are also run with (-N4) so we get the parallel GC.

Parallel versions with -N1 will tend to be slower than natively sequential versions due to overheads for supporting parallelism.

threads

Value passed to Haskell Runtime with -N threads flag.

Number of Haskell Execution Contexts (HECs) used when running the benchmark.

Can be less than the number of hardware threads / cores in the physical machine.

speedup

Runtime of reference / runtime of benchmark.

Measures how much faster a benchmark is relative to the reference.

(relative) efficiency

Speedup / number of threads.

Indicates the communication overhead involved with running something in parallel.

Can be > 1 if the parallel version running with a single thread is faster than the sequential reference version.

Status:

BROKEN: Benchmark doesn't compile, or crashes when run.

SLOWDOWN: Benchmark gets slower as number of threads increases.

SLOWLORIS: Benchmark scales as the number of threads increases, but the absolute performance is not acceptable compared with equivalent versions using immutable Data.Vectors. We do not have a setup in which the parallel version runs faster than the sequential reference version. Cute, but too slow to be useful.