PPoPP 2019 Hybrid TM, Mutable Fields GHC Benchmarks
All the resources needed to build and run our benchmarks are
included here.
Installing:
This has been tested on a fresh OS install (Ubuntu 18.04.1 LTS) on a machine
that supports Intel TSX.
$ uname -a
Linux d14005 4.15.0-39-generic #42-Ubuntu SMP Tue Oct 23 15:48:01 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.1 LTS
Release: 18.04
Codename: bionic
Prerequisites
We need gcc
, g++
, make
, gmp
, and ncurses
:
$ sudo apt install gcc g++ make libgmp-dev libncurses-dev
Make an environment variable GHC_COMPILERS
that has a path to where the
compilers will be installed. We used $HOME/ghc-8
as our path:
$ mkdir $HOME/ghc-8
$ export GHC_COMPILERS=$HOME/ghc-8
Installing the Binary Distribution:
Unpack and configure the binary distribution for the hybrid compiler:
$ cd $GHC_COMPILERS
... get the binary distribution file for the hybrid compiler
$ tar -xvf ghc-8.0.2-x86_64-mutable-fields-hybrid.tar.xz
$ cd ghc-hybrid
$ ./configure --prefix $GHC_COMPILERS/bin-hybrid
$ make install
Repeat for the compiler with the fine-grain based TM runtime:
$ cd $GHC_COMPILERS
... get the binary distribution file for the fine-grain compiler
$ tar -xvf ghc-8.0.2-x86_64-mutable-fields-fine.tar.xz
$ cd ghc-fine
$ ./configure --prefix $GHC_COMPILERS/bin-fine
$ make install
GHC should now be installed to $GHC_COMPILERS/bin-hybrid/bin/ghc
and $GHC_COMPILERS/bin-fine/bin/ghc
.
Building Compiler from Source:
The GHC sources are available on GitHub:
- https://github.com/fryguybob/ghc/releases/tag/PPoPP2016-mutable-fields-hybrid
- https://github.com/fryguybob/ghc/releases/tag/PPoPP2016-mutable-fields-fine
They are much easier to build using the source distribution packaging.
You can skip this step, but you will not get the early subscription
TM version for comparison to late subscription.
We will build the compiler from source using the binary distribution's hybrid
GHC. It should be buildable with any GHC close to version 8.0.2, just point to
the desired compiler in the --with-ghc
configure field.
Configure and build the hybrid
TM compiler (GHC takes a long tome to build):
$ cd $GHC_COMPILERS
... get the source distribution file for the hybrid compiler
$ tar -xvf ghc-8.0.2-mutable-fields-hybrid-src.tar.xz
$ cd src-hybrid
$ ./configure --prefix $GHC_COMPILERS/build-hybrid --with-ghc=$GHC_COMPILERS/bin-hybrid/bin/ghc
$ make
$ make install
Configure and build the hybrid-early
TM compiler (following these steps it will only
have to rebuild the rts):
$ cd $GHC_COMPILERS/src-hybrid
$ cd src-hybrid
$ sed -i 's/#define HTM_LATE_LOCK_SUBSCRIPTION/\/\/#define HTM_LATE_LOCK_SUBSCRIPTION/' rts/STM.c
$ ./configure --prefix $GHC_COMPILERS/build-hybrid-early --with-ghc=$GHC_COMPILERS/bin-hybrid/bin/ghc
$ make
$ make install
Configure and build the fine
TM compiler (GHC takes a long tome to build):
$ cd $GHC_COMPILERS
... get the source distribution file for the fine-grain compiler
$ tar -xvf ghc-8.0.2-mutable-fields-fine-src.tar.xz
$ cd src-hybrid
$ ./configure --prefix $GHC_COMPILERS/build-fine --with-ghc=$GHC_COMPILERS/bin-hybrid/bin/ghc
$ make
$ make install
Benchmarks
Benchmarks are packaged so that only our GHC is needed for building. No cabal
is needed and required packages are all included with minimal modifications to
remove irrelevant dependencies.
Picking the compilers to use
Use links to set the compilers to use as the hybrid
, hybrid-early
, and fine
compilers.
$ cd $GHC_COMPILERS
$ ln -s build-hybrid hybrid
$ ln -s build-hybrid-early hybrid-early
$ ln -s build-fine fine
Building the Benchmarks
Get and build the benchmarks (start in the directory of your
choice, we will use $HOME
):
$ cd $HOME
... get the benchmark source distribution
$ tar -xvf PPoPP2019-mutable-fields-benchmarks.tar.xz
$ cd PPoPP2019
$ ./build.sh
This should build 24 benchmark binaries in the bin
child directory:
$ ls bin
HAMT-MUT-fine HAMT-TVAR-hybrid-early RBTREE-TVAR-hybrid
HAMT-MUT-hybrid RBTREE-MUT-fine RBTREE-TVAR-hybrid-early
HAMT-MUT-hybrid-early RBTREE-MUT-hybrid TREAP-MUT-fine
HAMT-TSTRUCT-fine RBTREE-MUT-hybrid-early TREAP-MUT-hybrid
HAMT-TSTRUCT-hybrid RBTREE-TSTRUCT-fine TREAP-MUT-hybrid-early
HAMT-TSTRUCT-hybrid-early RBTREE-TSTRUCT-hybrid TREAP-TVAR-fine
HAMT-TVAR-fine RBTREE-TSTRUCT-hybrid-early TREAP-TVAR-hybrid
HAMT-TVAR-hybrid RBTREE-TVAR-fine TREAP-TVAR-hybrid-early
Running the Benchmarks
The results for each figure are run and plotted with their own script.
For figures 1a, 1b, and 1c there are a total of 24*threads
individual
runs of around 1.3 seconds each. On our 72 thread machine that comes to
around 40 minutes for the first three figures.
$ ./fig-1.sh
A plot of each figure will be in the output
child directory:
$ ls output/
fig-1a.html fig-1b.html fig-1c.html
The figures can be viewed with a browser that supports javascript. These plots
should match the findings in the paper.
The second set of figures should be quicker:
$ ./fig-2a.sh
$ ./fig-2bc.sh
Producing:
$ ls output/
fig-1a.html fig-1b.html fig-1c.html fig-2a.html fig-2b.html fig-2c.html
Troubleshooting
One difficult to predict aspect of these benchmarks is the layout of the machine.
We have guessed some common architectures, but they not match what you actually
have on your machine. The files topo-cores-sockets-threads-*
in the benchmark
suite are a configuration file for the Haskell runtime system's +RTS -qa
flag.
Each line is the processor to bind each GHC capability's thread affinity. We
attempt to fill the cores (without hyperthreads) on the first socket, then
subsequent sockets. Once all the cores are used we allocate hyperthreads. The
tool mktopo.hs
can be used to produce different layouts.