When building my university project on two different machines I experienced issues with LAPACK and Intel’s implementation in MKL. I already figured out the main problem: I used the LAPACK headers from liblapacke-devel
which where differing between both machines. In one of the headers, each LAPACK function had two additional size_t
arguments at the end of the argument list, having sth. to do with the Fortran origin of LAPACK. Realizing that, and since I was linking against MKL anyways, I just decided to use the MKL headers instead which don’t differ in the argument lists.
However I was curious and tried to call one of the LAPACK functions (dsyev
) with the additional arguments but still link against MKL, which does not have these additional arguments. I expected a segfault or similar, but my test program worked just fine. What could be the reason?
My theory is that since the arguments are at the end of the argument list, they are just not accessed and cleaned up when returning to the calling function. If true, would this mean doing such a thing is just fine or are there possible other implications that could lead to runtime issues? How could I inspect the possibly misaligned stack before the call to dsyev
?
I tried objdump
and nm
only to realize that information about argument lists are never part of shared libraries, only the symbol names. Due to my lack of experience using GDB
I also couldn’t extract any meaningful information from there. How could I find out if my theory why this still works is correct?
Here are the relevant excerpts of lapack.h
and mkl_lapack.h
referring to dsyev_
, from both installations:
Container, lapack.h
from liblapacke-dev
, version 3.10.0-2ubuntu1
:
...
/* It seems all current Fortran compilers put strlen at end.
* Some historical compilers put strlen after the str argument
* or make the str argument into a struct. */
#define LAPACK_FORTRAN_STRLEN_END
...
#define LAPACK_dsyev_base LAPACK_GLOBAL(dsyev,DSYEV)
void LAPACK_dsyev_base(
char const* jobz, char const* uplo,
lapack_int const* n,
double* A, lapack_int const* lda,
double* W,
double* work, lapack_int const* lwork,
lapack_int* info
#ifdef LAPACK_FORTRAN_STRLEN_END
, size_t, size_t
#endif
);
#ifdef LAPACK_FORTRAN_STRLEN_END
#define LAPACK_dsyev(...) LAPACK_dsyev_base(__VA_ARGS__, 1, 1)
#else
#define LAPACK_dsyev(...) LAPACK_dsyev_base(__VA_ARGS__)
#endif
This results in dsyev
having two additional size_t
arguments which are then again taken care of by the LAPACK_dsyev
define.
Host, lapack.h
from liblapacke-dev
, version 3.9.0-1build1
:
#define LAPACK_dsyev LAPACK_GLOBAL(dsyev,DSYEV)
void LAPACK_dsyev(
char const* jobz, char const* uplo,
lapack_int const* n,
double* A, lapack_int const* lda,
double* W,
double* work, lapack_int const* lwork,
lapack_int* info );
Container, mkl_lapack.h
from Intel OneMKL
, version 2024.2
:
void DSYEV( const char* jobz, const char* uplo, const MKL_INT* n, double* a,
const MKL_INT* lda, double* w, double* work, const MKL_INT* lwork,
MKL_INT* info ) NOTHROW;
void dsyev( const char* jobz, const char* uplo, const MKL_INT* n, double* a,
const MKL_INT* lda, double* w, double* work, const MKL_INT* lwork,
MKL_INT* info ) NOTHROW;
void dsyev_( const char* jobz, const char* uplo, const MKL_INT* n, double* a,
const MKL_INT* lda, double* w, double* work, const MKL_INT* lwork,
MKL_INT* info ) NOTHROW;
(Capslock C-style, C-style, Fortran style)
Host, mkl_lapack.h
from Intel OneMKL
, version 2021.1.1
:
void DSYEV( const char* jobz, const char* uplo, const MKL_INT* n, double* a,
const MKL_INT* lda, double* w, double* work, const MKL_INT* lwork,
MKL_INT* info ) NOTHROW;
void DSYEV_( const char* jobz, const char* uplo, const MKL_INT* n, double* a,
const MKL_INT* lda, double* w, double* work, const MKL_INT* lwork,
MKL_INT* info ) NOTHROW;
void dsyev( const char* jobz, const char* uplo, const MKL_INT* n, double* a,
const MKL_INT* lda, double* w, double* work, const MKL_INT* lwork,
MKL_INT* info ) NOTHROW;
void dsyev_( const char* jobz, const char* uplo, const MKL_INT* n, double* a,
const MKL_INT* lda, double* w, double* work, const MKL_INT* lwork,
MKL_INT* info ) NOTHROW;
(Capslock C-style, capslock Fortran style, C-style, Fortran style)
Moritz Sigg is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.