This gist compares the performance of Julia, Nim, C++ and R - the latter using either POMP, or LibBi in a simple simulation of an SIR epidemiological model. In addition to keeping track of susceptibles, infecteds and recovereds, I also store the cumulative number of infections. Time moves in discrete steps, and the algorithm avoids language-specific syntax features to make the comparison as fair as possible, including using the same algorithm for generating binomial random numbers and the same random number generator; the exception are the R versions, POMP uses the standard R Mersenne Twister for the random number generator; I'm not sure what LibBi uses. The algorithm for generating random binomial numbers is only really suitable for small np.
Benchmarks were run on a Mac Pro (Late 2013), with 3 Ghz 8-core Intel Xeon E3, 64GB 1866 Mhz RAM, running OSX v 10.11.3 (El Capitan), using Julia v0.6.1, Nim v0.17.3, clang v5.0.0, emscripten v1.37.34, node v8.9.1, and R v3.3.2.
nim c -d:release --passC="-flto -ffast-math" sir
The first number is time taken in s, the second the result of averaging the cumulative number of infections (
Y in the code).
Native, optimised version
Based on the comments below, I wrote an optimised version,
nim c -d:release --passC="-flto -ffast-math" sir_opt ./sir_opt
Nim can also compile to Webassembly via Emscripten; using
nim.cfg linked below:
nim c -d:release -d:wasm -o:sir_opt.js sir_opt node ./sir_opt.js
0.058961 seconds (2.09 k allocations: 232.998 KiB) 21.019
There is also a modified version that uses tuples (and hence is also a bit neater), adds in a couple of macros, and uses an algorithm to work out random binomials that is faster for small np. Thanks to @DNF2 and @ChrisRackauckas (see below) for tips here.
0.045802 seconds (87 allocations: 14.123 KiB) 21.028
g++ -std=c++11 -O3 -o sir_cpp sir.cpp
To compile the C++ code into Webassembly, I use Emscripten.
em++ -s WASM=1 -s SINGLE_FILE=1 -std=c++11 -O3 -o sir_cpp.js sir.cpp
R, using POMP
Loading required package: methods user system elapsed 0.741 0.108 0.849
R, using LibBi
Model: sir Run time: 0.073982 seconds Number of samples: 1000  20.251
Note that it takes much longer in practice than above for rbi to run the model, due to the need for compilation, which takes a lot longer than Julia. Thanks to @sbfnk for some excellent examples.
Any suggestions for improvements welcome!