Search code examples
matlabsegmentation-faultlapackblasarmadillo

Armadillo + Matlab Mex segfault


I fiddled with this the whole day, so I thought I might make everyone benefit from my experience, please see my answer below.

I first had a problem with running a compiled Mex file within Matlab, because Matlab complained that it couldn't open the shared library libarmadillo. I solved this using the environment variables LD_LIBRARY_PATH and LD_RUN_PATH (DYLD_LIBRARY_PATH and LYLD_RUN_PATH in osx).

The problem remained however, that a simple test file would segfault at runtime even though the exact same code would compile and run fine outside Matlab (not Mex'd).


Solution

  • The segfault seems to be caused by the fact that Matlab uses 64bits integers (long long or int64_t) in its bundled LAPACK and BLAS libraries. Armadillo on the other hand, uses 32bits integers (regular int on a 64bits platform, or int32_t) by default.

    There are two solutions; the first one involves forcing Matlab to link to the system's libraries instead (which use ints), the second involves changing Armadillo's config file to enable long longs with BLAS. I tend to think that the first is more reliable, because there is no black-box effect, but it's also more troublesome, because you need to manually install and remember the path of your BLAS and LAPACK libs.

    Both solutions required that I stopped using Armadillo's shared libraries and linked/included manually the sources. To do this, you must simply install LAPACK and BLAS on your system (if they are not already there, in Ubuntu that's libblas-dev and liblapack-dev), and copy the entire includes directory somewhere sensible like in $HOME/.local/arma for example.


    Solution 1: linking to system's libraries

    From the matlab console, set the environment variables BLAS_VERSION and LAPACK_VERSION to point to your system's libraries. In my case (Ubuntu 14.04, Matlab R2014b):

    setenv('BLAS_VERSION','/usr/lib/libblas.so');
    setenv('LAPACK_VERSION','/usr/lib/liblapack.so');
    

    You can then compile normally:

    mex -compatibleArrayDims -outdir +mx -L/home/john/.local/arma -llapack -lblas -I/home/john/.local/arma test_arma.cpp
    

    or if you define the flag ARMA_64BIT_WORD in includes/armadillo_bits/config.hpp, you can drop the option -compatibleArrayDims.


    Solution 2: changing Armadillo's config

    The second solution involves uncommenting the flag ARMA_BLAS_LONG_LONG in Armadillo's config file includes/armadillo_bits/config.hpp. Matlab will link to its bundled LAPACK and BLAS libraries, but this time Armadillo won't segfault because it's using the right word-size. Same than before, you can also uncomment ARMA_64BIT_WORD if you want to drop the -compatibleArrayDims.