我是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
文件(或者不是),但我不确定哪一个(或者这是否正确)。
任何有关此的帮助将不胜感激。如果需要更多信息,请告诉我。
答案 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
包含许多其他标头:
以下代码有可能链接到完整的库:
#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文件或其他任何内容。
希望其他人会觉得这很有用。感谢您的帮助!