使用GotoBLAS2和C.

时间:2011-09-01 05:12:57

标签: c linker blas

我是C编码的新手,但我编写了一个用于模拟神经网络的Matlab程序,我希望将其转换为C代码,因为我们的超级计算机集群不允许运行多个Matlab仿真。一旦。为此,我发现GotoBLAS可以处理矩阵数学。

不幸的是我不确定如何使用它,因为我在C和使用外部库方面没有很多经验。我假设'dgemm'是GotoBLAS中的一个函数,从阅读BLAS指南pdf。我已经能够成功编译GotoBLAS,但是当我这样做时:

gcc -o outputprog main.c -Wall -L -lgoto2.a

我收到了消息:

undefined reference to 'dgemm'

据我了解,我应该在GotoBLAS中加入一些.h文件(或者不是),但我不确定哪一个(或者这是否正确)。

任何有关此的帮助将不胜感激。如果需要更多信息,请告诉我。

2 个答案:

答案 0 :(得分:6)

一个问题可能是-L选项需要后面的'directory'名称,因此gcc(或由gcc调用的链接器)正在处理-lgoto2.a作为目录。编译器不会抱怨不存在的目录;它只是忽略了它们。您希望在哪个目录中找到该库? (为了这个答案的目的,我假设它在/usr/local/lib。)

另一个问题可能是该库未被称为libgoto2.a.a或libgoto2.a.so或类似的东西。您通常不会指定.a后缀。 (出于本答案的目的,我假设该库是libgoto2.a或libgoto2.so。)

您似乎无需指定标题的位置;这意味着它们处于一个足够传统的位置,编译器无论如何都会看到它。如果这是正确的,那么库也可能处于足够传统的位置,并且-L选项可能是不必要的。

所以,您可以使用:

gcc -Wall -o outputprog main.c -lgoto2

或者您可能需要使用:

gcc -Wall -o outputprog main.c -L/usr/local/lib -lgoto2

在评论中进行了一些广泛讨论之后,以及该库在当前目录中的名称为libgoto2.a并且符号dgemm仍然缺失的信息,我下载了GotoBLAS2 version 1.13和试图在半支持的平台上编译它(MacOS X,可能假装是Linux,使用x86_64架构)。构建不是完全成功的 - 一些汇编代码中的问题。然而,在标题处徘徊,有一个看起来像是解决你的问题:

cblas.h

在此,在许多其他函数定义中,我们发现:

void cblas_dgemm(enum CBLAS_ORDER Order, enum CBLAS_TRANSPOSE TransA,
                 enum CBLAS_TRANSPOSE TransB, blasint M, blasint N, blasint K,
                 double alpha, double *A, blasint lda, double *B, blasint ldb,
                 double beta, double *C, blasint ldc);

标题中的所有函数符号都以cblas_为前缀。您的代码应该使用:

#include "cblas.h"

您应该使用前缀为cblas_的Fortran名称(小写)调用函数:

cblas_dgemm(...);

要使用的正确链接行是上面列出的第一个选项:

gcc -Wall -o outputprog main.c -lgoto2

在紧要关头,你可以定义宏来将常规(无前缀)名称映射到正确的C函数名称,但我不相信它是值得的:

#define DGEMM cblas_dgemm

或(更安全,因为它检查参数列表的长度,但更详细):

#define DGEMM(a,b,c,d,e,f,g,h,i,j,k,l,m,n) cblas_dgemm(a,b,c,d,e,f,g,h,i,j,k,l,m,n)

然后你可以写:

DGEMM(a, ..., n);

将调用正确的函数。


上面提到的部分成功构建GotoBLAS2的实验表明:

  • cblas.h不是独立的(与良好的编码标准相反)。
  • common.h必须包含在其中。
  • common.h包含许多其他标头:
    • 的config.h
    • common_x86_64.h
    • param.h
    • common_param.h
    • common_interface.h
    • common_macro.h
    • common_s.h
    • common_d.h
    • common_q.h
    • common_c.h
    • common_z.h
    • common_x.h
    • common_level1.h
    • common_level2.h
    • common_level3.h
    • common_lapack.h
  • 以下代码有可能链接到完整的库:

    #include "common.h"
    #include "cblas.h"
    
    void check_dgemm(void)
    {
        double A[33] = { 0.0 };
        double B[33] = { 0.0 };
        double C[33] = { 0.0 };
        cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
                    3, 3, 3, 2.0, A, 3, B, 3, 3.0, C, 3);
    }
    
    int main(void)
    {
        check_dgemm();
        return 0;
    }
    

    (在我无可否认的图书馆建筑中,投诉从'cblas_dgemm()未被发现'转移到其他许多功能上。这是一个巨大的进步!)

答案 1 :(得分:3)

好的,我能够在GotoBLAS邮件列表https://lists.tacc.utexas.edu/mailman/listinfo/gotoblas上找到答案(据我所知,网站上没有列出这个答案)。以下是使用GotoBLAS2和C和GCC编译器的快速步骤。

构建GotoBLAS2库(.so和.a),库中包含的文档很好,所以我不会在这里发布。在-L所设置的libs目录中包含这些文件的两个。我只包括一个,因为我认为它们只是同一个库的不同版本,这是不正确的。

如果您希望使用gcc进行编译,也可以链接到-lgfortran-lpthread也可能有用,虽然我不确定,我已经看过它的例子,但它没有编译。你的gcc应该是这样的:

gcc -Wall -o outprog -L./GotoLIBSDIR -lgoto2 -lgfortran -lpthread(maybe) main.c

最后,在使用gfortran编译fortran接口时,请调用function_()而不是function(),例如dgemm_()

除了fortran接口之外,cblas接口可以用作cblas_dgemm()。您仍然需要链接到-lgfortran,否则链接到libgoto2.so将失败,您需要链接到该文件才能正确使用cblas_dgemm()

似乎没有必要包含任何.h文件或其他任何内容。

希望其他人会觉得这很有用。感谢您的帮助!