实验5 蒙特卡罗法求PI及排序算法

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

浙江大学城市学院实验报告

课程名称多核与并行程序设计

实验项目名称实验五蒙特卡罗法求PI及排序算法

学生姓名专业班级学号

实验成绩指导老师(签名)日期

【实验环境】

硬件平台:联想4核,4GZ内存

编译器:Microsoft Visual Studio C++ 6.0

操作系统:Windows 2003 server sp2

测试数据集合:由随机数函数产生的数据集合

【实验1】

一、问题描述

蒙特卡洛算法可理解为通过大量实验,模拟实际行为,来收集统计数据。本例中,算法随机产生一系列点,模拟这些点落在如下图所示的正方形区域内的情况。其几何解释如下

1

1

图1

如图1所示,正方形边长为1,左下顶点与原点重合,两边分别与x,y轴重合。曲线为1/4圆弧,圆心位于原点,与正方形左下定点重合,半径为1。正方形面积S1=1,圆弧内

面积S2=

π

π

4

1

4

1

2=

r。算法模拟大量点随机落在此正方形区域内,落在圆弧内的点

的数量(n2)与点的总数(n1)的比例与面积成正比关系。即

π42121==S S n n (1) 由此可得

124n n =π (2)

因此,只要计算出落在圆弧内的点的数量在点总数中所占的比例,就能求出π的值。 由图1可知,所有点均落在正方形范围内,因此点的x 坐标满足10≤≤x 。又,当点落在圆弧范围内,则点的二维坐标关系满足

122≤+y x 。检验每一个点是否满足此关系即可判定改点是否落在圆弧内。

二、串行算法描述

本项目中使用了标准C 语言库中的产生随机数函数。该函数原型为:

int rand( void );

此函数产生随机数列,每次调用时均返回0到RAND_MAX 之间的一个整数。

void srand( unsigned int seed );

此函数为rand ()函数所生成的伪随机数序列设置起始点,使之产生不同的伪随机数。 算法:

产生2n 个随机数据,范围[0,1],对每个数据点计算其坐标是否满足122≤+y x ,统计满足此关系的点的数量count ,则 n count

4=π

三、并行算法

3.1 并行算法描述

算法步骤:

1、确定需要产生的点的个数n ,参与运行的处理器数m ;

2、对每一个处理器,生成两个随机数x ,y ,范围[0,1];

3、判断两个随机数x ,y 是否满足12

2≤+y x ;

4、若满足,则变量COUNT i++;

5、重复步骤2-4,直至每个处理器均生成n/m个随机点;

6、收集COUNT i的值,并累加至变量COUNT中,此即为随机点落在圆弧内的数量;

7、通过(2)式计算 的值。

3.2 并行算法在Windows下的一个例子

#include

#include

#include

//#include

#include

#include

#include

using namespace std;

HANDLE evFinish;

long cs=0; //总循环次数

long count=0; //主线程有效次数

long count_thread=0; //thread线程有效次数

time_t start, finish; //定义开始结束时间

//thread线程计算量为总数的一半

DWORD WINAPI thread(LPVOID param) //这个函数在PDF里

WaitForSingleObject(evFinish,INFINITE);//两线程同步

count+=count_thread;

finish=time(NULL); //记录结束时间

printf("并行情况:\n\n");

printf("用时=%f 秒\n",difftime(finish,start)); //计算时间差printf("总共的循环次数=%d次\n",cs);

printf(" 线程有效次数=%d次\n",count);

printf("pi= %f \n",4*(double)count/(double)cs);

printf("串行行情况:\n");

count=0;

start=time(NULL); //记录开始时间

for(i=0;i

{

x=(long double)rand()/(long double)RAND_MAX;

y=(long double)rand()/(long double)RAND_MAX;

if((x*x+y*y)<=1)

count++;

// printf("主%d",i);

//printf("count%d",count);

}

finish=time(NULL); //记录结束时间

printf("用时=%f 秒\n",difftime(finish,start));

printf("总共的循环次数=%d次\n",cs);

printf(" 线程有效次数=%d次\n",count);

printf("pi= %f \n",4*(double)count/(double)cs);

return(0);

}

四、实验结果

1、实验运行结果是多少

2、本例中加速比(串行时间/并行时间):S=

【实验2】

一、问题描述

在单核计算环境中,排序算法关注的核心问题是怎样减少要排序数据之间的比较次数或算法所需要的内存空间。

在多核计算环境中,每个核以线程为执行单元,排序程序可以通过生成相互协作的线程来完成排序。与单核计算环境不同的是,在多核计算环境中更关注数据集的合理划分,更致力于识别可并行执行的任务。一旦完成这些工作,程序设计上就可以生成对应的线程去执行任务。理论上,基于相同的串行算法和相同的cache命中率,多核计算速度可以无限接近单核计算速度的P倍,其中P为核的数目。

多核上的并行排序算法所面临的问题在于:

1. 未排序的数据集合理划分到每个线程后,最后怎么汇合,形成完整的排好序的数据集呢?

2. 怎么保证可并行执行的线程的数目和核的数目相等或稍微多于核的数目,同时也保

证这些线程之间的工作量也尽可能的相同呢?

在这个实验中,串行的算法采用标准C语言库中的快速排序函数。

并行算法中,先将要处理的数据集均等的分到每个线程中,并使用C语言库中的快速排序函数各自排序。然后所有线程开始根据相同的数对自己的数据集进行划分,这个数是依据一定的方法选出来的(详见并行算法描述)。每个线程的数据集都会被分成K份,(其中P<= K < P2 ,P为核的数目),每份将被称为一桶。很显然这个过程选出了K个数,这些数将被成为bound_value, 记为X1, X2, X3…… X K。最后每个线程中小于或等于X1的数会被一个独立的线程去归并排序,同样小于或等于X2的数也会被另外一个独立的线程去归并排序,依次类推,直到排好序。

需要指出的是:这个并行版本最消耗时间的部分是一开始每个线程各自的排序,时间为:

n n);不过其数据划分和线程生成也相对简单。最后的归并排序所需时间是线性增O(log

长的,即:O(n),因此即使在最后归并部分线程执行的任务已经是不均衡的,也不会对整个程序的性能产生很大的影响。

相关文档
最新文档