将C ++与BLAS和LAPACK链接起来

时间:2013-08-12 23:26:03

标签: c++ fortran lapack blas

要从c ++调用Fortran例程,我一直在使用: extern“C”void routinename _(...) 使用附加的下划线使其与Fortran子例程名称“ROUTINENAME”兼容。

当我将c ++与BLAS或LAPACK链接时,它只能在没有下划线的情况下工作。将c ++与这些用Fortran编写的库链接起来有什么区别,这使得下划线不必要?

2 个答案:

答案 0 :(得分:0)

我可能错了,因为没有什么信息可以继续,但是......

here:第一个F77编译器将_附加到ABI中的函数名称。此行为与C不同,后者只接受函数名称并将其用作ABI中的名称。

某些F77编译器的行为方式不同,而是覆盖了整个子例程名称,因此当C看到foo()变为FOO()时,UNIX Fortran编译器会模仿C行为并且只是复制意大利面。名称,以便{AB}中的foo()foo()

如果你看一下参考实现here的BLAS绑定到C,你会看到他们在处理F77时处理尾随下划线。我打赌下注是F77 ABI的一个更常见的特征,而不是没有它们。

后来,Fortran 2003引入了与C的互操作性(参见here)。当使用某些Fortran结构时,这使得函数命名方案相同(参见here)。

因此,我会猜测这与Fortran版本中的ABI差异有关。或者甚至只是编译器,因为不同的编译器似乎在Fortran中有不同的行为。

所以,再次,我不确定这是否与你的情况相符,因为你的问题没有太多可以继续,但是我不能将这一切都纳入评论中所以这里是一个'回答'。

如果我错了告诉我,我可以纠正MAH'POST。

tl; dr:因为编译器版本

答案 1 :(得分:-1)

我将给出链接 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 中使用以下内容。

  1. www.openblas.net,获取 tar.gz 将其复制到您的目录中
  2. 解压:tar -zxvf OpenBLAS-0.2.20.tar.gz
  3. 编译: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++ 中的 Name mangling 在 C 中存在问题。由于 C 不支持重载,所以我们必须使用 extern "c"{}。