并行计算八皇后问题.docx
《并行计算八皇后问题.docx》由会员分享,可在线阅读,更多相关《并行计算八皇后问题.docx(47页珍藏版)》请在冰豆网上搜索。
![并行计算八皇后问题.docx](https://file1.bdocx.com/fileroot1/2023-5/25/38b8a04a-f326-48c2-bcd9-0e9b4640a05e/38b8a04a-f326-48c2-bcd9-0e9b4640a05e1.gif)
并行计算八皇后问题
并行计算与多核多线程技术
课程报告
班级__________________
学号_____________
姓名_________________
2014年11月26日
评价
实践效果(正确度/加速比)
理论基础
难度
工作量
独立性
1.N皇后问题并行算法设计与实现
1.1功能描述与解决方案
1.1.1功能描述
八皇后问题是十九世纪著名数学家高斯于1850年提出的。
问题是:
在8*8的棋盘上摆放8个皇后,使其不能互相攻击,即任意的两个皇后不能处在同意行,同一列,或同意斜线上。
可以把八皇后问题拓展为n皇后问题,即在n*n的棋盘上摆放n个皇后,使其任意两个皇后都不能处于同一行、同一列或同一斜线上。
1.1.2解决方案
1、此题有多重解法,常见解法有残卷法(即穷举法,但时间复杂度和空间复杂度均为N^N,并不高效)和递归+回溯算法(本次采用此算法)。
2、判断当前放置的皇后“安全”的依据为同行、同列、对角线-\、对角线-/的遍历结果均为TRUE即没有不满足问题条件的皇后存在。
3、第一个线程从第一列第一行的坐标开始放置皇后,其他线程从其他列第一行的元素开始递归放置皇后,每放置一个皇后,判断其是否安全,若“安全”则继续在当前列和(当前行+1)处放置下一个皇后,若不安全则将当前皇后坐标设为0。
4、采用三维数组m[THREAD][QUEENS][QUEENS]来存放棋盘的放置状态,第一维用于保证各线程不会影响其他线程的放置状态,第二、三维用来确定棋盘的规格。
1.2算法设计
1.2.1串行算法设计
/**
*wy_serial_listAllCol:
ListAllTheValidChessTableInSerialWay
*
*@paramm[][][]
*@paramy
*/
staticvoidwy_serial_listAllCol(intm[THREADS][QUEENS][QUEENS],inty){for(intx=0;xm[0][x][y]=1;
if(wy_isOk(m,x,y,0)){
if(y==QUEENS-1){
//print(m,0);
}else
wy_serial_listAllCol(m,y+1);
}
m[0][x][y]=0;
}
}
1.2.2并行算法设计
OpenMP使用parallelfor来调用listFirstCol()函数,listFirstCol再递归调用listSecondCol()函数来实现各线程并行递归回溯
其他语言使用并行区域的办法来保证各线程并行递归回溯
/**
*wy_parallel_listOtherCol:
DetermineTheOtherColsInParallelWay
*
*@paramm[][][]
*@paramy
*@paramthread
*/
staticvoidwy_parallel_listOtherCol(intm[THREADS][QUEENS][QUEENS],inty,intthread){
for(intx=0;xm[thread][x][y]=1;
if(wy_isOk(m,x,y,thread)){
if(y==QUEENS-1){
//print(m,omp_get_thread_num());
}else
wy_parallel_listOtherCol(m,y+1,thread);
}
m[thread][x][y]=0;
}
}
/**
*wy_parallel_listFirstCol:
DetermineTheFirstColInParallelWay
*
*@paramm[][][]
*@paramy
*/
staticvoidwy_parallel_listFirstCol(intm[THREADS][QUEENS][QUEENS],inty){
#pragmaompparallelfor
for(intx=0;x//printf("thread_num%d\n",omp_get_thread_num());
m[omp_get_thread_num()][x][y]=1;
if(wy_isOk(m,x,y,omp_get_thread_num())){
wy_parallel_listOtherCol(m,y+1,omp_get_thread_num());
}
m[omp_get_thread_num()][x][y]=0;
}
}
1.2.3理论加速比分析(选作)
在N皇后问题中,加速比一般为Thread数目,最高加速比为N。
因为最多允许N个线程同时运行。
1.3基于OpenMP的并行算法实现
1.3.1代码及注释(变量名名字首字母开头)
//YTUWangYang123-2201258503222OpenMPN-QUEEN
#include"stdafx.h"
#defineQUEENS8/*QUEENSNUM*//*8QUEENSHAVA92RES*/
#defineTHREADS4/*THREADSTOTALNUM*/
/**
*wy_isOk:
CheckTheCurrentQueenSiteValidity
*
*@paramx
*@paramy
*@returnbool-value
*/
staticboolwy_isOk(intm[THREADS][QUEENS][QUEENS],intx,inty,intthread){
inttx,ty;
/*Samerow,returnfalse*/
for(ty=0;tyif(m[thread][x][ty]==1)returnfalse;
}
/*Samecol,impossible*/
/*Diagonal\,returnfalse*/
tx=x;ty=y;
while(--tx>=0&&--ty>=0){
if(m[thread][tx][ty]==1)returnfalse;
}
/*Diagonal/,returnfalse*/
tx=x;ty=y;
while(++tx=0){
if(m[thread][tx][ty]==1)returnfalse;
}
returntrue;
}
/**
*count:
CurrentCount
*/
staticintcount=1;
/**
*print:
PrintCurrentFinishedChessTable
*
*@paramm[][][]
*@paramthread
*/
staticvoidprint(intm[THREADS][QUEENS][QUEENS],intthread){
printf(">%d\n",count);
count++;
for(inti=0;ifor(intj=0;jprintf("%d",m[thread][i][j]);
}
printf("\n");
}
}
/**
*wy_serial_listAllCol:
ListAllTheValidChessTableInSerialWay
*
*@paramm[][][]
*@paramy
*/
staticvoidwy_serial_listAllCol(intm[THREADS][QUEENS][QUEENS],inty){
for(intx=0;xm[0][x][y]=1;
if(wy_isOk(m,x,y,0)){
if(y==QUEENS-1){
//print(m,0);
}else
wy_serial_listAllCol(m,y+1);
}
m[0][x][y]=0;
}
}
/**
*wy_parallel_listOtherCol:
DetermineTheOtherColsInParallelWay
*
*@paramm[][][]
*@paramy
*@paramthread
*/
staticvoidwy_parallel_listOtherCol(intm[THREADS][QUEENS][QUEENS],inty,intthread){
for(intx=0;xm[thread][x][y]=1;
if(wy_isOk(m,x,y,thread)){
if(y==QUEENS-1){
//print(m,omp_get_thread_num());
}else
wy_parallel_listOtherCol(m,y+1,thread);
}
m[thread][x][y]=0;
}
}
/**
*wy_parallel_listFirstCol:
DetermineTheFirstColInParallelWay
*
*@paramm[][][]
*@paramy
*/
staticvoidwy_parallel_listFirstCol(intm[THREADS][QUEENS][QUEENS],inty){
#pragmaompparallelfor
for(intx=0;x//printf("thread_num%d\n",omp_get_thread_num());
m[omp_get_thread_num()][x][y]=1;
if(wy_isOk(m,x,y,omp_get_thread_num())){
wy_parallel_listOtherCol(m,y+1,omp_get_thread_num());
}
m[omp_get_thread_num()][x][y]=0;
}
}
int_tmain(intargc,_TCHAR*argv[]){
intm[THREADS][QUEENS][QUEENS];
/*ParallelPart*/
omp_set_num_threads(THREADS);
clock_tt1=clock();
for(inti=0;ifor(intj=0;jfor(intz=0;zm[i][j][z]=0;
}
}
}
wy_parallel_listFirstCol(m,0);
clock_tt2=clock();
floatpt=t2-t1;
printf("NQUEEN:
N=%d\n",QUEENS);
printf("ParallelTime=%f\n",pt);
/*SerialPart*/
t1=clock();
for(inti=0;ifor(intj=0;jfor(intz=0;zm[i][j][z]=0;
}
}
}
wy_serial_listAllCol(m,0);
t2=clock();
floatst=t2-t1;
printf("SerialTime=%f\n",st);
printf("相对加速比=%f\n",st/pt);
getch();
return0;
}
1.3.2执行结果截图(体现串行时间、并行时间和加速比)
(1)小数据量验证正确性的执行结果
N=12SerialTime=498,ParallelTime=1235
相对加速比=2.479
(2)大数据量获得较好加速比的执行结果
N=14SerialTime=20340,ParallelTime=41072
相对加速比=2.019
1.3.3遇到的问题及解决方案
(1)问题一
错误代码及后果
当数组m维数为2维时,无法避免其他线程对当前线程的影响,各线程存在数据竞争,无法准确的描述棋盘放置状态。
正确代码
应将数组设置为3维,第1维为Thread维,避免多线程共同操作同一个棋盘,出现数据竞争。
分析
OpenMP和Intel的CPU兼容很好,所以加速比很理想。
1.4基于MPI的并行算法实现
1.4.1代码及注释(变量名名字首字母开头)
//YTUWangYang123-2201258503222MPIN-QUEEN
#include"stdafx.h"
#defineQUEENS8/*QUEENSNUM*//*8QUEENSHAVE92RES*/
#defineTHREADS2/*THREADSTOTALNUM*/
/**
*wy_isOk:
CheckTheCurrentQueenSiteValidity
*
*@paramx
*@paramy
*@returnbool-value
*/
staticboolwy_isOk(intm[THREADS][QUEENS][QUEENS],intx,inty,intthread){
inttx,ty;
/*Samerow,returnfalse*/
for(ty=0;tyif(m[thread][x][ty]==1)returnfalse;
}
/*Samecol,impossible*/
/*Diagonal\,returnfalse*/
tx=x;ty=y;
while(--tx>=0&&--ty>=0){
if(m[thread][tx][ty]==1)returnfalse;
}
/*Diagonal/,returnfalse*/
tx=x;ty=y;
while(++tx=0){
if(m[thread][tx][ty]==1)returnfalse;
}
returntrue;
}
/**
*count:
CurrentCount
*/
staticintcount=1;
/**
*print:
PrintCurrentFinishedChessTable
*
*@paramm[][][]
*@paramthread
*/
staticvoidprint(intm[THREADS][QUEENS][QUEENS],intthread){
printf(">%d\n",count);
count++;
for(inti=0;ifor(intj=0;jprintf("%d",m[thread][i][j]);
}
printf("\n");
}
}
/**
*wy_serial_listAllCol:
ListAllTheValidChessTableInSerialWay
*
*@paramm[][][]
*@paramy
*/
staticvoidwy_serial_listAllCol(intm[THREADS][QUEENS][QUEENS],inty){
for(intx=0;xm[0][x][y]=1;
if(wy_isOk(m,x,y,0)){
if(y==QUEENS-1){
//print(m,0);
}else
wy_serial_listAllCol(m,y+1);
}
m[0][x][y]=0;
}
}
/**
*wy_parallel_listOtherCol:
DetermineTheOtherColsInParallelWay
*
*@paramm[][][]
*@paramy
*@paramthread
*/
staticvoidwy_parallel_listOtherCol(intm[THREADS][QUEENS][QUEENS],inty,intthread){
for(intx=0;xm[thread][x][y]=1;
if(wy_isOk(m,x,y,thread)){
if(y==QUEENS-1){
//print(m,thread);
}else
wy_parallel_listOtherCol(m,y+1,thread);
}
m[thread][x][y]=0;
}
}
/**
*wy_parallel_listFirstCol:
DetermineTheFirstColInParallelWay
*
*@paramm[][][]
*@paramy
*/
staticvoidwy_parallel_listFirstCol(intm[THREADS][QUEENS][QUEENS],inty,intthread){
intfloorLength=int(floor(double(QUEENS/2)));
if(thread==0){
for(intx=0;xm[thread][x][y]=1;
if(wy_isOk(m,x,y,thread)){
wy_parallel_listOtherCol(m,y+1,thread);
}
m[thread][x][y]=0;
}
}else{
for(intx=floorLength;xm[thread][x][y]=1;
if(wy_isOk(m,x,y,thread)){
wy_parallel_listOtherCol(m,y+1,thread);
}
m[thread][x][y]=0;
}
}
}
int_tmain(intargc,char*argv[]){
intm[THREADS][QUEENS][QUEENS];
/*ParallelPart*/
intn=0,done=0;
intthread,size;
doublet1,t2;
MPI_Init(&argc,&argv);/*InitMPI*/
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Comm_rank(MPI_COMM_WORLD,&thread);
for(inti=0;ifor(intj=0;jfor(intz=0;zm[i][j][z]=0;
}
}
}
while(!
done){
if(thread==0){
t1=clock();
}
MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD);
if(n==0){
done=1;
}
wy_parallel_listFirstCol(m,0,thread);
if(n==0)
t2=clock();
}
MPI_Finalize();/*FinishMPI*/
doublept=t2-t1;
printf("NQUEEN:
N=%d\n",QUEENS);
printf(