CLAPACK安装问题解决及应用举例

今天在安装及使用CLAPACK的过程中,遇到诸多问题,现就遇到的问题及解决方式做简单记录,楼主的CLAPACK版本为3.2.1,操作系统为ubuntu 15.04,编译器为默认版本。

在安装CLAPACK的过程中,应对程序的源码做简单分析。根据源码中给出的安装手册中给出的说明手册,/BLAS/SRC 文件夹下给出了 BLAS 的程序源码,SRC文件夹下给出了CLAPACK的程序源码,/F2CLIBS/libf2c 文件夹下存放的是f2c库的程序源码。以上三部分源码会被分别编译为blas_LINUX.a、lapack_LINUX.a、libf2c.a,三个静态库的依赖关系依次为lapack_LINUX.a -> blas_LINUX.a -> libf2c.a,lapack中会调用位于blas中的函数,而blas中会调用libf2c中的函数,具体的分析过程也会给出。

好了,现在给出详细的安装过程,主要参考源码包中的README.install文件

1)解压缩并制作make.inc

解压缩命令:gunzip clapack.tgz;tar xvf clapack.tar

制作make.inc:由于makefile中包含的是make.inc,而当前软件包中给出的是make.inc.example,因此将make.inc.example根据机器的实际情况进行修改,实际情况就是,楼主根本不需要任何修改,直接就改为了make.inc。

2)在根目录下 make f2clib,这一步没有任何问题,产生libf2c.a为静态库。

3)在根目录下 make blaslib ,这一步可选,可选用其他blas库,推荐使用blaslib,主要由于其安装方便,产生blas_LINUX.a。若选用其他blas库,则需要make cblaswrap,不过这一步楼主并没有实践,因此有兴趣的同学可以自行摸索。

4)在根目录下make,至此安装过程全部完成,产生lapack_LINUX.a。

安装完成后就要使用clapack,clapack 作为一套静态链接库,在使用过程直接链接即可。因此首先编写测试代码,所使用的测试代码来自于以下地址:http://www.netlib.org/clapack/faq.html#1.4 1.9节。

代码如下:

/* Start of Listing */

#include "f2c.h"
#include "stdio.h"
#include "clapack.h"

#define SIZE 4

main( )
{
     char JOBU;
     char JOBVT;

     int i;
    
     integer M = SIZE;
     integer N = SIZE;
    
     integer LDA = M;
     integer LDU = M;
     integer LDVT = N;
     integer LWORK;
     integer INFO;
   
     integer mn = min( M, N );
    
     integer MN = max( M, N );
     
     double a[SIZE*SIZE] = { 16.0, 5.0, 9.0 , 4.0, 2.0, 11.0, 7.0 , 14.0, 3.0, 10.0, 6.0, 15.0, 13.0, 8.0, 12.0, 1.0};
     double s[SIZE];
     double wk[201];
     double uu[SIZE*SIZE];
     double vt[SIZE*SIZE];
     
       JOBU = 'A';
     
       JOBVT = 'A';
     
    LWORK =  201;
    
/* Subroutine int dgesvd_(char *jobu, char *jobvt, integer *m, integer *n, 
        doublereal *a, integer *lda, doublereal *s, doublereal *u, integer *
        ldu, doublereal *vt, integer *ldvt, doublereal *work, integer *lwork, 
        integer *info)
*/

    dgesvd_( &JOBU, &JOBVT, &M, &N, a, &LDA, s, uu, 
          &LDU, vt, &LDVT, wk, &LWORK, &INFO);
          
    printf("\n INFO=%d", INFO );          

    for ( i= 0; i< SIZE; i++ ) {
        printf("\n s[ %d ] = %f", i, s[ i ] );
    }

    return 0;
}     

/* End of Listing */

根据安装说明,程序在链接时需要使用的静态库有blas_LINUX.a、lapack_LINUX.a、libf2c.a,但在编译libf2c.a时发现其中有main函数,测试程序中同样具有main函数,如果直接编译会出现main函数重定义的情况,因此先试着写了一个makefile看是否还存在其他问题,makefile如下,其实只有一句话。

gcc -o my_test_lapack -I./INCLUDE -L./ lapack_LINUX.a blas_LINUX.a libf2c.a -lm my_test_lapack.c

结果错误如下:

my_test_lapack.c: In function ‘main’:
my_test_lapack.c:48:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘integer’ [-Wformat=]
     printf("\n INFO=%d", INFO );          
     ^
/tmp/ccLtDGCS.o:在函数‘main’中:
my_test_lapack.c:(.text+0x0): `main'被多次定义
libf2c.a(main.o):(.text.startup+0x0):第一次在此定义
libf2c.a(main.o):在函数‘main’中:
(.text.startup+0x87):对‘MAIN__’未定义的引用
/tmp/ccLtDGCS.o:在函数‘main’中:
my_test_lapack.c:(.text+0x229):对‘dgesvd_’未定义的引用
collect2: error: ld returned 1 exit status

通过观察发现main函数确实重定义了,通过nm与grep命令组合的方式,确定main函数在main.o中。因此第一个想法是把main.o从libf2c.a中删除,使用如下命令:

ar -dv libf2c.a main.o

 结果如下:

d - main.o

代表被删除的模块。而后再次运行makefile文件

结果如下:

my_test_lapack.c: In function ‘main’:
my_test_lapack.c:48:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘integer’ [-Wformat=]
     printf("\n INFO=%d", INFO );          
     ^
/tmp/ccWCXPdq.o:在函数‘main’中:
my_test_lapack.c:(.text+0x229):对‘dgesvd_’未定义的引用
collect2: error: ld returned 1 exit status

发现dgesvd函数仍然未定义,同样使用nm与grep命令相结合的方式,查找dgesvd函数的实现,在lapack_LINUX.a找到相关定义,结果如下:
dgesvd.o:
0000000000000000 T dgesvd_

发现dgesvd确实已经实现了,直接使用“对‘dgesvd_’未定义的引用”进行搜索,结果发现这篇博客中介绍的方法: http://www.linuxdiyf.com/linux/16754.html

原来是文件依赖顺序的问题,因此修改makefile文件为:

gcc -o my_test_lapack my_test_lapack.c -I./INCLUDE -L./ lapack_LINUX.a blas_LINUX.a libf2c.a -lm 

结果问题就得到了顺利解决,尝试运行程序,结果为:

 INFO=0
 s[ 0 ] = 34.000000
 s[ 1 ] = 17.888544
 s[ 2 ] = 4.472136
 s[ 3 ] = 0.000000

好问题来了,要是我们把main.o加回到libf2c.a中会出现什么情况,使用命令如下:

首先使用“ar -t libf2c.a”命令查看obj文件顺序,发现f77vers.o是第一个文件。

然后使用

ar -rbv f77vers.o libf2c.a main.o 

命令将main.o重新加入到libf2c.a,并运行makefile,结果如下:

my_test_lapack.c: In function ‘main’:
my_test_lapack.c:48:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘integer’ [-Wformat=]
     printf("\n INFO=%d", INFO );          
     ^

编译同样通过,怎么不报重定义的错误了????,运行以下看看结果是不是对的,运行结果如下:

 INFO=0
 s[ 0 ] = 34.000000
 s[ 1 ] = 17.888544
 s[ 2 ] = 4.472136
 s[ 3 ] = 0.000000

与上面的运行结果完全相同!!!!

不知道大神有没有时间完整的看完这篇blog,并帮我解决问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值