【操作系统实验】多线程结合蒙特卡罗法计算圆周率

实验目的:

通过多线程编程(C语言)实践进一步理解操作系统中线程这一概念,熟悉linux系统操作,培养节省计算资源的意识。

预期效果:

使用linux系统,在通过多线程编程减少资源消耗的情况下,较精准地计算出圆周率的值。

实验背景:

蒙特卡罗法:蒙特卡罗法也称统计模拟法、统计试验法。是把概率现象作为研究对象的数值模拟方法。是按抽样调查法求取统计值来推定未知特性量的计算方法。蒙特卡罗是摩纳哥的著名赌城,该法为表明其随机抽样的本质而命名。故适用于对离散系统进行计算仿真试验。在计算仿真中,通过构造一个和系统性能相近似的概率模型,并在数字计算机上进行随机试验,可以模拟系统的随机特性。(摘自百度百科)

蒙特卡洛法计算圆周率方法推导:

正方形面积公式为 (The\quad Length\quad of\quad an\quad Edge)^2

圆面积公式为 \pi(radius)^2

那么,对于一个正方形的内接圆来说,半径是正方形边长的\frac{\pi}{2},面积是其\frac{\pi}{4}

所以,如果我们在一个正方形内随机生成若干个点,生成的点落在其内接圆内的概率即可被估计为为\frac{\pi}{4}的值。

所以,我们可以写出计算圆周率的代码:

(实验环境为CentOS 7 64位)

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void calculate_pi(int times_root) {
    // 变量初始化
	unsigned int seed = time(NULL);

	int points_in_circle = 0;
	int points_in_square = 0;
	
    // 生成随机点并判断其是否落在内接圆内
	for (int i = 0; i < times_root*times_root; i++) {
		double x = (double)rand_r(&seed)/RAND_MAX;
		double y = (double)rand_r(&seed)/RAND_MAX;

		if ((x*x) + (y*y) <= 1){
			points_in_circle++;
		}
		points_in_square++;
	}
    
    // 输出结果
	double pi = (double)(4.0*points_in_circle)/points_in_square;
	printf("The estimated PI is %lf in %d times\n", pi, times_root*times_root);
}

int main() {
	calculate_pi(1000);

	return 0;
}

编译运行,测试成功。

实验思路:

如果我需要进行多次实验,以找出一个合理的\pi值,就需要调用多次这个函数。随着times_root参数的变大以及调用次数的增加,消耗时间会逐渐增加。

for (int i=1; i<9; i++) {
    calculate_pi(i*1000);
}

利用多线程,创建多个线程来执行计算,即可提升cpu时间利用率,从而提升计算效率。

所以最终的实验代码为:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>

// 计算圆周率函数(根据pthread线程函数要求定义)。
void* calculate_pi(void* args) {
		
	int times_root = *((int*)args);

	unsigned int seed = time(NULL);

	int points_in_circle = 0;
	int points_in_square = 0;
	
	for (int i = 0; i < times_root*times_root; i++) {
		double x = (double)rand_r(&seed)/RAND_MAX;
		double y = (double)rand_r(&seed)/RAND_MAX;

		if ((x*x) + (y*y) <= 1){
			points_in_circle++;
		}
		points_in_square++;
	}

	double pi = (double)(4.0*points_in_circle)/points_in_square;
	printf("The estimated PI is %lf in %d times\n", pi, times_root*times_root);
}

int main() {
	pthread_t calculate_pi_threads[8];
	int args[8];
	
	for (int i=1; i<9; i++) {
		args[i-1] = i*1000;
		pthread_create(calculate_pi_threads+i-1,NULL,calculate_pi,args+i-1);	
	}
	
	for (int i=0; i<8; i++) {
		pthread_join(calculate_pi_threads[i],NULL);	
	}

	return 0;
}

测试结果:

 可以看到实际运行时间为3.892秒,比直接在一个线程中执行代码要快很多。

本次实验的虚拟机配置仅有2个处理器内核,适当增加处理器内核可以进一步提升执行速度。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值