1、并行计算八皇后问题并行计算与多核多线程技术课程报告班级 _学号_ 姓名 _ 2014 年 11 月 26 日评 价实践效果(正确度/加速比)理论基础难度工作量独立性1. N皇后问题 并行算法设计与实现1.1 功能描述与解决方案1.1.1功能描述八皇后问题是十九世纪著名数学家高斯于1850年提出的。问题是:在8*8的棋盘上摆放8个皇后,使其不能互相攻击,即任意的两个皇后不能处在同意行,同 一列,或同意斜线上。可以把八皇后问题拓展为n皇后问题,即在n*n的棋盘上摆放n个皇后,使其任意两个皇后都不能处于同一行、同一列或同一斜线上。1.1.2 解决方案1、此题有多重解法,常见解法有残卷法(即穷举法,但
2、时间复杂度和空间复杂度均为NN,并不高效)和递归+回溯算法(本次采用此算法)。2、判断当前放置的皇后“安全”的依据为同行、同列、对角线-、对角线-/的遍历结果均为TRUE即没有不满足问题条件的皇后存在。3、第一个线程从第一列第一行的坐标开始放置皇后,其他线程从其他列第一行的元素开始递归放置皇后,每放置一个皇后,判断其是否安全,若“安全”则继续在当前列和(当前行+1)处放置下一个皇后,若不安全则将当前皇后坐标设为0。4、采用三维数组mTHREADQUEENSQUEENS来存放棋盘的放置状态,第一维用于保证各线程不会影响其他线程的放置状态,第二、三维用来确定棋盘的规格。1.2算法设计1.2.1 串
3、行算法设计/* * wy_serial_listAllCol : List All The Valid Chess Table In Serial Way * * param m * param y */ static void wy_serial_listAllCol(int mTHREADSQUEENSQUEENS , int y) for(int x = 0; x QUEENS; x+) m0xy = 1; if(wy_isOk(m, x, y,0) if(y = QUEENS - 1) /print(m,0); else wy_serial_listAllCol(m, y+1); m0
4、xy = 0; 1.2.2 并行算法设计OpenMP使用parallel for 来调用listFirstCol()函数,listFirstCol再递归调用listSecondCol()函数来实现各线程并行递归回溯其他语言使用并行区域的办法来保证各线程并行递归回溯/* * wy_parallel_listOtherCol : Determine The Other Cols In Parallel Way * * param m * param y * param thread */ static void wy_parallel_listOtherCol(int mTHREADSQUEENS
5、QUEENS , int y,int thread) for(int x = 0; x QUEENS; x+) mthreadxy = 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); mthreadxy = 0; /* * wy_parallel_listFirstCol : Determine The First Col In Parallel Way * * param m * param
6、 y */ static void wy_parallel_listFirstCol(int mTHREADSQUEENSQUEENS , int y) #pragma omp parallel for for(int x = 0; x QUEENS; x+) /printf(thread_num%dn,omp_get_thread_num(); momp_get_thread_num()xy = 1; if(wy_isOk(m, x, y,omp_get_thread_num() wy_parallel_listOtherCol(m, y+1,omp_get_thread_num(); mo
7、mp_get_thread_num()xy = 0; 1.2.3 理论加速比分析(选作)在N皇后问题中,加速比一般为Thread数目,最高加速比为N。因为最多允许N个线程同时运行。1.3 基于OpenMP的并行算法实现1.3.1 代码及注释(变量名 名字首字母 开头)/YTU Wang Yang 123-2 201258503222 OpenMP N-QUEEN #include stdafx.h #define QUEENS 8 /* QUEENS NUM */* 8 QUEENS HAVA 92 RES */ #define THREADS 4 /* THREADS TOTAL NUM *
8、/ /* * wy_isOk : Check The Current Queen Site Validity * * param x * param y * return bool-value */ static bool wy_isOk(int mTHREADSQUEENSQUEENS,int x,int y,int thread) int tx,ty; /* Same row , return false */ for(ty = 0;ty = 0 & -ty = 0) if(mthreadtxty = 1)return false; /* Diagonal / , return false
9、 */ tx = x; ty = y; while(+tx = 0) if(mthreadtxty = 1)return false; return true; /* * count : Current Count */ static int count = 1; /* * print : Print Current Finished Chess Table * * param m * param thread */ static void print(int mTHREADSQUEENSQUEENS,int thread) printf(%dn,count); count+; for(int
10、 i = 0 ; i QUEENS ; i+) for(int j = 0 ; j QUEENS ; j+) printf( %d,mthreadij); printf(n); /* * wy_serial_listAllCol : List All The Valid Chess Table In Serial Way * * param m * param y */ static void wy_serial_listAllCol(int mTHREADSQUEENSQUEENS , int y) for(int x = 0; x QUEENS; x+) m0xy = 1; if(wy_i
11、sOk(m, x, y,0) if(y = QUEENS - 1) /print(m,0); else wy_serial_listAllCol(m, y+1); m0xy = 0; /* * wy_parallel_listOtherCol : Determine The Other Cols In Parallel Way * * param m * param y * param thread */ static void wy_parallel_listOtherCol(int mTHREADSQUEENSQUEENS , int y,int thread) for(int x = 0
12、; x QUEENS; x+) mthreadxy = 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); mthreadxy = 0; /* * wy_parallel_listFirstCol : Determine The First Col In Parallel Way * * param m * param y */ static void wy_parallel_listFirstC
13、ol(int mTHREADSQUEENSQUEENS , int y) #pragma omp parallel for for(int x = 0; x QUEENS; x+) /printf(thread_num%dn,omp_get_thread_num(); momp_get_thread_num()xy = 1; if(wy_isOk(m, x, y,omp_get_thread_num() wy_parallel_listOtherCol(m, y+1,omp_get_thread_num(); momp_get_thread_num()xy = 0; int _tmain(in
14、t argc, _TCHAR* argv) int mTHREADSQUEENSQUEENS; /* Parallel Part */ omp_set_num_threads(THREADS); clock_t t1 = clock(); for (int i = 0; i THREADS; i+) for (int j = 0; j QUEENS; j+) for (int z = 0; z QUEENS; z+) mijz = 0; wy_parallel_listFirstCol(m, 0); clock_t t2 = clock(); float pt = t2 - t1; print
15、f(N QUEEN : N = %dn,QUEENS); printf(Parallel Time = %fn,pt); /* Serial Part */ t1 = clock(); for (int i = 0; i THREADS; i+) for (int j = 0; j QUEENS; j+) for (int z = 0; z QUEENS; z+) mijz = 0; wy_serial_listAllCol(m, 0); t2 = clock(); float st = t2 - t1; printf(Serial Time = %fn,st); printf(相对加速比=
16、%fn,st/pt); getch(); return 0; 1.3.2 执行结果截图(体现串行时间、并行时间和加速比)(1)小数据量验证正确性的执行结果N = 12 Serial Time = 498 , Parallel Time= 1235相对加速比 = 2.479(2)大数据量获得较好加速比的执行结果N = 14 Serial Time = 20340 , Parallel Time = 41072相对加速比 = 2.0191.3.3 遇到的问题及解决方案(1)问题一错误代码及后果当数组m维数为2维时,无法避免其他线程对当前线程的影响,各线程存在数据竞争,无法准确的描述棋盘放置状态。正
17、确代码应将数组设置为3维,第1维为Thread维,避免多线程共同操作同一个棋盘,出现数据竞争。分析OpenMP和Intel的CPU兼容很好,所以加速比很理想。1.4 基于MPI的并行算法实现1.4.1 代码及注释(变量名 名字首字母 开头)/YTU Wang Yang 123-2 201258503222 MPI N-QUEEN #include stdafx.h #define QUEENS 8 /* QUEENS NUM */* 8 QUEENS HAVE 92 RES */ #define THREADS 2 /* THREADS TOTAL NUM */ /* * wy_isOk :
18、Check The Current Queen Site Validity * * param x * param y * return bool-value */ static bool wy_isOk(int mTHREADSQUEENSQUEENS,int x,int y,int thread) int tx,ty; /* Same row , return false */ for(ty = 0;ty = 0 & -ty = 0) if(mthreadtxty = 1)return false; /* Diagonal / , return false */ tx = x; ty =
19、y; while(+tx = 0) if(mthreadtxty = 1)return false; return true; /* * count : Current Count */ static int count = 1; /* * print : Print Current Finished Chess Table * * param m * param thread */ static void print(int mTHREADSQUEENSQUEENS,int thread) printf(%dn,count); count+; for(int i = 0 ; i QUEENS
20、 ; i+) for(int j = 0 ; j QUEENS ; j+) printf( %d,mthreadij); printf(n); /* * wy_serial_listAllCol : List All The Valid Chess Table In Serial Way * * param m * param y */ static void wy_serial_listAllCol(int mTHREADSQUEENSQUEENS , int y) for(int x = 0; x QUEENS; x+) m0xy = 1; if(wy_isOk(m, x, y,0) if
21、(y = QUEENS - 1) /print(m,0); else wy_serial_listAllCol(m, y+1); m0xy = 0; /* * wy_parallel_listOtherCol : Determine The Other Cols In Parallel Way * * param m * param y * param thread */ static void wy_parallel_listOtherCol(int mTHREADSQUEENSQUEENS , int y,int thread) for(int x = 0; x QUEENS; x+) m
22、threadxy = 1; if(wy_isOk(m, x, y,thread) if(y = QUEENS - 1) /print(m,thread); else wy_parallel_listOtherCol(m, y+1,thread); mthreadxy = 0; /* * wy_parallel_listFirstCol : Determine The First Col In Parallel Way * * param m * param y */ static void wy_parallel_listFirstCol(int mTHREADSQUEENSQUEENS ,
23、int y ,int thread) int floorLength = int(floor(double(QUEENS / 2) ); if(thread = 0) for (int x = 0 ; x floorLength ; x+) mthreadxy = 1; if (wy_isOk(m , x , y , thread) wy_parallel_listOtherCol(m , y+1 , thread); mthreadxy = 0; else for (int x = floorLength ; x QUEENS ; x+) mthreadxy = 1; if (wy_isOk
24、(m , x , y , thread) wy_parallel_listOtherCol(m , y+1 , thread); mthreadxy = 0; int _tmain(int argc, char* argv) int mTHREADSQUEENSQUEENS; /* Parallel Part */ int n = 0, done = 0; int thread , size; double t1 , t2; MPI_Init(&argc , &argv); /* Init MPI */ MPI_Comm_size(MPI_COMM_WORLD,&size); MPI_Comm
25、_rank(MPI_COMM_WORLD,&thread); for (int i = 0; i THREADS; i+) for (int j = 0; j QUEENS; j+) for (int z = 0; z QUEENS; z+) mijz = 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(); /* Finish MPI */ double pt = t2 - t1; printf(N QUEEN : N = %dn,QUEENS); printf(
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1