Using external LAPACK versions in mex

9 views (last 30 days)
Arwel
Arwel on 13 Mar 2018
Hi,
I have an external shared library which I would like to call from a (coder generated) mex.
Looking at the CmakeCache.txt for the external library, I can see the following...
//Path to a library.
LAPACK_lapack_LIBRARY:FILEPATH=/usr/lib64/liblapack.so
and also..
//Path to a library.
BLAS_blas_LIBRARY:FILEPATH=/usr/lib64/libblas.so
CMake creates a library called libmultinest.so, and I can compile and run a test problem with no problem from Eclipse. I'm trying to run the exact same test problem from Matlab.
The C test problem looks like this....
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <float.h>
#include "multinest.h"
void LogLike(double *Cube, int *ndim, int *npars, double *lnew, void *context)
{
double chi = 1.0;
int i;
for(i = 0; i < *ndim; i++)
{
double x = Cube[i]*10.0*M_PI;
chi *= cos(x/2.0);
Cube[i] = x;
}
*lnew = powf(chi + 2.0, 5.0);
}
/***********************************************************************************************************************/
/************************************************* dumper routine ******************************************************/
void dumper(int *nSamples, int *nlive, int *nPar, double **physLive, double **posterior, double **paramConstr, double *maxLogLike, double *logZ, double *INSlogZ, double *logZerr, void *context)
{
// convert the 2D Fortran arrays to C arrays
// the posterior distribution
// postdist will have nPar parameters in the first nPar columns & loglike value & the posterior probability in the last two columns
int i, j;
double postdist[*nSamples][*nPar + 2];
for( i = 0; i < *nPar + 2; i++ )
for( j = 0; j < *nSamples; j++ )
postdist[j][i] = posterior[0][i * (*nSamples) + j];
// last set of live points
// pLivePts will have nPar parameters in the first nPar columns & loglike value in the last column
double pLivePts[*nlive][*nPar + 1];
for( i = 0; i < *nPar + 1; i++ )
for( j = 0; j < *nlive; j++ )
pLivePts[j][i] = physLive[0][i * (*nlive) + j];
}
/***********************************************************************************************************************/
/************************************************** Main program *******************************************************/
int main(int argc, char *argv[])
{
int i;
// set the MultiNest sampling parameters
int IS = 1; // do Nested Importance Sampling?
int mmodal = 0; // do mode separation?
int ceff = 0; // run in constant efficiency mode?
int nlive = 1000; // number of live points
double efr = 1.0; // set the required efficiency
double tol = 0.1; // tol, defines the stopping criteria
int ndims = 2; // dimensionality (no. of free parameters)
int nPar = 2; // total no. of parameters including free & derived parameters
int nClsPar = 2; // no. of parameters to do mode separation on
int updInt = 1000; // after how many iterations feedback is required & the output files should be updated
// note: posterior files are updated & dumper routine is called after every updInt*10 iterations
double Ztol = -1E90; // all the modes with logZ < Ztol are ignored
int maxModes = 100; // expected max no. of modes (used only for memory allocation)
int pWrap[ndims]; // which parameters to have periodic boundary conditions?
for(i = 0; i < ndims; i++) pWrap[i] = 0;
char root[130] = "/home/arwel/Documents/coding/multinestEdits/eggboxOnly/MultiNest_v3.10_eggboxOnly/multinest_eggboxOnly/bin/chains-";
int seed = -1; // random no. generator seed, if < 0 then take the seed from system clock
int fb = 1; // need feedback on standard output?
int resume = 0; // resume from a previous job?
int outfile = 0; // write output files?
int initMPI = 1; // initialize MPI routines?, relevant only if compiling with MPI
// set it to F if you want your main program to handle MPI initialization
double logZero = -DBL_MAX; // points with loglike < logZero will be ignored by MultiNest
int maxiter = 0; // max no. of iterations, a non-positive value means infinity. MultiNest will terminate if either it
// has done max no. of iterations or convergence criterion (defined through tol) has been satisfied
void *context = 0; // not required by MultiNest, any additional information user wants to pass
// calling MultiNest
run(IS, mmodal, ceff, nlive, tol, efr, ndims, nPar, nClsPar, maxModes, updInt, Ztol, root, seed, pWrap, fb, resume, outfile, initMPI,
logZero, maxiter, LogLike, dumper, context);
return(0);
}
/*****
..with 'multinest.h' as....
#define NESTRUN __nested_MOD_nestrun
/***************************************** C Interface to MultiNest **************************************************/
extern void NESTRUN(int *, int *, int *, int *, double *, double *, int *, int *, int *, int *, int *, double *,
char *, int *, int *, int *, int *, int *, int *, double *, int *, void (*Loglike)(double *, int *, int *,
double *, void *), void (*dumper)(int *, int *, int *, double **, double **, double **, double *,
double *, double *, double *, void *), void *context);
void run(int IS, int mmodal, int ceff, int nlive, double tol, double efr, int ndims, int nPar, int nClsPar,
int maxModes, int updInt, double Ztol, char root[], int seed, int *pWrap, int fb, int resume, int outfile,
int initMPI, double logZero, int maxiter, void (*LogLike)(double *, int *, int *, double *, void *),
void (*dumper)(int *, int *, int *, double **, double **, double **, double *, double *, double *, double *, void *),
void *context)
{
int i;
for (i = strlen(root); i < 100; i++) root[i] = ' ';
NESTRUN(&IS, &mmodal, &ceff, &nlive, &tol, &efr, &ndims, &nPar, &nClsPar, &maxModes, &updInt, &Ztol,
root, &seed, pWrap, &fb, &resume, &outfile, &initMPI, &logZero, &maxiter, LogLike, dumper, context);
}
To try to run the test problem from Matlab, the above is split into three files - LogLike.c, dumper.c and mainRoutine.c, essentially unchanged, then in Matlab I have...
function res = multinestCaller()
path = '//home/arwel/Documents/RascalDev/RAT/Sandbox/multinestTests';
coder.updateBuildInfo('addSourcePaths',path);
coder.cinclude('mainRoutine.c');
coder.cinclude('LogLike.c');
coder.cinclude('dumper.c');
libPriority = '';
libPreCompiled = true;
libLinkOnly = true;
linkPath = '/usr/local/lib';
pw = '/usr/lib64';
coder.updateBuildInfo('addLinkObjects','liblapack.so.3.4.2',pw,libPriority,libPreCompiled,libLinkOnly);
coder.updateBuildInfo('addLinkObjects','libblas.so.3.4.2',pw,libPriority,libPreCompiled,libLinkOnly);
coder.updateBuildInfo('addLinkObjects','libmultinest.so.3.10',linkPath,libPriority,libPreCompiled,libLinkOnly);
coder.ceval('mainRoutine',0,[]);
res = [];
end
To build this in Matlab, I then just go...
codegen multinestCaller -o multinestCaller_mex
..but when I try to run it, everything hangs with the message (in the terminal)..
Intel MKL ERROR: Parameter 18 was incorrect on entry to DSYEVR.
So, I'm taking this to mean the problem is caused by the different BLAS and Lapack libraries in the Library to those used in Matlab (i.e. openBLAS in the library, MKL in Matlab...).
So I tried to fix this like so....
>> setenv('BLAS_VERSION','/usr/lib64/libblas.so');
>> setenv('LAPACK_VERSION','/usr/lib64/liblapack.so');
>> codegen multinestCaller -o multinestCaller_mex
>> multinestCaller_mex()
Error using multinestCaller_mex
LAPACK loading error:
/lib64/liblapack.so.3: undefined symbol: checon_rook_
>>
So now it looks like its using the correct versions of BLAS and LAPACK, but I'm still missing something. What have I missed here??
Cheers,
Arwel
(This.Is.Driving.Me.Nuts!)

Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!