高性能计算

cell下blas库的使用-程序编译及模拟运行

2009年4月23日 阅读(169)

一.makefile:
编译时的makefile我们参考了/opt/cell/sdk/src/blas-examples下的makefile的写法,最终如下:
Makefile:
PROGRAM_ppu :=  solve
IMPORTS =  $(SDKLIB_ppu)/libblas.so  \
            -lspe2 -lm -lnuma
LDFLAGS += -Wl,-rpath  $(SDKLIB_ppu)
include /opt/cell/sdk/buildutils/make.footer

二.源程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cblas.h>
#include "malloc_align.h"

void environment_init();
typedef double data_t;
int N,M;//N行,M列,M = N+1
data_t * matrix_A;//X的系数矩阵
data_t * B;//y向量
data_t * X;//x的解向量
int *shift_table;

//通过A(i,j)得到,x系数矩阵中[i,j]元素的地址
data_t * A(int i,int j){
    return matrix_A+i*N+j;
}
void print_matrix();

int main()
{
    FILE * f = fopen("data.txt","r");
    int i = 0,j = 0,index = 0,row = 0,temp = 0;
   
    fscanf(f,"%d%d",&N,&M);
    matrix_A = (data_t *)_malloc_align(sizeof(data_t)*N*N,7);
    B = (data_t *)_malloc_align(sizeof(data_t)*N,7);
    X = (data_t *)_malloc_align(sizeof(data_t)*N,7);
    shift_table = (int*)_malloc_align(sizeof(int)*N,7);
  
    //get matrix from file
    for(i = 0 ; i < N ; i++){
        for(j = 0 ; j < N ; j++){
            fscanf(f,"%lf",A(i,j));  
            printf("%lf ",*A(i,j));
        }
        fscanf(f,"%lf",B+i);
        printf("%lf\n",*(B+i));
    }    
    //init shift table
    for(i = 0 ; i < N ; i++){
        shift_table[i] = i;
    }
    //computer
    for(i = 0 ; i < N-1 ; i++){
        //选主元
    index = cblas_idamax(N-i,A(i,i),1)+i;//cblas_idamax 选择最大绝对值的blas库
    printf("index:%d\n",index);
        //列交换
        if(index != i){
           temp = shift_table[i]; 
       shift_table[i] = shift_table[index];     
           shift_table[index] = temp;
           for(row = 0 ; row < N ; row++){
               data_t temp = *A(row,i);  
               *(A(row,i)) = *A(row,index); 
               *A(row,index) = temp;
           }
        }
    for(row = 0 ; row < N ; row++)
        printf("%d ",shift_table[row]);
    printf("\n");
        //主元归一化
        // 消元
        for(row = i+1 ; row < N ; row++){
        if(*A(row,i) == 0) continue;   
        data_t factor = -1*(*A(row,i)/ *A(i,i));
        cblas_daxpy(N-i,factor,A(i,i),1,A(row,i),1);//cblas_daxpy( N, alpha,X,incX, Y, incY); Y=Y+alpha*X
        *(B+row) = *(B+row) + *(B+i)*factor;   
        }
        print_matrix();
      
    }
    //回代,i代表了Xi,col代表了列号,用来计算前面已经计算的xi值的sum
    for(i = N-1 ; i >= 0 ; i–){
        data_t sum = 0;
        for( j = i+1 ; j < N ; j++){
            sum += *A(i,j)*X[j];  
        }
        X[i] = (*(B+i) – sum) / *A(i,i);
    }
    //恢复,其中shift table保存了原来的列号
    for(i = 0 ; i < N ; i++){
        printf("x%d:%lf ",shift_table[i],X[i]);
    } 
              

 
}
void print_matrix(){
    int i,j;   
    printf("matrix:\n");
    for(i = 0 ; i < N ; i++){
        for(j = 0 ; j < N ; j++){
                printf("%lf ",*A(i,j));
        }
        printf("%lf\n",*(B+i));
    }

}

三.cell模拟器上的运行:
sudo su
ulimit -s unlimited
export PATH=/opt/ibm/systemsim-cell/bin:$PATH
systemsim -g
选择mode->fast mode ->go,在模拟器中输入如下命令
callthru source /home/duanple/test/test>test
chmod +x test
./test
当我们把采用blas编写的高斯消元解方程的cell程序,拷贝到模拟器时,出现如下错误:找不到libblas.so.1 libalf.so.4
解决方法:再次利用callthru source,将ubuntu上的这两个库放到了cell模拟器上的/lib目录下,这样就可以运行了
/opt/cell/sysroot/usr/lib/libblas.so.1
/opt/cell/sysroot/usr/lib/libalf.so.4
但是运行时出现了segement fault.原因是忘了拷贝data.txt,拷贝完毕就可以了。

四.cell上的blas库有如下特殊点:
1.
cell使用的是_malloc_align,这个函数的代码,直接位于malloc_align.h里,因此其他平台的可以直接复制它,就可以防止代码的差异。
/opt/cell/sysroot/opt/cell/sdk/usr/spu/include/malloc_align.h
/opt/cell/sysroot/opt/cell/sdk/usr/include/malloc_align.h

2.blas库不同,需要链接到正确的那个库部分
/usr/include/cblas.h
/home/duanple/test/cblas.h
/home/duanple/CBLAS/src/cblas.h

普通blas库的安装使用:

CBLAS是BLAS的C语言接口。BLAS的全称是Basic Linear Algebra Subprograms,中文大概可以叫做基础线性代数子程序。主要是用于向量和矩阵计算的高性能数学库。本身BLAS是用Fortran写的,为了方便C/C++程序的使用,就有了BLAS的C接口库CBLAS。BLAS的主页是http://www.netlib.org/blas/,CBLAS的下载地址也可以在这个页面上找到。
 
CBLAS安装需要先装BLAS,从主页上下载blas.tgz,解压,根据系统修改make.inc和Makefile,make,就会生成一个blas_LINUX.a文件。然后,下载cblas.tgz,解压,在目录下将Makefile.*文件改名或者做一个链接文件为Makefile.in文件,比如在linux下就是ln -s Makefile.LINUX Makefile.in,根据具体情况修改Makefile.in文件,主要是BLAS的库文件路径BLLIB和CBLAS的安装目录CBDIR,make help就可以打印出可以使用的make命令,要生成全部文件就是用make all。在$(CBDIR)目录下的$(CBLIBDIR)将生成CBLAS的库文件$(CBLIB),cblas_LINUX.a。
 
在CBLAS的安装目录$(CBDIR)下的src目录中有个cblas.h是包括的CBLAS的函数和常量的头文件,使用CBLAS的时候就需要这个头文件,同时还需要BLAS的库文件$(BLLIB )和CBLAS的库文件$(CBLIB)。

编译构建方法:
直接使用gcc是不行的,通过观察cblas下的make example,得到如下过程:
gcc -c -O3 -DADD_ -Isrc cblas_example1.c
g77 -o cblas_ex1 cblas_example1.o /home/duanple/CBLAS/lib/LINUX/cblas_LINUX.a /home/duanple/BLAS/blas_LINUX.a
直接使用命令仍然有问题,因此我们仍然借鉴它们所提供的实例,CBLAS下的make 命令,提供了example1这样的实例目标,得到如下方法:
把我们使用的solve.c代替CBLAS下的cblas_example1.c文件,进行编译时只需要make example1便可以了。
我们对于普通平台 的blas采用如下方法实验:

 两个环境如果要使用相同源代码需要的支持:
1,必须为非cell开发环境提供malloc_align.h,比如将其加入INCLUDE路径
2.考虑如何统一上述复杂不一的make过程,以及makefile的各种变异结构。

You Might Also Like