一.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的各种变异结构。