将 C++ 与 BLAS 和 LAPACK 连接起来
Posted
技术标签:
【中文标题】将 C++ 与 BLAS 和 LAPACK 连接起来【英文标题】:Linking C++ with BLAS and LAPACK 【发布时间】:2013-08-12 23:26:03 【问题描述】:要从我一直使用的 c++ 调用 Fortran 例程: extern "C" void 例程名称_(...) 附加下划线使其与 Fortran 子例程名称“ROUTINENAME”兼容。
当我将 c++ 与 BLAS 或 LAPACK 链接时,它只能在没有下划线的情况下工作。将 c++ 与这些用 Fortran 编写的库链接起来有什么区别,这使得下划线变得不必要?
【问题讨论】:
你听说过LAPACKE
(Lapack 的 C 接口)吗? BLAS 还有一个 C 接口。
【参考方案1】:
我可能是错的,因为要了解的信息很少,但是...
来自here:第一个 F77 编译器在 ABI 中的函数名称后附加了一个 _
。这种行为与 C 不同,C 只接受函数名称并将其用作 ABI 中的名称。
一些 F77 编译器的行为不同,而是将整个子例程名称大写,因此当 C 看到时,foo()
变为 FOO()
。UNIX Fortran 编译器模仿 C 的行为,只是复制粘贴名称以便 @ 987654328@ 在 ABI 中也是 foo()
。
如果您查看参考实现here 的 BLAS 与 C 的绑定,您会发现它们在处理 F77 时正在处理尾随下划线。我敢打赌,在过去,下划线是 F77 ABI 的一个更常见的特征,而不是没有它们。
后来,Fortran 2003 引入了与 C 的互操作性(请参阅here)。当使用某些 Fortran 结构时,这使得函数命名方案相同(请参阅here)。
因此,我将大胆猜测这与 Fortran 版本之间的 ABI 差异有关。甚至只是跨编译器,因为不同的编译器在 Fortran 中似乎有不同的行为。
因此,我不确定这是否与您的情况相匹配,因为您的问题没有太多要讨论的内容,但我无法将这一切都放入评论中,所以这里是'回答'。
如果我错了,请告诉我,以便我更正 MAH 的帖子。
tl;dr:因为编译器版本
【讨论】:
【参考方案2】:我正在为链接 BLAS 提供一个通用答案,不仅是这个问题,这个问题的答案在下面。
首先,您需要确保使用 (+lapack) 安装了 BLAS
$ sudo apt-get install libblas-dev liblapack-dev
然后您可以在您的程序文件之后使用 -lblas 进行链接。或者你可以使用 make 文件。
例如: g++ test.o dmatrix_denseCM.o mmio.o -o 输出 -lblas
就我而言,我更喜欢使用 OpenBlas,您可以在 makefile 中使用以下内容。
-
www.openblas.net,获取 tar.gz
将其复制到您的目录中
解压:tar -zxvf OpenBLAS-0.2.20.tar.gz
编译它:cd OpenBLAS-0.2.20
制作
完成后,您应该拥有文件 libopenblas.a,即 openblas 库
BLASLIB = OpenBLAS/libopenblas.a -lpthread 然后将其添加到链接在一起的文件中:$(BLASLIB)这个目录OpenBLAS/libopenblas.a应该在同一个工作目录中。
.cc 文件中的示例代码:
extern "C"
void dgemm_( const char &TRANSA, const char &TRANSB, const int &M, const int &N, const int & K, const double & ALPHA, const double *A, const int & LDA, const double *B, const int &LDB, const double &BETA, double *C, const int & LDC);
此外,当从 C 调用 LAPACK 或 BLAS 例程时,请注意,由于 Fortran 语言不区分大小写,因此例程名称可以是大写或小写,带有或不带有尾随下划线。例如,以下名称是等价的:
LAPACK:dgetrf、DGETRF、dgetrf_ 和 DGETRF_
BLAS:dgemm、DGEMM、dgemm_ 和 DGEMM_Intel® Math Kernel Library 11.3 Update 4 Developer Guide
您可以添加有关您用于编译 BLAS 的 FORTRAN 编译器的更多信息,例如:
使用 -U 选项编译 Fortran 程序,该选项告诉编译器保留函数/子程序名称的现有大写/小写区别。
Fortran 编译器通常会在出现在入口点定义和调用中的子程序名称后附加下划线 (_)。此约定不同于具有相同用户分配名称的 C 过程或外部变量。 here
C++ 中的名称修饰在 C 中造成问题。因为 C 不支持重载,所以我们必须使用 extern "c"。
【讨论】:
以上是关于将 C++ 与 BLAS 和 LAPACK 连接起来的主要内容,如果未能解决你的问题,请参考以下文章
Armadillo C++ 和 BLAS 和 ATLAS 在 mingw32 下找不到 lapack blas
将 armadillo/blas/lapack 与 cmake 链接(未定义对 `dgemv_' 的引用)
求救,在Win7下怎么安装Amardillo还有LAPACK和BLAS