MPI对道路车辆情况的Nagel-Schreckenberg 模型进行蒙特卡洛模拟

平台Ubuntu 16.04,Linux下MPI环境的安装见链接:https://blog.csdn.net/lusongno1/article/details/61709460

Nagel-Schreckenberg 模型,车辆的运动满足以下规则:

1.   假设当前速度是 v ,和前一辆车的距离为d。

2.   如果 d > v,它在下一秒的速度会提高到 v + 1 ,直到达到规定的最高限速。

3.   如果 d <= v,那么它在下一秒的速度会降低到 d - 1 。

4.   前三条完成后,司机还会以概率 p 随机减速1个单位,速度不会为负值。

5.   基于以上几点,车辆向前移动v(这里的v已经被更新)个单位。

实验规模:

  1. 车辆数量为100 000,模拟2000个周期后的道路情况。
  2. 车辆数量为 500 000 模拟 500个周期后的道路情况。
  3. 车辆数量为 1 000 000 ,模拟300个周期后的道路情况。

实验设计:

初始化条件:

所有车辆初速度为4,车辆间距为8,最大速度为8,最小速度为1,最后一辆车的位置是0。减速概率为0.3

车辆结构体:

typedef struct car{int v;int d;int p;
}car;

所有车辆为一个数组car_list

核心循环:

//更新距离
car_list[i].d=car_list[i+1].p-car_list[i].p;//依赖于前一辆车
//更新速度
if(car_list[i].d>car_list[i].v&& car_list[i].v<vmax)car_list[i].v++;//加速
if(car_list[i].d<=car_list[i].v)car_list[i].v=car_list[i].d-1;//减速
if(car_list[i].v>1 && rand()%10< p )car_list[i].v--;//随机减速
//更新位置
car_list[i].p+=car_list[i].v;

对这段程序进行周期次数的循环

并行设计:

在每个周期中,按照核心数(0…N-1)将车辆分为N个连续的区间,每个核心计算各自的部分。

i=(num_car/numprocs*myid);//指向这个集合的第一个元素

除第一个核心外其他的进程K都需要在更新自己的车辆部分之前发送第一辆车的位置到进程K-1,除最后一个进程外的其他进程K都要在计算自己部分的最后一辆车时接受进程K+1发送的位置数据以更新最后一辆车。

为避免标准通信方式导致后面的进程要等待前面的进程执行到最后开始接受的时候才执行完发送,采用缓存通信方式(MPI_Bsend)。

if(myid!=0){//如果不是第一个线程就要向前发送数据		MPI_Bsend(&(car_list[i].p),1,MPI_INT,myid-1,myid,MPI_COMM_WORLD);
}
//核心循环if(myid!=numprocs-1){//不是最后一个进程MPI_Recv(&(temp),1,MPI_INT,myid+1,myid+1,MPI_COMM_WORLD,&status);//更新距离car_list[i].d=temp-car_list[i].p;	
}

在周期结束之前要同步所有进程。

MPI_Barrier(MPI_COMM_WORLD);

输出结果:

只在四线程执行时输出到文件,将每个进程自己部分的车辆数据发送到第一个进程,第一个进程接收其它进程的数据整合后输出,并进行统计。

车辆的信息输出到result.txt中,格式为 进行输出的线程号 第几辆车:速度 位置 和前一辆车的距离

统计输出到statistic.txt中,前面输出的是速度统计,对应的速度有几辆车 。后面是位置统计,在位置范围有几辆车

结果分析:




可见不管哪种规模都会有大量的车处于速度为1的状态,随机减速会导致堵车情况。

运行时间分析:

10000

rank=0time:12.911823

rank=1time:12.937384

rank=2time:12.968312

rank=3time:12.837026

100000

rank=0time:127.054991

rank=1time:127.597898

rank=2time:127.428670

rank=3time:127.302298

 

rank=0time:169.043639

rank=1time:169.092520

rank=2time:169.038982

 

rank=0time:137.758731

rank=1time:137.782351

 

rank=0time:255.181992

500000

rank=0 time:158.620365

rank=1time:159.041463

rank=2time:158.827125

rank=3time:158.519957

 

rank=0time:211.242267

rank=1time:211.114535

rank=2time:211.117872

 

rank=0time:171.935731

rank=1time:171.970319

 

rank=0time:319.567614

 

1000000

rank=0 time:190.271859

rank=1time:190.056185

rank=2time:189.846401

rank=3time:190.314395

 

rank=0time:211.273677

rank=1time:211.328568

rank=2time:211.304030

 

rank=0time:172.247044

rank=1time:172.281147

 

rank=0time:318.965036

规模

时间/s

100k*2k

255

137

169

127

500k*0.5k

319

171

211

158

1000K*0.3k

318

172

211

190

加速比

100k*2k

1

1.861314

1.508876

2.007874

500k*0.5k

1

1.865497

1.511848

2.018987

1000K*0.3k

1

1.848837

1.507109

1.673684


实验遇到的问题:

1.如何串行执行

MPI的并行是进程的并行,所以MPI_Finalize()只是将资源释放了,并不是之后的程序就串行执行了,要想串行,可以指定一个进程执行。

2.结果输出

在用进程0输出所有车辆数据时发现只有线程0处理的部分数据有变更,其余数据维持在初始化时的状态。那么应该是每个进程是将处理了自己部分的数据的备份,而不是在原有数据的基础上处理的。所以要一个进程进行输出。

如果每个进程都自己输出数据就会产生文件写冲突而导致结果的不可预知,所以要将其它进程的数据发送到一个进程,用一个进程进行输出。

3.进程同步

如果进程间通信时设置的tag可以区分所有周期(比如设置为j*10+myid),那么在每个周期结束时就没有必要同步所有进程。

但是在这样修改之后运行时间没有什么区别,应该是核心的处理能力类似,同步产生的开销并不明显。

源程序:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>int num_car=100000;
int num_cycle[]={2000,500,300};const int v0=4,vmax=8,p=5;typedef struct car
{int v;int d;int p;
}car;
car car_list[1000000];int count[10]={0,0,0,0,0, 0,0,0,0,0};
int pos_count[20*8+10000*8]={0};//count per 100int main(int argc,char *argv[])
{//四线程写结果的时候打开文件FILE*fp = fopen("result_100000.txt","w");FILE*fp2 = fopen("statistic_100000.txt","w");//初始条件int i=0;for(i=0;i<num_car;i++){car_list[i].v=v0;car_list[i].p=vmax*i;car_list[i].d=vmax;}int     myid, numprocs;clock_t starttime,endtime;int    namelen;char   processor_name[MPI_MAX_PROCESSOR_NAME];MPI_Init(&argc,&argv);MPI_Comm_size(MPI_COMM_WORLD,&numprocs);MPI_Comm_rank(MPI_COMM_WORLD,&myid);int* mpi_buffer=malloc(sizeof(int)*1000000);MPI_Buffer_attach(mpi_buffer,sizeof(int)*1000000);//模拟过程开始starttime=clock();int j=0;for(j=0;j<2000;j++){i=(num_car/numprocs*myid);//指向这个集合的第一个元素if(myid!=0)//如果不是第一个线程就要向前发送数据{			MPI_Bsend(&(car_list[i].p),1,MPI_INT,myid-1,j*10+myid,MPI_COMM_WORLD);}for(;i<num_car/numprocs*(myid+1)-1;i++){//更新距离car_list[i].d=car_list[i+1].p-car_list[i].p;//更新速度if(car_list[i].d>car_list[i].v && car_list[i].v<vmax)car_list[i].v++;if(car_list[i].d<=car_list[i].v)car_list[i].v=car_list[i].d-1;srand(i*num_car+j);if( car_list[i].v>1 ){int r=rand()%10;if(r<p){car_list[i].v--;//printf("#");}}//更新位置car_list[i].p+=car_list[i].v;}if(myid!=numprocs-1)//不是最后一个进程{int temp;MPI_Status status;MPI_Recv(&(temp),1,MPI_INT,myid+1,j*10+myid+1,MPI_COMM_WORLD,&status);//更新距离car_list[i].d=temp-car_list[i].p;	//printf("%d temp %d %d\n",myid,temp,car_list[i].d);}//更新速度if(car_list[i].v<vmax)car_list[i].v++;if(car_list[i].d<=car_list[i].v)car_list[i].v=car_list[i].d-1;srand((unsigned) time(NULL));if( car_list[i].v>1 && rand()%10< p ){car_list[i].v--;}//更新位置car_list[i].p+=car_list[i].v;//MPI_Barrier(MPI_COMM_WORLD);}//for cycle//模拟过程结束endtime=clock();printf("rank=%d time:%lf\n",myid,(double)(endtime-starttime)/CLOCKS_PER_SEC);//四线程的时候向文件写结果,别的线程时注释掉好了MPI_Barrier(MPI_COMM_WORLD);if(myid==0){MPI_Send((car_list),sizeof(car)*num_car/4,MPI_BYTE,3,myid,MPI_COMM_WORLD);	}if(myid==1){MPI_Send((car_list+num_car/4),sizeof(car)*num_car/4,MPI_BYTE,3,myid,MPI_COMM_WORLD);			}if(myid==2){MPI_Send((car_list+2*num_car/4),sizeof(car)*num_car/4,MPI_BYTE,3,myid,MPI_COMM_WORLD);			}if(myid==numprocs-1){MPI_Status status;MPI_Recv((car_list),sizeof(car)*num_car/4,MPI_BYTE,0,0,MPI_COMM_WORLD,&status);MPI_Recv((car_list+num_car/4),sizeof(car)*num_car/4,MPI_BYTE,1,1,MPI_COMM_WORLD,&status);MPI_Recv((car_list+2*num_car/4),sizeof(car)*num_car/4,MPI_BYTE,2,2,MPI_COMM_WORLD,&status);		int a;for(a=0;a<num_car;a++){fprintf(fp,"%d %d:%d %d %d\n",myid,a,car_list[a].v,car_list[a].p,car_list[a].d);}for(i=0;i<num_car;i++){count[car_list[i].v]++;pos_count[car_list[i].p/1000]++;}int k;for(k=0;k<10;k++){fprintf(fp2,"%d\t:%d\n",k,count[k]);}for(k=0;k<2*8+num_car*8/1000;k++){fprintf(fp2,"%d\t%d\n",k,pos_count[k]);}		}MPI_Barrier(MPI_COMM_WORLD);fclose(fp);fclose(fp2);MPI_Finalize();return 0;
}


转载于:https://www.cnblogs.com/biaoJM/p/10186706.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/570818.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 中.aar文件生成方法与用法

https://i.cnblogs.com/EditPosts.aspx?opt1 无论是用Eclipse还是用Android Studio做android开发&#xff0c;都会接触到jar包&#xff0c;全称应该是&#xff1a;Java Archive&#xff0c;即java归档文件。在用AS的过程中&#xff0c;你会发现有aar这么个东西&#xff0c;经查…

windows10上安装mysql

环境&#xff1a;windwos 10&#xff08;1511&#xff09; 64bit、mysql 5.7.14 一、下载mysql1. 在浏览器里打开mysql的官网http://www.mysql.com/2. 进入页面顶部的"Downloads"3. 打开页面底部的“Community(GPL) Downloads” 4. 在页面中间的位置找到我们windows上…

sql server 内存初探

sql server 内存初探 原文:sql server 内存初探一. 前言 对于sql server 这个产品来说&#xff0c;内存这块是最重要的一个资源&#xff0c; 当我们新建一个会话&#xff0c;相同的sql语句查询第二次查询时间往往会比第一次快&#xff0c;特别是在sql统计或大量查询数据输出时&…

使用TcpClient的例程

例子1&#xff1a; ///假定一切工作正常 ///连接后发送一次消息&#xff0c;然后不停接受消息并且打印 主要API说明 TcpClient clientnew TcpClient(); client.Connect("127.0.0.1",8888); NetworkStream streamclient.GetStream(); 发送&#xff1a; stream.Write(o…

20172324 2017-2018-2《程序设计与数据结构》实验三报告

20172324 2017-2018-2《程序设计与数据结构》实验三报告 课程&#xff1a;《程序设计与数据结构》 班级&#xff1a; 1723 姓名&#xff1a; 曾程 学号&#xff1a;20172324 实验教师&#xff1a;王志强 实验日期&#xff1a;2018年5月23日 必修/选修&#xff1a; 必修 一、实验…

mysql if--else

SQL之case when then用法 case具有两种格式。简单case函数和case搜索函数。 --简单case函数 case sexwhen 1 then 男when 2 then 女’else 其他 end --case搜索函数 case when sex 1 then 男when sex 2 then 女else 其他 end 这两种方式&#xff0c;可以实现相同的功能。简…

笔记41 Spring Web Flow——Demo

订购披萨的应用整体比较比较复杂&#xff0c;现拿出其中一个简化版的流程&#xff1a;即用户访问首页&#xff0c;然后输入电话号&#xff08;假定未注册&#xff09;后跳转到注册页面&#xff0c;注册完成后跳转到配送区域检查页面&#xff0c;最后再跳转回首页。通过这个简单…

CSS3弹性盒子Flex

CSS3弹性盒子Flex 基础知识和术语 原文链接&#xff1a;https://css-tricks.com/snippets/css/a-guide-to-flexbox/ 父级&#xff08;flex容器&#xff09;的属性 &#xff03;显示 这定义了一个flex容器; 内联或块取决于给定的值。它为所有直接的孩子提供了一个弹性环境。 .co…

cloudera manager的7180 web界面访问不了的解决办法(图文详解)

说在前面的话 我的机器是总共4台&#xff0c;分别为ubuntucmbigdata1、ubuntucmbigdata2、ubuntucmbigdata3和ubuntucmbigdata4。&#xff08;注意啦&#xff0c;以下是针对Ubuntu系统的&#xff09; 在ubuntucmbigdata1上执行了 sudo apt-get install cloudera-manager-daemon…

2018 ios开发者账号同意新协议加联系电话教程

苹果开发者账号经常会更新协议&#xff0c;需要同意新的协议账号才能正常使用。 1、首先登录苹果开发者中心https://developer.apple.com/account/ 会出现下面飘红的提示&#xff0c;就是提示你要同意新协议。因为苹果规则的改变&#xff0c;需要先到appid管理中心加个联系手机…

Django REST FRAMEWORK swagger(一)框架详解

Django REST FRAMEWORK swagger&#xff08;一、框架详解&#xff09; 一.Django REST SWAGGER框架图 具体见下图 二.说明 RESTFul说明 每一个URI代表一种资源&#xff1b; 客户端和服务器之间&#xff0c;传递这种资源的某种表现层&#xff1b; 客户端通过四个HTTP动词&…

Prism for WPF初探(构建简单的模块化开发框架)

Prism for WPF初探&#xff08;构建简单的模块化开发框架&#xff09; 原文:Prism for WPF初探&#xff08;构建简单的模块化开发框架&#xff09;先简单的介绍一下Prism框架&#xff0c;引用微软官方的解释&#xff1a; Prism provides guidance to help you more easily desi…

15-[JavaScript]-ECMAScript 1

0.javaScript的发展历程 https://zhuanlan.zhihu.com/p/27985124 1、javaScript是什么&#xff1f; javaScript是一种web前端的描述语言&#xff0c;也是一种基于对象&#xff08;object&#xff09;和事件驱动&#xff08;Event Driven&#xff09;的、安全性好的脚本语言。 它…

WPF MVVM 架构 Step By Step(2)(简单的三层架构示例及粘合代码GLUE code)

WPF MVVM 架构 Step By Step(2)&#xff08;简单的三层架构示例及粘合代码GLUE code&#xff09; 原文:WPF MVVM 架构 Step By Step(2)&#xff08;简单的三层架构示例及粘合代码GLUE code&#xff09;我们第一步就是去了解三层架构和问题然后去看MVVM是怎么去解决这些问题的。…

基于YARN集群构建运行PySpark Application

文章转载&#xff1a;https://www.tuicool.com/articles/eaYVN3v Spark Application可以直接运行在YARN集群上&#xff0c;这种运行模式&#xff0c;会将资源的管理与协调统一交给YARN集群去处理&#xff0c;这样能够实现构建于YARN集群之上Application的多样性&#xff0c;比…

Apache nifi 集群安装

原文地址&#xff1a;https://pierrevillard.com/2016/08/13/apache-nifi-1-0-0-cluster-setup/ 文章写的很好了&#xff0c;步骤性的英文写得也比较易懂&#xff0c;原样搬过来了&#xff0c;没有再翻译 As you may know a version 1.0.0-BETA of Apache NiFi has been rele…

Html5 学习笔记 --》html基础 css 基础

HTML5 功能 HTML5特点 <!DOCTYPE html> <html lang"zh-cn"> <head><meta charset"utf-8"><title>基本格式</title> </head> <body><a href"http://www.baidu.com">百度</a> </b…

VMware仅主机模式访问外网

原文转载至&#xff1a;https://blog.csdn.net/eussi/article/details/79054622 保证VMware Network Adapter VMnet1是启用状态 将可以连接外网的连接共享属性设置成如下图所示 将VMware Network Adapter VMnet1的IP地址设置成与本机IP不同的网段即可 VMware虚拟网络编辑器VMne…

IE上ORACLE OEM 证书错误 , 导航阻止,无法”继续浏览此网站”

文章转载自&#xff1a;http://blog.51cto.com/cswggod/1193266 仅用于个人学习&#xff0c;知识收藏 本文是我安装ORACLE11g后客户端IE访问不了是出现的&#xff0c;无奈下找OTN上help&#xff0c; 结果很lucky的被解脱了。 网站是&#xff1a;https://forums.oracle.com/for…

testng使用DataProvider+Excel实现DDT

DDT&#xff0c;即数据驱动测试 Data Driver Test&#xff0c;我曾经记录了一篇关于python的DDT框架&#xff08;ExcelDDT数据驱动实例&#xff09;&#xff0c;那么java中的DDT是怎么样的呢&#xff1f;在java中&#xff0c;可以用testng的DataProvider和Excel实现。 首先建一…