xxxxx_()、LAPACK_xxxxx() 和 LAPACKE_xxxxx() 函数之间的区别

Difference between xxxxx_(), LAPACK_xxxxx() and LAPACKE_xxxxx() functions

假设我想使用 LAPACK 求解 C (GCC) 中的线性方程组。 我设置问题如下:

/* Want to solve Ax=b */
int n = ...;      // size
double *A = ...;  // nxn matrix
double *b = ...;  // length-n vector
int m = 1;        // number of columns in b (needs to be in a variable)
double *pivot;    // records pivoting
int info;         // return value

现在看来我可以使用三个函数中的一个来解决这个问题。 第一个是这样的:

dgesv_( &n, &m, A, &n, pivot, b, &n, &info );

我很惊讶地发现这不需要任何 #includes,这看起来......很奇怪。

第二个函数具有几乎相同的签名,除了前缀 LAPACK_,我认为它会导致歧义较少并且可能更不容易出错:

#include <lapack/lapacke.h>
LAPACK_dgesv( &n, &m, A, &n, pivot, b, &n, &info );

请注意,这需要我包含 lapacke.h

第三个函数通过返回 info 而不是将所有参数都作为指针来稍微更改签名:

#include <lapack/lapacke.h>
info = LAPACKE_dgesv( LAPACK_COL_MAJOR, n, m, A, n, pivot, b, n);

同样,此函数需要 lapacke.h。它还需要使用 -llapacke 链接到一个额外的库。 这三个函数都需要 -llapack.

我正在尝试找出这些函数之间的区别。 我四处窥探了一下,在 lapacke.h 和相关的头文件中发现了以下宏:

#define LAPACK_GLOBAL(name,NAME) name##_
#define LAPACK_dgesv LAPACK_GLOBAL(dgesv,DGESV)

所以 LAPACK_dgesv()dgesv_() 似乎是完全相同功能的不同名称。 但是,LAPACKE_dgesv() 似乎是另外一种可能具有不同实现方式的东西,特别是考虑到它需要一个额外的库这一事实。

所以我的问题是:这两个函数有什么区别? 文档说LAPACKE是LAPACK的C接口,但是函数dgesv_()呢? 很明显,我可以正常使用它而不需要 LAPACKE,也不需要在 Fortran 中编译任何东西,那有什么不同呢?

谢谢。


更新

奇怪的是,函数 dgemm_()(矩阵乘法)没有任何等价的 LAPACK_dgemm()。 怎么回事?

  • 注意 LAPACKE_dgesv() 有一个额外的标志,它可以是 LAPACK_COL_MAJOR(通常的 fortran 顺序)或 LAPACK_ROW_MAJOR(通常的 c 顺序)。在 LAPACK_COL_MAJOR 的情况下,它只是直接调用 LAPACK_dgesv()。在 LAPACK_ROW_MAJOR 的情况下,LAPACKE_dgesv() 将在调用 LAPACK_dgesv() 之前转置矩阵。它不是 dgesv_() 的新实现。看看 lapack-3.5.0/lapacke/src/dgesv_work.c 在这个文件中,有一些关于错误处理的小的额外变化。

  • LAPACK_dgesv() 在 header lapacke.h 中定义为 LAPACK_GLOBAL(dgesv,DGESV)。宏 LAPACK_GLOBAL 在 lapacke_mangling.h 中定义:它只是包装 dgesv_ 并在使用其他约定时关心命名约定。

所以,基本上,函数LAPACK_dgesv()只需要lapacke的headers。与dgesv_相比,可以避免一些与库中的命名约定相关的问题。但是 LAPACK_dgesv()dgesv_() 完全一样。函数 LAPACKE_dgesv() 扩大了 LAPACK_dgesv() 的范围来处理通常的 c matrix.But 它最后仍然调用 dgesv_.

函数dgemm() is part of the BLAS library. A wrapped c version cblas_dgemm() can be found in CBLAS。同样,需要一个附加标志 CBLAS_ORDER,可能的值为 CblasRowMajorCblasColMajor.