并行计算最短路径算法(操作系统课程设计)

要解决的问题

在这里插入图片描述

代码段

1.生成矩阵模块

#include "stdafx.h"
#include <stdlib.h>
#include <time.h>
#include <fstream.h>
#define Size 2000

int aMatrix[Size][Size];

int createMatrix()
{
	int i,j;
	srand(time(NULL));
	fstream fs;
	fs.open("Matrix2000.txt",ios::out);
	for(i=0;i<Size;i++)
	{
		for(j=0;j<Size;j++)
		{
			if(i==j)
			{
				aMatrix[i][j]=0;
			}
			else
			{
				aMatrix[i][j]=30+rand()%71;//1+rand()%100;
			}
		}
	}
	for(i=0;i<Size;i++)
	{
		for(j=0;j<i;j++)
		{
			aMatrix[i][j]=aMatrix[j][i];
		}
	}
	for(i=0;i<Size;i++)
	{
		for(j=0;j<Size;j++)
		{
			fs<<aMatrix[i][j]<<' ';
		}
	}
	fs.close();
	return 1;
}

int main(int argc, char* argv[])
{
	createMatrix();
	printf("OK!\n");	
	return 0;
}


2.主程序模块

#include <fstream.h>
#include <windows.h>
#include <stdio.h>
#include <process.h>
#include <string.h>
#include "stdafx.h"
#include <stdlib.h>
#include <time.h>


#define Size 2000
#define Threadnum 10//×î´óÏß³ÌÊý ÓÃÓÚ³õʼ»¯
#define Inf 1000000 

int xcs;//Óû§ÊäÈëµÄÏß³ÌÊý
int c1,c2;//c1,c2״̬

HANDLE hMutex;
struct ProcParam {
	int qidian;//ÿ´ÎÕÒµÄÆðµã
	int zhongdian;//ÿ´ÎÕÒµÄ×îºóÒ»¸öÊý
	int threadid;//Ïß³Ìid
	int *qbook;//´«bookÊý×éµÄÖ¸Õë
	int *qdst;//´«dstÊý×éµÄÖ¸Õë
	int *qmin;//´«jubuminµÄÖ¸Õë
	int pos;//¼Ç¼×îСֵµÄ×ø±ê
	int *qroute;//´«Â·¾¶routeÊý×éµÄÖ¸Õë
	int condition;//
	int *qtm;//
};


struct ProcParam2 {
	int start;
	int end;
	int sumtime;
	int zt;
};

int **aMatrix=new int *[Size];//´´½¨¾ØÕó
int readMatrix()
{
	int i,j;
	// ´´½¨¶¯Ì¬¶þάÊý×éaMatrix
	for(i=0;i<Size;i++)
	{
		aMatrix[i]=new int [Size];
	}
	fstream fs;
	fs.open("Matrix2000.txt",ios::in); //´ò¿ªÎļþmatrix.txt£¬¶ÁÈëÊý¾Ý
	for(i=0;i<Size;i++)
	{
		for(j=0;j<Size;j++)
		{
			fs>>aMatrix[i][j];
		}
	}
	fs.close();
 	return 1;
}

void time_Qiu(int *qiutime)//Çóʱ¼ä
{
	int t=0;
	for(int i=1;i<=xcs;i++)
	{
		printf("Ïß³Ì%d:¿ªÊ¼ÓÚ%d£¬½áÊøÓÚ%d,¹²ÓÃʱ¼äΪ%dms\n",i,qiutime[(i-1)*2+0],qiutime[(i-1)*2+1],qiutime[(i-1)*2+1]-qiutime[(i-1)*2+0]);
		qiutime[(i-1)*2+1]-qiutime[(i-1)*2+0]>t?(t=qiutime[(i-1)*2+1]-qiutime[(i-1)*2+0]):t;
	}
	printf("T=max{");
	for(i=1;i<=xcs;i++)
	{
		printf("t%d ",i);
	}
	printf("}=%dms\n",t);

}

unsigned __stdcall biJiao(void * arg)
{
	ProcParam *param;
	param = (ProcParam*)arg;
	if(param->condition==1) param->qtm[(param->threadid*2)+0]=GetTickCount();
	int min=Inf+1;//Èç¹û³öÏÖ¶¼ÊÇÎÞÇî¡£¡£´ý¶¨
	int pos;//ÊÇ·ñÒª¸³³õÖµ -1ÔõôÑù£¿
	for(int j=param->qidian;j<param->zhongdian;j++)
	{
		if(param->qbook[j] == 0 && param->qdst[j] < min)
		{  
			min = param->qdst[j];  
			pos=j;
		}  
	}
	param->qmin[param->threadid]=min;
	param->pos=pos;
	param->qtm[(param->threadid*2)+1]=GetTickCount();

    return 0;
}


int minFind(int *book,int *dst,int dyc,int *qiutime)//dycµÚÒ»´Î
{
	//int xcs=Threadnum;// ·ÖÅäµÄÏ̸߳öÊý
	int eachfind=Size/xcs;//ÿ¸öÏß³ÌËù×ö¸öÊý
	HANDLE hThread[Threadnum]; //HANDLE³ÆΪ¾ä±ú£¬±¾ÖÊÊÇÒ»¸ö×ÊÔ´µÄID±êʶ·û
	unsigned threadID[Threadnum];
	ProcParam *param=new ProcParam[Threadnum];
	int jubuMin[Threadnum];//¾Ö²¿×îСֵÊý×é
	for(int i=0;i<xcs;i++)//Êý×é³õʼ»¯Îª×î´óÖµ¡£
	{
		jubuMin[i]=Inf;
	}
	
	for(i=0;i<xcs;i++)
	{
		param[i].qtm=qiutime;
		param[i].condition=dyc;//ÅжÏÊÇ·ñÊǵÚÒ»´Î
		param[i].qmin=jubuMin;
		param[i].qbook=book;
		param[i].qdst=dst;
		param[i].qidian=0+eachfind*i;//Æðµã
		if(i!=xcs-1)
		{
			param[i].zhongdian=param[i].qidian+eachfind;//ÖÕµã
		}
		else
		{
			param[i].zhongdian=Size;
		}
		param[i].threadid=i;
		hThread[i] = (HANDLE)_beginthreadex(NULL, 0, biJiao, (void*)&param[i], 0, &threadID[i]);
	}
	WaitForMultipleObjects(xcs,hThread,TRUE,INFINITE);//µÈ´ýËùÓоä±ú¶¼Íê³ÉÔٱȽÏÆäÖеÄ×îСֵ  ÆäÖÐÏß³ÌÊýÒªÉ趨
	for(i=0;i<xcs;i++)
	{
		CloseHandle(hThread[i]);// ¹Ø±ÕÕâ¸öÏ̶߳ÔÓ¦µÄ¾ä±ú£¬ÊÍ·Å×ÊÔ´
	}
	int pos;//×îСֵËùÔÚµÄλÖÃ
	int minReal=Inf;//ËùÓоֲ¿×îСֵÖеÄ×îСֵ
	for(int j=0;j<xcs;j++)
	{
		if(jubuMin[j]<minReal)
		{
			minReal=jubuMin[j];
			pos=param[j].pos;
		}
	}
	return pos;
}

unsigned __stdcall refresh(void * arg)
{
	ProcParam *param;
	param = (ProcParam*)arg;
	for(int k=param->qidian;k<(param->zhongdian);k++)
	{
		if((param->qdst[k] > param->qdst[param->pos] + aMatrix[param->pos][k]) && param->qbook[k] == 0)
		{ 
			param->qroute[k]=param->pos;
			param->qdst[k] = param->qdst[param->pos] + aMatrix[param->pos][k];
			
		}    
	}
    return 0;
}
int printroute(int *route,int end,int start,int dst)
{
	int newroute[Size];//ÕýÐòµÄ·¾¶
	char str[Size]="";//¼Ç¼·¾¶µÄ×Ö·û´®
	int i=0;
	printf("v%d->v%dµÄ×î¶Ì·¾¶ÊÇ:\n",end,start);
	fstream fs;
	fs.open("print.txt",ios::app);//ÒÑ×·¼Ó·½Ê½´ò¿ª£¬ÈôÊÇios::out¾Í»áÖØдtxt
	fs<<"v"<<end<<"->"<<"v"<<start<<"×î¶Ì·¾¶ÊÇ£º"<<endl;
	
	while(route[end]!=-1)
	{
		newroute[i]=end;
		end=route[end];
		i++;
	}
	newroute[i]=end;
	if(end!=start)  
	{
		i++;
		newroute[i]=start;
	}
	

	for(int k=0;k<=i;k++)
	{
		if(k==i)
		{
			printf("v%d\n",newroute[k]);
			fs<<"v"<<newroute[k]<<endl;
		}
		else
		{
			printf("v%d->",newroute[k]);
			fs<<"v"<<newroute[k]<<"->";
		}
	}
	printf("¾àÀëΪ£º%d\n",dst);
	fs<<"¾àÀëΪ£º"<<dst<<endl;
	fs<<"      "<<endl;
	fs.close();
	return 1;
}

int reshuffle(int *book,int *dst,int &pos,int start,int end,int *route)//ºÃÏñÕâÀï²»ÓüÓ&
{
	//int xcs=Threadnum;
	int eachfind=Size/xcs;//ÿ¸öÏß³ÌËù×öµÄ¸öÊý

	HANDLE hThread[Threadnum]; //HANDLE³ÆΪ¾ä±ú£¬±¾ÖÊÊÇÒ»¸ö×ÊÔ´µÄID±êʶ·û
	unsigned threadID[Threadnum];
	ProcParam *param=new ProcParam[Threadnum];
	for(int i=0;i<xcs;i++)
	{
		param[i].qroute=route;
		param[i].qbook=book;
		param[i].qdst=dst;
		param[i].qidian=0+eachfind*i;//Æðµã
		if(i!=xcs-1)
		{
			param[i].zhongdian=param[i].qidian+eachfind;//ÖÕµã
		}
		else
		{
			param[i].zhongdian=Size;
		}
		param[i].pos=pos;
		param[i].threadid=i;
		hThread[i] = (HANDLE)_beginthreadex(NULL, 0, refresh, (void*)&param[i], 0, &threadID[i]);
	}
	WaitForMultipleObjects(xcs,hThread,TRUE,INFINITE);//µÈ´ýËùÓоä±ú¶¼Íê³ÉÔٱȽÏÆäÖеÄ×îСֵ  ÆäÖÐÏß³ÌÊýÒªÉ趨
	for(i=0;i<xcs;i++)
	{
		CloseHandle(hThread[i]);// ¹Ø±ÕÕâ¸öÏ̶߳ÔÓ¦µÄ¾ä±ú£¬ÊÍ·Å×ÊÔ´
	}
	return 0;
}



void dijkstra(int *book,int *dst,int start,int end,int &time,int option)//option 0´òӡ·¾¶  option1²»´òӡ·¾¶
{
	int qiutime[1000];//ÇóÒ»ÂÖÖеĸ÷¸ö²¿·Öʱ¼ä
	DWORD st,et;//starttime endtime
	st=GetTickCount();
	int i;
	for(i=0;i<Size;i++)
	{
		book[i]=0;
		dst[i]=aMatrix[start][i];
	}
	printf("\n");
	book[start]=1;
	int route[Size];
	for(i=0;i<Size;i++)
	{
		route[i]=-1;   //ÒòΪ³õʼËùÓнڵ㶼ԴÓÚstart£¬²»ÄÜÖ»ÊÇroute[start]=-1
	}

	for(i = 1; i < Size; i++)
	{
		int t=minFind(book,dst,i,qiutime);//×îСֵ×ø±ê
		book[t]=1;
		if(t==end)break;//²»ÓÃÈ«²¿±éÀúÕÒµ½¼´¿É
		reshuffle(book,dst,t,start,end,route);//startÆðµãendÖÕµãÊÇΪÁËÇ󷾶  route¼Ç¼µÚn¸ö½ÚµãµÄÇ°Ò»¸ö½ÚµãÊÇʲô
	}
	et=GetTickCount();
	time=et-st;
	if(!option)
	{
		printroute(route,end,start,dst[end]);//´òӡ·¾¶ºÍ·¾¶³¤¶È
		time_Qiu(qiutime);
	}

}

int jiexi(char *a,int size,int &start,int &end)//½âÎö×Ö·û´®£¬¶ÁÈ¡ÆäÖеÄÆðµãºÍÖÕµã
{
	int temp=-1,d=1,t=0;//temp=-1ÓÐv0
	for(int i=size-1;i>=0;i--)
	{
		if(48<=a[i]&&a[i]<=57)
		{
			if(48<=a[i+1]&&a[i]<=57)
			{
				d*=10;
			}
			else
			{
				d=1;
				t++;
				temp=0;
			}
			temp+=(a[i]-48)*d;
		}
		else
		{
			if(temp>-1)
			{
				if(t==1)
				{
					start=temp;
					temp=-1;
				}
				if(t==2)
				{
					end=temp;
				}
			}
		}
	}
	return 1;
}

int input(int *qi_zhong)
{
	FILE* f1=fopen("Input.txt","r");
	if(!f1) return 0;
	char buf[1024]={0};
	int mount=0;//¼Ç¼¹²ÓжàÉÙ¸öÆðÖÕµã
	while(!feof(f1))
	{
		int start,end;
		memset(buf, 0, sizeof(buf));//Çå¿Õ»º³åÇø
		fscanf(f1, "%s", buf);//´ÓÎļþÖжÁÈ¡Ò»¶ÎÊý¾Ý´æÈ뻺³åÇø
		jiexi(buf,strlen(buf),start,end);
		qi_zhong[mount++]=start;
		qi_zhong[mount++]=end;
	}
	fclose(f1);	
	return mount;
}

void thread_Time()
{
	for(xcs=2;xcs<11;xcs++)
	{
		int time,time_sum=0;
		int qi_zhong[100];//¼Ç¼ÆðÖÕµãµÄÊý×é
		int mount=input(qi_zhong);
		if(mount)
		{
			for(int i=0;i<mount/2;i++)
			{		
				int book[Size];
				int dst[Size];
				int start=qi_zhong[2*i];
				int end=qi_zhong[2*i+1];
				dijkstra(book,dst,start,end,time,1);
				time_sum+=time;
			}
		}
		printf("%d¸öỊ̈߳º%dms\n",xcs,time_sum);
		fstream fs;
		fs.open("time.txt",ios::app);//ios::out¾Í»áÖØдtxt
		fs<<xcs<<"¸öỊ̈߳º"<<time_sum<<endl;
		fs.close();
	}
}

unsigned __stdcall bXing(void * arg)
{
	ProcParam2 *param2;
	param2=(ProcParam2*)arg;
	int qi_zhong[100];//¼Ç¼ÆðÖÕµãµÄÊý×é
	input(qi_zhong);
	int time=0;
	for(int i=param2->start;i<param2->end;i++)
	{
		int book[Size];
		int dst[Size];
		dijkstra(book,dst,qi_zhong[2*i],qi_zhong[2*i+1],time,0);
		param2->sumtime+=time;
	}
	return 0;
}
void double_Find()
{
	HANDLE hThread[2];
	unsigned threadID[2];
	ProcParam2 *param2=new ProcParam2[2];
	int qi_zhong[100];//¼Ç¼ÆðÖÕµãµÄÊý×é
	int mount=input(qi_zhong);
	int n=mount/2;//¼¸¶ÔÆðÖÕµã
	int k=n/2;
	if(readMatrix())
	{
		for(int i=0;i<2;i++)
		{
			param2[i].start=0+i*k;
			param2[i].sumtime=0;
			if(i!=1)
			{
				param2[i].end=param2[i].start+k;
			}
			else
			{
				param2[i].end=n;
			}
			hThread[i] = (HANDLE)_beginthreadex(NULL, 0, bXing, (void*)&param2[i], 0, &threadID[i]);
		}
		WaitForMultipleObjects(2,hThread,TRUE,INFINITE);
		CloseHandle(hThread[0]);CloseHandle(hThread[1]);
		printf("Ëã·¨¹²ÓÃ=%dms\n",param2[0].sumtime+param2[1].sumtime);
	}
}

int chaxun()
{
	printf("****       ÇëÊäÈëÊ×Ä©½ÚµãºÅ         ****\n");
	int a,b;
	int start,end;
	scanf("%d %d",&a,&b);
	FILE* f1=fopen("print.txt","r");
	if(!f1) return 0;
	char buf[1024]={0};
	while(!feof(f1))
	{
		memset(buf, 0, sizeof(buf));//Çå¿Õ»º³åÇø
		fscanf(f1, "%s", buf);//´ÓÎļþÖжÁÈ¡Ò»¶ÎÊý¾Ý´æÈ뻺³åÇø
		jiexi(buf,strlen(buf),start,end);
		if(start==b&&end==a)
		{
			for(int i=0;i<strlen(buf);i++)
			{
				printf("%c",buf[i]);
			}
			printf("\n");
			memset(buf, 0, sizeof(buf));//Çå¿Õ»º³åÇø
			fscanf(f1, "%s", buf);
			for(i=0;i<strlen(buf);i++)
			{
				printf("%c",buf[i]);
			}
			printf("\n");
			memset(buf, 0, sizeof(buf));//Çå¿Õ»º³åÇø
			fscanf(f1, "%s", buf);
			for(i=0;i<strlen(buf);i++)
			{
				printf("%c",buf[i]);
			}
			printf("\n");
			return 1;
		}
		
	}
	printf("ÕÒ²»µ½\n");
	fclose(f1);	
}


void main()
{
	while(1)
	{
		printf("***************************************\n");
		printf("****        ²âÊÔÇëÊäÈë1            ****\n");
		printf("****        ͳ¼ÆÇëÊäÈë2            ****\n");
		printf("****        ²éѯÇëÊäÈë3            ****\n");
		printf("***************************************\n");
		int option;
		scanf("%d",&option);
		system("cls");
		switch(option)
		{
		case 1:
			printf("***************************************\n");
			printf("****        ÇëÊäÈëÏß³ÌÊý           ****\n");
			printf("***************************************\n");
			scanf("%d",&xcs);
			double_Find();break;
		case 2:thread_Time();break;
		case 3:chaxun();break;
		default:printf("ÇëÊäÈëÕýÈ·µÄÊý\n");
		}			
	getchar();
	}
}

3.输入模块

//input.txt
v8->v10
v231->v32
v342->v1034
v986->v128
v86->v1234

实验分析

在这里插入图片描述

1. 设计目的、意义(功能描述) 蒙特·卡罗方法(Monte Carlo method),也称统计模拟方法,是二十世纪四十年代中期由于科学技术的发展和电子计算机的发明,而被提出的一种以概率统计理论为指导的一类非常重要的数值计算方法。本次大作业主要是对蒙特·卡罗方法进行并行处理,通过OpenMP、MPI、.NET、Java、Win32API等一系列并行技术和并行机制对该算法进行并行处理,从而也进一步熟悉了蒙特·卡罗方法的串行算法和并行算法,实现了用蒙特·卡罗方法计算出半径为1单位的球体的体积,体会到了并行技术在实际生活中的应用。 2. 方案分析(解决方案) 蒙特·卡罗方法(Monte Carlo method)是指使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。球的体积可以估算为:位于点模型内随机点个数与全体随机点个数的比值乘以包围盒的体积算的。 3. 设计分析 3.1 串行算法设计 假定球体用B表示,半径r=1单位,B1是包含B的参考立方体(在本例中是边长为2的正方体),在B1中产生N个均匀分布的伪随机点。对每个随机点检测其是否在B内,假设位于B内的随机点个数为N(in)(<=N),应用蒙特卡洛算法,则B的体积为 V=V1(N(in)/N) 其中V1是B1的体积。如果产生足够多的随机点,理论上可以获得任意逼近精度。 算法描述如下: BEGIN N=_MAX; FOR I=0;I<_MAX;I++ X=RANDOM(); Y=RANDOM(); Z=RANDOM(); IF (X*X+Y*Y+Z*Z)<=1 COUNT++; END IF; END FOR; BULK=V1*(COUNT/_MAX); END; 本算法主要是在参考立方体的选取上和定义的_MAX的值对结果影响较大,所以应该选择合适的数。 3.2 并行算法设计 对FOR循环进行划分使用两个处理器完成计算。例如对一个长为n的序列,首先划分得到两个长为n/2的序列,将其交给两个处理器分别处理;而后进一步划分得到四个长为n/4的序列,再分别交给四个处理器处理;如此递归下去最终得到结果。当然这是理想的划分情况,如果划分步骤不能达到平均分配的目的,那么结果的效率会相对较差。 伪代码如下: BEGIN N=_MAX; FOR1 I=0;I<_MAX/2;I++ X1=RANDOM(); Y1=RANDOM(); Z1=RANDOM(); IF (X1*X1+Y1*Y1+Z1*Z1)<=1 COUNT1++; END IF; END FOR1; FOR2 I=_MAX/2+1;I<_MAX;I++ X2=RANDOM(); Y2=RANDOM(); Z2=RANDOM(); IF (X2*X2+Y2*Y2+Z2*Z2)<=1 COUNT2++; END IF; END FOR2; BULK=V1*((COUNT1+ COUNT2)/_MAX); END; 3.3 理论加速比分析 实验中大量数据所产生的加速比比小量数据所产生的加速比要体现得更明显,并且数据生成的并行加速比随着处理器核的增加而增加。设处理器个数为p,数据量为n,由于正常情况下该快速排序算法的复杂度为O(nlogn),并行处理的时间复杂度为O(klogk),其中k=n/p,所以并行算法的时间复杂度为O((n/p)log(n/p)),理论加速比为nlogn/((n/p)log(n/p))=p+logp. 4. 功能模块实现与最终结果分析 4.1 基于OpenMP的并行算法实现 4.1.1 主要功能模块与实现方法 利用了OpenMP里面的#omp parallel sections将对两个for循环用两个线程并行化执行,以多线程方式并行运行程序,并行的算法步骤如下: (1)初始化_max = 10000000; (2)创建两个线程; (3)由OpenMP编译指导语句控制产生并行执行代码区段; (4)将数据存放到tianqing_count; (5)各线程调用算法得出结果; 并行算法的部分代码如下: #pragma omp parallel for private(tianqing_x,tianqing_y,tianqing_z) reduction(+:tianqing_count2) for (tianqing_i = 0; tianqing_i<tianqing_max; tianqing_i++) { tianqing_x = rand(); tianqing_x = tianqing_x / 32767; tianqing_y = rand(); tianqing_y = tianqing_y / 32767; tianqing_z = rand(); tianqing_z = tianqing_z / 32767; if ((tianqing_x*tianqing_x + tianqing_y*tianqing_y + tianqing_z*tianqing_z) work1.pSumto(b, 0, MAXN - 1)); Thread newthread1 = new Thread(thread1); 创建Work类的对象work2; ThreadStart thread2 = new ThreadStart(() => work2.pSumto(c, 0, MAXN - 1)); Thread newthread2 = new Thread(thread2); stopwatch.Start(); 启动线程1和线程2; 等待进程结束; stopwatch.Stop(); 得到结果; 4.5.2 实验加速比分析 实验中创建了两个线程,通过多次测试,得出实验结果:由上面的理论加速比分析可知,当线程数为2时,理论加速比为2+log2=3.但由于实际操作中硬件设备以及内存分配的影响,实验加速比达不到理论值3.实验加速比在2.6~2.7左右。 4.6 并行计算技术在实际系统中的应用 4.6.1 主要功能模块与实现方法 该飞机订票系统主要实现了对机票的一些基本信息进行存储和管理的功能。在系统中实现了对机票信息的增删改查,考虑到查询的方便性,对机票按照航班号进行排序,而此排序方法用并行快速排序运用进来。利用OpenMP的并行技术,对机票信息按顺序排列好,并分析了实验过程中的加速比。 4.6.2 实验加速比分析 实验中创建了两个线程,通过多次测试,得出实验结果:当数据量比较大时,加速比理论在1.9左右。数据量较大时体现出来的加速比更准确。由上面的理论加速比分析可知,当线程数为2时,理论加速比为2+log2=3.但由于实际操作中硬件设备以及内存分配的影响,实验加速比达不到理论值3.实验加速比在2.2~2.4左右。 5. 设计体会 虽然没有按时完成作业,但这份报告花了我好几天的时间,从开始的搭建并行计算平台到最后的程序运行成功可以说是对我的一个锻炼。每一次的遇到问题与每一次的解决问题都是一个成长。每一次遇到问题和解决问题都是一种锻炼,一种尝试,从我们上并行计算课我懂得了很多电脑硬件和软件的知识,这些可能对于我们这个专业以后都是没有机会接触的,所以我觉得选择了并行计算与多核多线程技术这门课是非常正确的。对OpenMP、MPI、WIN32API、Java、.NET的并行技术有了一定的了解。在搭建MPI并行程序这块,学习的知识尤为增加,这些都是在不断的摸索、学习中学会的。 这次的大作业虽然是对以前实验的整合,但它加深了我对并行计算的印象,也使我对并行计算知识的理解更加深刻,也使我认识到了自己很多不足之处。学习并行计算的历程不会因为完成本次大作业而停止,我们是为了用知识武装大脑而学习,通过学习充实自己的生活,要努力学习,争取以后能够完成规模更大的程序。
1. 设计目的、意义(功能描述) 蒙特·卡罗方法(Monte Carlo method),也称统计模拟方法,是二十世纪四十年代中期由于科学技术的发展和电子计算机的发明,而被提出的一种以概率统计理论为指导的一类非常重要的数值计算方法。本次大作业主要是对蒙特·卡罗方法进行并行处理,通过OpenMP、MPI、.NET、Java、Win32API等一系列并行技术和并行机制对该算法进行并行处理,从而也进一步熟悉了蒙特·卡罗方法的串行算法和并行算法,实现了用蒙特·卡罗方法计算出半径为1单位的球体的体积,体会到了并行技术在实际生活中的应用。 2. 方案分析(解决方案) 蒙特·卡罗方法(Monte Carlo method)是指使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。球的体积可以估算为:位于点模型内随机点个数与全体随机点个数的比值乘以包围盒的体积算的。 3. 设计分析 3.1 串行算法设计 假定球体用B表示,半径r=1单位,B1是包含B的参考立方体(在本例中是边长为2的正方体),在B1中产生N个均匀分布的伪随机点。对每个随机点检测其是否在B内,假设位于B内的随机点个数为N(in)(<=N),应用蒙特卡洛算法,则B的体积为 V=V1(N(in)/N) 其中V1是B1的体积。如果产生足够多的随机点,理论上可以获得任意逼近精度。 算法描述如下: BEGIN N=_MAX; FOR I=0;I<_MAX;I++ X=RANDOM(); Y=RANDOM(); Z=RANDOM(); IF (X*X+Y*Y+Z*Z)<=1 COUNT++; END IF; END FOR; BULK=V1*(COUNT/_MAX); END; 本算法主要是在参考立方体的选取上和定义的_MAX的值对结果影响较大,所以应该选择合适的数。 3.2 并行算法设计 对FOR循环进行划分使用两个处理器完成计算。例如对一个长为n的序列,首先划分得到两个长为n/2的序列,将其交给两个处理器分别处理;而后进一步划分得到四个长为n/4的序列,再分别交给四个处理器处理;如此递归下去最终得到结果。当然这是理想的划分情况,如果划分步骤不能达到平均分配的目的,那么结果的效率会相对较差。 伪代码如下: BEGIN N=_MAX; FOR1 I=0;I<_MAX/2;I++ X1=RANDOM(); Y1=RANDOM(); Z1=RANDOM(); IF (X1*X1+Y1*Y1+Z1*Z1)<=1 COUNT1++; END IF; END FOR1; FOR2 I=_MAX/2+1;I<_MAX;I++ X2=RANDOM(); Y2=RANDOM(); Z2=RANDOM(); IF (X2*X2+Y2*Y2+Z2*Z2)<=1 COUNT2++; END IF; END FOR2; BULK=V1*((COUNT1+ COUNT2)/_MAX); END; 3.3 理论加速比分析 实验中大量数据所产生的加速比比小量数据所产生的加速比要体现得更明显,并且数据生成的并行加速比随着处理器核的增加而增加。设处理器个数为p,数据量为n,由于正常情况下该快速排序算法的复杂度为O(nlogn),并行处理的时间复杂度为O(klogk),其中k=n/p,所以并行算法的时间复杂度为O((n/p)log(n/p)),理论加速比为nlogn/((n/p)log(n/p))=p+logp. 4. 功能模块实现与最终结果分析 4.1 基于OpenMP的并行算法实现 4.1.1 主要功能模块与实现方法 利用了OpenMP里面的#omp parallel sections将对两个for循环用两个线程并行化执行,以多线程方式并行运行程序,并行的算法步骤如下: (1)初始化_max = 10000000; (2)创建两个线程; (3)由OpenMP编译指导语句控制产生并行执行代码区段; (4)将数据存放到tianqing_count; (5)各线程调用算法得出结果; 并行算法的部分代码如下: #pragma omp parallel for private(tianqing_x,tianqing_y,tianqing_z) reduction(+:tianqing_count2) for (tianqing_i = 0; tianqing_i<tianqing_max; tianqing_i++) { tianqing_x = rand(); tianqing_x = tianqing_x / 32767; tianqing_y = rand(); tianqing_y = tianqing_y / 32767; tianqing_z = rand(); tianqing_z = tianqing_z / 32767; if ((tianqing_x*tianqing_x + tianqing_y*tianqing_y + tianqing_z*tianqing_z) work1.pSumto(b, 0, MAXN - 1)); Thread newthread1 = new Thread(thread1); 创建Work类的对象work2; ThreadStart thread2 = new ThreadStart(() => work2.pSumto(c, 0, MAXN - 1)); Thread newthread2 = new Thread(thread2); stopwatch.Start(); 启动线程1和线程2; 等待进程结束; stopwatch.Stop(); 得到结果; 4.5.2 实验加速比分析 实验中创建了两个线程,通过多次测试,得出实验结果:由上面的理论加速比分析可知,当线程数为2时,理论加速比为2+log2=3.但由于实际操作中硬件设备以及内存分配的影响,实验加速比达不到理论值3.实验加速比在2.6~2.7左右。 4.6 并行计算技术在实际系统中的应用 4.6.1 主要功能模块与实现方法 该飞机订票系统主要实现了对机票的一些基本信息进行存储和管理的功能。在系统中实现了对机票信息的增删改查,考虑到查询的方便性,对机票按照航班号进行排序,而此排序方法用并行快速排序运用进来。利用OpenMP的并行技术,对机票信息按顺序排列好,并分析了实验过程中的加速比。 4.6.2 实验加速比分析 实验中创建了两个线程,通过多次测试,得出实验结果:当数据量比较大时,加速比理论在1.9左右。数据量较大时体现出来的加速比更准确。由上面的理论加速比分析可知,当线程数为2时,理论加速比为2+log2=3.但由于实际操作中硬件设备以及内存分配的影响,实验加速比达不到理论值3.实验加速比在2.2~2.4左右。 5. 设计体会 虽然没有按时完成作业,但这份报告花了我好几天的时间,从开始的搭建并行计算平台到最后的程序运行成功可以说是对我的一个锻炼。每一次的遇到问题与每一次的解决问题都是一个成长。每一次遇到问题和解决问题都是一种锻炼,一种尝试,从我们上并行计算课我懂得了很多电脑硬件和软件的知识,这些可能对于我们这个专业以后都是没有机会接触的,所以我觉得选择了并行计算与多核多线程技术这门课是非常正确的。对OpenMP、MPI、WIN32API、Java、.NET的并行技术有了一定的了解。在搭建MPI并行程序这块,学习的知识尤为增加,这些都是在不断的摸索、学习中学会的。 这次的大作业虽然是对以前实验的整合,但它加深了我对并行计算的印象,也使我对并行计算知识的理解更加深刻,也使我认识到了自己很多不足之处。学习并行计算的历程不会因为完成本次大作业而停止,我们是为了用知识武装大脑而学习,通过学习充实自己的生活,要努力学习,争取以后能够完成规模更大的程序。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值