Tag Archives: Julia

A website with mortality charts built using Julia

By: Karl Pettersson

Re-posted from: https://www.dusty-test.klpn.se/posts/2017-03-01-mcsite.html

A website with mortality charts built using Julia

Posted on 2017-03-01

by Karl Pettersson.

Tags: ,

Since 2015, I have run a website with cause-specific mortality trends.
The idea is to have a static site, which gives fast and easy access to
information about international mortality trends, using open data
available from WHO (2025), which, for many countries, covers the time
period from 1950 up until recent times. The website is inspired by
Whitlock (2012), which contains comprehensible charts with mortality trends
based on these data, but has been unmaintained since 2013, when its
creator died. Other sites with international cause-specific mortality
trends I have seen tend to be slower, due to dynamic chart generation,
and to cover only shorter time periods.

My implementation of the site generator, which was written in Python and
R, had become rather messy, and the chart tools I used
(matplotlib and
ggplot2) are not really suited to make
interactive web charts. I decided to rewrite the routines to generate
the charts and the site files in Julia (albeit with the help of some
non-Julia tools, as described below). These routines are now available
as a GitHub repo, and I use
them to generate the site in both
English and
Swedish versions.

The site is built as follows with the Julia package (see the README in
the repo for instructions). The whole process is controlled with a JSON
configuration
file
.
YAML, using some non-JSON features, might be less cumbersome, and will
perhaps be used once there is full YAML write support implemented in
Julia. Julia functions mentioned are in the main
Mortchartgen.jl
file, if not otherwise stated.

  1. The WHO (2025) data files are downloaded and read into a MySQL
    database, using the functions in the
    Download.jl
    file.
  2. These data files contain cause of death codes from many different
    versions of the ICD classifications for different time periods and
    countries, and the codes are also often at a much more detailed
    level than I use in the charts. Therefore, the data on deaths is
    grouped using regular expressions defined in the configuration file.
    To avoid repeating this time-consuming regular expression matching,
    the resulting DataFrames can be saved in CSV files. There are still
    some issues with unsupported datatypes in the
    MySQL.jl package, which mean
    that grouping cannot be done at the SQL level and that prepared SQL
    statements cannot be used.
  3. The charts themselves are generated from the DataFrames created in
    step 2, using the Python Bokeh
    library
    , which is well-suited
    for interactive web visualizations. I call Bokeh directly using
    PyCall, instead of using the
    Bokeh.jl package, which is
    unmaintained. There is a batchplot function to generate all the
    charts for the site using the settings in the configuration file.
  4. The writeplotsite function generates the charts as well as HTML
    tables with links to the charts, a documentation file in Markdown
    format, and navigation menus for a given language, and copies these
    to a given output location. To generate the site files, except for
    the charts themselves, templates processed with
    Mustache.jl
    are used.
  5. The final generation of the site is done using
    Hakyll, a static site generator
    written in Haskell. In the output directory generated in step 4,
    there will be a Haskell source file, site.hs, which, provided that
    a Haskell complier and the Hakyll libraries are installed, can be
    compiled to an executable file. This file can then be run as
    ./site build to generate the site, which can then be uploaded to a
    web server. The resulting site is static in the sense that it has no
    code running on the server-side (but rendering the charts requires
    JavaScript on the client side).

References

Whitlock, Gary. 2012. Mortality Trends [archived 21 december 2014].” http://web.archive.org/web/20141221203103/http://www.mortality-trends.org/.
WHO. 2025. “WHO Mortality Database.” https://www.who.int/data/data-collection-tools/who-mortality-database.

Debugging Julia with Address Sanitizer

By: Tim Besard

Re-posted from: https://blog.maleadt.net/2017/02/24/julia-asan/

Address sanitizer is a useful tool for
debugging various memory problems, from invalid accesses to mismanagement or leaks. It is
similar to Valgrind’s
memcheck, but uses compile-time
instrumentation to lower the cost.

In this post I’ll explain how to use Clang’s address sanitizer (or ASAN) with Julia. This is
somewhat tricky, as the Julia compiler uses LLVM for code generation purposes. Long story
short, this implies that all instances of LLVM (ie. the one Julia is compiled with, and the
one used for code generation) have to match up exactly for the instrumentation to work as
expected.

LLVM toolchain

We’ll start by building a toolchain to compile Julia with. As mentioned before, all LLVM
instances in play have to match up exactly for instrumentation to work, so we’ll use Julia’s
build infrastructure to generate us an LLVM toolchain.

Start by checking-out Julia, and creating an out-of-tree build directory:

$ git clone https://github.com/JuliaLang/julia
$ cd julia
$ make O=configure sanitize_toolchain

This build will need to provide clang, so create a Make.user containing
BUILD_LLVM_CLANG=1. In addition, LLVM does not build its sanitizers with autotools, so add
override LLVM_USE_CMAKE=1 to that file as well. And because that triggers LLVM bug
#23649
, also add USE_LLVM_SHLIB=0

Now execute make install-llvm from the deps subfolder. When it
finishes, check if binaries have been written to usr/bin (due to what’s probably a bug in
LLVM’s build scripts), and move them to usr/tools if they have.

Sanitized Julia

Now that we have a working toolchain, we’ll use it to compile a sanitized version of the
Julia compiler and libraries. Start by creating a new out-of-tree build directory using
make O=configure sanitize. But this time, our Make.user will be significantly more
complex:

TOOLCHAIN=$(BUILDROOT)/sanitize_toolchain/usr/tools

# use our new toolchain
USECLANG=1
override CC=$(TOOLCHAIN)/clang
override CXX=$(TOOLCHAIN)/clang++
export ASAN_SYMBOLIZER_PATH=$(TOOLCHAIN)/llvm-symbolizer

# enable ASAN
override SANITIZE=1
override LLVM_SANITIZE=1

# autotools doesn't have a self-sanitize mode
override LLVM_USE_CMAKE=1

# make the GC use regular malloc/frees, which are intercepted by ASAN
override WITH_GC_DEBUG_ENV=1

# default to a debug build for better line number reporting
override JULIA_BUILD_MODE=debug

Now kick-off the build using make from the sanitize build directory. Barring any memory
issues triggered during system image generation, this should yield a sanitized julia
binary and system image.

Running the test-suite

The test-suite is a beast, and because ASAN keeps track of a lot of information it easily
takes over 128GiB of memory to run it to completion. Instead, we’ll tune ASAN to consume
less memory at the expense of accuracy and report detail.

Julia however already configures default ASAN
options
,
which we need to copy when specifying a different set. Do so by defining the
ASAN_OPTIONS environment variable and assigning it the value of
detect_leaks=0:allow_user_segv_handler=1:fast_unwind_on_malloc=0:malloc_context_size=2.
This copies aforementioned default values, and caps backtrace collection.

Using CUDA packages

If you thought all that was convoluted, prepare for some more. ASAN uses so-called shadow memory to store
information about memory allocations. There is a correspondence between regular memory
addresses and their shadow counterpart, and this mapping is
fixed

in order to keep the instrumentation overhead
low
. Sadly, the default shadow memory
location overlaps with fixed memory allocated by CUDA (presumably for its unified virtual
address
space
).

Because the shadow memory is fixed, we need to patch both instances of LLVM (easiest to add
a patch to llvm.mk) and have it pick a different shadow offset:

--- lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -359,7 +359,7 @@
       if (IsKasan)
         Mapping.Offset = kLinuxKasan_ShadowOffset64;
       else
-        Mapping.Offset = kSmallX86_64ShadowOffset;
+        Mapping.Offset = kDefaultShadowOffset64;
     } else if (IsMIPS64)
       Mapping.Offset = kMIPS64_ShadowOffset64;
     else if (IsAArch64)
--- projects/compiler-rt/lib/asan/asan_mapping.h
+++ projects/compiler-rt/lib/asan/asan_mapping.h
@@ -146,7 +146,7 @@
 #  elif SANITIZER_IOS
 #    define SHADOW_OFFSET kIosShadowOffset64
 #  else
-#   define SHADOW_OFFSET kDefaultShort64bitShadowOffset
+#   define SHADOW_OFFSET kDefaultShadowOffset64
 #  endif
 # endif
 #endif

Note that you might need to redefine a different macro for your platform.

Sanitizing older versions of Julia

If you want to sanitize older versions of Julia, before the switch to LLVM
3.9
, there’s yet other issues: only LLVM
3.9 is compatible with recent versions of
glibc, while the CMake build system of LLVM 3.7 doesn’t
export
all necessary public symbols. You can
work around these issues by using a sufficiently old system, and overriding the LLVM version
to 3.8 (by specifying override LLVM_VER=3.8.1 in the Make.user of both build
directories) or preventing it from generating a shared library (by specifying
USE_LLVM_SHLIB=0 in the Make.user of the final Julia build).

DynProg Class – Week 2

By: pkofod

Re-posted from: http://www.pkofod.com/2017/02/18/dynprog-class-week-2/

This post, and other posts with similar tags and headers, are mainly directed at the students who are following the Dynamic Programming course at Dept. of Economics, University of Copenhagen in the Spring 2017. The course is taught using Matlab, but I will provide a few pointers as to how you can use Julia to solve the same problems. So if you are an outsider reading this I welcome you, but you won’t find all the explanations and theory here. If you want that, you’ll have to come visit us at UCPH and enroll in the class!

This week we continue with a continuous choice model. This means we have to use interpolation and numerical optimization.

A (slightly less) simple model

Consider a simple continuous choice consumption-savings model:

\(V_t(M_t) = \max_{C_t}\sqrt{C_t}+\mathbb{E}[V_{t+1}(M_{t+1})|C_t, M_t]\)
subject to
\(M_{t+1} = M_t – C_t+R_t\\
C_t\leq M_t\\
C_t\in\mathbb{R}_+\)

where \(R_t\) is 1 with probability \(\pi\) and 0 with probability \(1-\pi\), \(\beta=0.9\), and \(\bar{M}=5\)

Last week the maximization step was merely comparing values associated with the different discrete choices. This time we have to do continuous optimization in each time period. Since the problem is now continuous, we cannot solve for all \(M_t\). Instead, we need to solve for \(V_t\) at specific values of \(M_t\), and interpolate in between. Another difference to last time is the fact that the transitions are stochastic, so we need to form (very simple) expectations as part of the Bellman equation evaluations.

Interpolation

It is of course always possible to make your own simple interpolation scheme, but we will use the functionality provided by the Interpolations.jl package. To perform interpolation, we need a grid to be used for interpolation \(\bar{x}\), and calculate the associated function values.

f(x) = (x-3)^2
x̄ = linspace(1,5,5)
fx̄ = f.()

Like last time, we remember that the dot after the function name and before the parentheses represent a “vectorized” call, or a broadcast – that is we call f on each element of the input. We now use the Interpolations.jl package to create an interpolant \(\hat{f}\).

using Interpolations
f̂ = interpolate((collect(),), fx̄, Gridded(Linear()))

We can now index into \(\hat{f}\) as if it was an array

[-3] #returns 16.0

We can also plot it

using Plots
plot()

which will output

Solving the model

Like last time, we prepare some functions, variables, and empty containers (Arrays)

# Model again
u(c) = sqrt(c)
T = 10; β = 0.9
π = 0.5 ;M₁ = 5
# Number of interpolation nodes
Nᵐ = 50 # number of grid points in M grid
Nᶜ  = 50 # number of grid points in C grid
 
M = Array{Vector{Float64}}(T)
V = Array{Any}(T)
C = Array{Any}(T)

The V and C arrays are allocated using the type “Any”. We will later look at how this can hurt performance, but for now we will simply do the convenient thing. Then we solve the last period

M[T] = linspace(0,M₁+T,Nᵐ)
C[T] = M[T]
V[T] = interpolate((M[T],), u.(C[T]), Gridded(Linear()))

This new thing here is that we are not just saving V[T] as an Array. The last element is the interpolant, such that we can simply index into V[T] as if we had the exact solution at all values of M (although we have to remember that it is an approximation). For all periods prior to T, we have to find the maximum as in the Bellman equation from above. To solve this reduced “two-period” problem (sum of utility today and discounted value tomorrow), we need to form expectations over the two possible state transitions given an M and a C today, and then we need to find the value of C that maximizes current value. We define the following function to handle this

# Create function that returns the value given a choice, state, and period
v(c, m, t, V) = u(c)*(π*V[t+1][m-c+1]+(1)*V[t+1][m-c])

Notice how convenient it is to simply index into V[t] using the values we want to evaluate tomorrow’s value function at. We perform the maximization using grid search on a predefined grid from 0 to the particular M we’re solving form. If we abstract away from the interpolation step, this is exactly what we did last time.

for t = T-1:-1:1
    M[t] = linspace(0,M₁+t,Nᵐ)
    C[t] = zeros(M[t])
    Vt = fill(-Inf, length(M[t]))
    for (iₘ, m) = enumerate(M[t])
        for c in linspace(0, m, Nᶜ)
            _v = v(c, m, t, V)
            if _v >= Vt[iₘ]
                Vt[iₘ] = _v
                C[t][iₘ] = c
            end
        end
    end
    V[t] = interpolate((M[t],), Vt, Gridded(Linear()))
end

Then we can plot the value functions to verify that they look sensible

Nicely increasing in time and in M.

Using Optim.jl for optimization

The last loop could just as well have been done using a proper optimization routine. This will in general be much more robust, as we don’t confine ourselves to a certain amount of C-values. We use the one of the procedures in Optim.jl. In Optim.jl, constrained, univariate optimization is available as either Brent’s method or Golden section search. We will use Brent’s method. This is the standard method, so an optimization call simply has the following syntax

using Optim
f(x) = x^2
optimize(f, -1.0, 2.0)

Unsurprisingly, this will return the global minimizer 0.0. However, if we constrain ourselves to a strictly positive interval

optimize(f, 1.0, 2.0)

we get a minimizer of 1.0. This is not the unconstrained minimizer of the square function, but it is minimizer given the constraints. Then, it should be straight forward to see how the grid search loop can be converted to a loop using optimization instead.

for t = T-1:-1:1
    update_M!(M, M₁, t, Nᵐ)
    C[t] = zeros(M[t])
    Vt = fill(-Inf, length(M[t]))
    for (iₘ, m) = enumerate(M[t])
        if m == 0.0
            C[t][iₘ] = m
            Vt[iₘ] = v(m, m, t, V)
        else
            res = optimize(c->-v(c, m, t, V), 0.0, m)
            Vt[iₘ] = -Optim.minimum(res)
            C[t][iₘ] = Optim.minimizer(res)
        end
    end
    V[t] = interpolate((M[t],), Vt, Gridded(Linear()))
end

If our agent has no resources at the beginning of the period, the choice set has only one element, so we skip the optimization step. We also have to negate the minimum to get the maximum we’re looking for. The main advantage of using a proper optimization routine is that we’re not restricting C to be in any predefined grid. This increases precision. If we look at the number of calls to “v” (using Optim.f_calls(res)), we see that it generally takes around 10-30 v calls. With only 10-30 grid points from 0 up to M, we would generally get an approximate solution of much worse quality.

Julia bits and pieces

This time we used a few different package from the Julia ecosystem: Plots.jl, Interpolations.jl, and Optim.jl. These are based on my personal choices (full disclosure: I’ve contributed to the former and the latter), but there are lots of packages to explore. Visit the JuliaLang discourse forum or gitter channel to discuss Julia and the various packages with other users.