在两台不同的机器上构建我的大学项目时,我遇到了LAPACK和英特尔在MKL中的实现问题。我已经找出了主要问题:我使用了来自
liblapacke-devel
这两台机器之间存在差异。在其中一个标头中,每个LAPACK函数都有两个额外的
size_t
参数列表末尾的参数,与LAPACK的Fortran起源有关。意识到这一点,而且由于我无论如何都是在链接MKL,我决定使用MKL头文件,这些头文件在参数列表中没有区别。
然而,我很好奇,试图调用其中一个LAPACK函数(
dsyev
)虽然有额外的参数,但仍然链接到MKL,而MKL并没有这些额外的参数。我原本以为会出现segfault或类似的错误,但我的测试程序运行得很好。原因是什么?
我的理论是,由于参数位于参数列表的末尾,因此在返回调用函数时,它们不会被访问和清理。如果是真的,这是否意味着做这样的事情很好,或者是否有可能导致运行时问题的其他影响?在调用之前,我如何检查可能未对齐的堆栈
dsyev
?
我试过了
objdump
和
nm
只是意识到关于参数列表的信息从来不是共享库的一部分,只有符号名称。由于我缺乏使用经验
GDB
我也无法从中提取任何有意义的信息。我怎样才能知道我的理论为什么仍然有效?
以下是相关摘录
lapack.h
和
mkl_lapack.h
提及
dsyev_
,从两个装置:
集装箱,
背包。h
从
liblapacke-dev
,版本
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
这导致
dsyev
有两个额外的
size_t
然后由
LAPACK_dsyev
定义。
主机,
背包。h
从
liblapacke开发
,版本
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 );
集装箱,
mkl_lapack。h
从
Intel OneMKL
,版本
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风格、C风格、Fortran风格)
主机,
mkl_lapack。h
从
英特尔OneMKL
,版本
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风格,Capslock Fortran风格,C风格,Fortran风格)