课程论文LU分解的OpenMP实现讲解.docx
《课程论文LU分解的OpenMP实现讲解.docx》由会员分享,可在线阅读,更多相关《课程论文LU分解的OpenMP实现讲解.docx(13页珍藏版)》请在冰豆网上搜索。
课程论文LU分解的OpenMP实现讲解
《并行算法实践》要求学生在KD60实验平台上设计并行算法并实现。
实验平台由一块处理板、一块监控板和一块背板等组成。
处理板逻辑结构如图1所示。
处理板承载4个处理单元,每个处理单元包括一个龙芯3号四核CPU、2GBDDR2内存、RTL8110千兆以太网卡芯片、BIOSFlash、串口收发芯片以及电源变换电路等。
四个龙芯3号处理器通过HT总线实现互连。
监控电路检测4个处理单元的状态,并实现对其控制。
图1处理板逻辑结构
实验平台的系统软件以开源软件为主(见图2),具有兼容性强、易维护、易升级、易使用等特点。
处理单元操作系统为DebianGNU/Linux无盘系统,采用稳定高效的2.6.27内核。
图2软件系统结构
要求选修《并行算法实践》同学在下面表1中选一个题目,
(1)阐述基本原理(包括对算法改进和优化方法);
(2)根据KD60实验平台设计实验方法和步骤(包括主要调试过程要求拷屏)。
(3)数据及结果分析:
根据不同的实验内容,记录具体的实验数据或程序运行结果(要求拷屏)。
实验数据量较大时,最好制成表格形式。
附上程序功能、模块说明、完整源代码,源代码中尽量多带注释;(4)分析和总结:
对程序与算法性能改进结论,总结和体会。
表1《并行算法实践》题目
序号
题目名称
基本方法和内容要求
1
LU分解的OpenMP实现
编写LU分解的OpenMP程序
2
KMP算法的OpenMP实现
编写KMP算法的OpenMP程序
3
高斯消元法解线性方程组的OpenMP实现
编写高斯消元法解线性方程组的OpenMP程序
4
高斯消元法解线性方程组的MPI实现
编写高斯消元法解线性方程组的MPI程序
5
高斯-塞德尔迭代解线性方程组的MPI实现
编写高斯-塞德尔迭代解线性方程组的MPI程序
6
Cannon乘法的MPI实现
编写Cannon乘法的MPI程序
7
LU分解的MPI实现
编写LU分解的MPI程序
8
随机串匹配算法的MPI实现
编写随机串匹配算法的MPI程序
9
单源最短路径Dijkstra算法的MPI实现
编写单源最短路径Dijkstra算法的MPI程序
10
快速排序算法的MPI实现
编写快速排序算法的MPI程序
11
KMP串匹配的MPI实现
编写KMP串匹配算法的MPI程序
一、实验课程名称:
并行算法实践
二、实验项目名称:
LU分解的OpenMP实现
三、实验目的:
理解多核程序的设计思想,学习使用OpenMP编写并行程序。
四、必修或选修:
选修
五、实验平台:
硬件平台:
龙芯3A教学仪器
软件平台:
DebianGNU/Linux2.6.27无盘系统,GCC4.3编译环境
六、实验原理:
(阐述基本原理,也包括对算法改进和优化方法)
对于一个n阶非奇异方阵A=[aij],对A进行LU分解是求一个主对角元素全为1的下三角方阵L=[lij]与上三角方阵U=[uij],使A=LU。
例如对于一个3×3的矩阵,就有
设A的各阶主子行列式皆非零,U和L的元素可由下面的递推式求出:
aij
(1)=aij
aij(k+1)=aij(k)-likukj
在计算过程中,首先计算出U的第一行元素,然后算出L的第一列元素,修改相应A的元素;再算出U的第二行,L的第二列…,直至算出unn为止。
若一次乘法和加法运算或一次除法运算时间为一个单位时间,则下述LU分解的串行算法时间复杂度为
=O(n3)。
单处理器上矩阵LU分解串行算法
输入:
矩阵An×n
输出:
下三角矩阵Ln×n,上三角矩阵Un×n
Begin
(1)fork=1tondo
(1.1)fori=k+1tondo
a[i,k]=a[i,k]/a[k,k]
endfor
(1.2)fori=k+1tondo
forj=k+1tondo
a[i,j]=a[i,j]-a[i,k]*a[k,j]
endfor
endfor
endfor
(2)fori=1tondo
(2.1)forj=1tondo
if(j
l[i,j]=a[i,j]
else
u[i,j]=a[i,j]
endif
endfor
(2.2)l[i,i]=1
endfor
End
LU分解的OpenMP并行算法主要是用pragmaompfor制导语句对非数据相关且非操作相关的for循环语句并行化。
多核处理器上矩阵LU分解OpenMP并行算法
Begin
#pragmaompparallelshared(A)private(tid,i,j,k)
{
(1)fork=1tondo
#pragmaompfor
{
(1.1)fori=k+1tondo
a[i,k]=a[i,k]/a[k,k]
endfor
}
#pragmaompfor
{
(1.2)fori=k+1tondo
forj=k+1tondo
a[i,j]=a[i,j]-a[i,k]*a[k,j]
endfor
endfor
}
endfor
}
(2)fori=1tondo
(2.1)forj=1tondo
if(j
l[i,j]=a[i,j]
else
u[i,j]=a[i,j]
endif
endfor
(2.2)l[i,i]=1
endfor
End
七、实验内容及步骤:
1.编写程序源代码:
lu.c
#include
#include
#include
#include
#include
#defineMaxN1010
#defineinfile"LU.in"
#defineoutfile"LU.out"
#defineNUM_OF_THREADS2
FILE*fin,*fout;//fin为输入文件fout为输出文件
doubleA[MaxN][MaxN];//A为原矩阵
doubleL[MaxN][MaxN],U[MaxN][MaxN];//L和U为分解后的矩阵
intn;//n为矩阵行数
intnthreads,tid;
intcreatefile()//创建A矩阵数据文件
{
inti=0,j=0;
n=1000;
srand((unsigned)time(NULL));
FILE*f;
f=fopen(infile,"w");
fprintf(f,"%d",n);
for(i=0;i{
for(j=0;jfprintf(f,"%d",rand()%1000);
fprintf(f,"%c",'\n');
}
fclose(f);
printf("Finished!
\n");
return0;
}
intinit()//初始化,读取A矩阵数据文件
{
inti,j;
fscanf(fin,"%d",&n);
for(i=0;ifor(j=0;jfscanf(fin,"%lf",&A[i][j]);
omp_set_num_threads(NUM_OF_THREADS);//设置OpenMP线程数量
for(i=0;ifor(j=0;j{
L[i][j]=0;
U[i][j]=0;
}
for(i=0;ireturn0;
}
intfactorize()
{
inti,j,k;
#pragmaompparallelshared(A)private(tid,i,j,k)
{
for(k=0;k{
#pragmaompfor//for循环并行制导语句
for(i=k+1;iA[i][k]=A[i][k]/A[k][k];
#pragmaompfor//for循环并行制导语句
for(i=k+1;ifor(j=k+1;j{
A[i][j]=A[i][j]-A[i][k]*A[k][j];
}
}
}
for(i=0;ifor(j=0;j{
if(i<=j)U[i][j]=A[i][j];
elseL[i][j]=A[i][j];
}
return0;
}
intoutput()
{
inti,j;
//输出L矩阵
fprintf(fout,"MatrixL:
\n");
for(i=0;ifor(j=0;jfprintf(fout,"%.10lf%c",L[i][j],(j==n-1)?
'\n':
'');
//输出U矩阵
fprintf(fout,"MatrixU:
\n");
for(i=0;ifor(j=0;jfprintf(fout,"%.10lf%c",U[i][j],(j==n-1)?
'\n':
'');
return0;
}
intmain()
{
doublets,te;
while((fin=fopen(infile,"r"))==NULL)//如果检测不到A矩阵数据文件,则调用createfile()函数,以随机数创建一个
{
createfile();
}
fout=fopen(outfile,"w");
//初始化
init();
//矩阵分解
ts=omp_get_wtime();
factorize();
te=omp_get_wtime();
printf("time=%fs\n",te-ts);//输出LU分解所用时间
//输出结果
output();
fclose(fin);
fclose(fout);
return0;
}
2.下载并安装SecureCRT
(可在或自行上网搜索下载)
3.主机名192.168.150.218,用户名kd60,密码kd60
4.进入后,以sshroot@192.168.60.80登陆龙芯实验平台KD60,密码kd60。
5.编译命令gcclu.c–olu-fopenmp
6.运行命令./lu,即可得到实验结果。
八、实验数据及结果:
本实验对1000阶矩阵进行LU分解。
当把线程个数设置为4时,即#defineNUM_OF_THREADS4
运行时间为11.566771秒。
当把线程个数设置为2时,即#defineNUM_OF_THREADS2
运行时间为22.170146秒。
当把线程个数设置为1时,即#defineNUM_OF_THREADS1
程序实际上变成串行程序,运行时间为45.148058秒。
当把线程个数设置为8时,即#defineNUM_OF_THREADS8
由于龙芯3A处理器只有4核,线程数量超过4时,实际上将不再完全是并行执行,反而会带来一定的线程切换开销。
运行时间竟长达194.894202秒。
根据以上实验数据,计算得加速比如下:
线程数
1
2
4
8
运行时间(s)
45.148058
22.170146
11.566771
194.894202
加速比
1x
2.03x
3.90x
0.23x
九、实验结论分析及总结:
1.实验结论分析:
由于龙芯3A实验平台采用四核的龙芯3A处理器,因此OpenMP线程数设置为4时,达到最大加速比,即3.90,非常接近4。
当线程数设置为2时,只用到一半的处理器核,也即2个,加速比为2..03,接近2。
当线程数设置为1时,程序退化为串行程序。
如果把线程数设置得比4更大,将反而使加速比下降,甚至运行时间比串行程序更大。
例如线程数为8时,运行时间长达194.9秒之外,远大于串行程序的45秒,主要原因为线程切换开销。
2.总结
对于OpenMP并行程序设计,只有当线程数量设置与处理器核数量相同时,才能获得最大的加速比。
小于或大于处理器核数量,都将使加速比下降。