Running debug threaded programs with heap profiling triggers an assertion in the RTS. Running them without debugging is a segfault.
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: Fusion doesn't work. Vectorised program 1000x slower than the C version with small matrix sizes. For 1000x1000 with 10% fill ratio it takes about 1s and allocates 400M memory, while the C program is instantaneous. For larger sizes it dies with OOM.
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. Version with -fllvm takes 30 min to compile, suspect complexity problems in LLVM mangler.
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 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.
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. This needs a parallel update operation, but we currently can't guarantee atomic updates of compound types such as tuples.
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.
Status: Sequential vectorised version does not compile due to a loop in SpecConstr (#4831).
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.
A: Uses mutable Data.Vectors for intermediate buffers.
B: Uses mutable Data.Vectors, forkIO and atomicModifyIORef. Concurrent threads fill a shared output vector. Code is uglier than the C version.
C: Sequential C version with pre-allocated mutable intermediate buffers.
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 loop in SpecConstr (#4831). LLVM versions take >10 min to compile (#4838 (closed))
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.
A : Time stated is end-to-end, not just for the kernel.
Status: -fasm vesions compile but fusion doesn't work so it's very slow. LLVM versions take 30min to compile (#4838 (closed))
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.
vectorised means it's been through the DPH vectorising transform.
vector is a hand written version using immutable Data.Vectors
vector-mutable is a hand written version using mutable Data.Vectors.
vector-immutable means the same as vector and is used when there is also an mutable version.
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.
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.
Runtime of reference / runtime of benchmark.
Measures how much faster a benchmark is relative to the reference.
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.
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.