并行计算课程设计报告.doc

上传人:w****2 文档编号:6491802 上传时间:2020-02-27 格式:DOC 页数:46 大小:464.50KB
返回 下载 相关 举报
并行计算课程设计报告.doc_第1页
第1页 / 共46页
并行计算课程设计报告.doc_第2页
第2页 / 共46页
并行计算课程设计报告.doc_第3页
第3页 / 共46页
点击查看更多>>
资源描述
并行计算与多核多线程技术课程报告 专业 班级 学号 姓名 成绩 _ 年 月 日课程报告要求手写内容:设计目的、意义,设计分析,方案分析,功能模块实现,最终结果分析,设计体会等。 允许打印内容:设计原理图等图形、图片,电路图,源程序。硬件类的设计,要有最终设计的照片图;软件类设计,要有各个功能模块实现的界面图、输入输出界面图等。评 价理论基础实践效果(正确度/加速比)难度工作量独立性目 录1. 设计目的、意义(功能描述)12. 方案分析(解决方案)13. 设计分析13.1 串行算法设计13.2 并行算法设计13.3 理论加速比分析24. 功能模块实现与最终结果分析24.1 基于OpenMP的并行算法实现24.1.1 主要功能模块与实现方法24.1.2 实验加速比分析24.2 基于MPI的并行算法实现24.2.1 主要功能模块与实现方法24.2.2 实验加速比分析24.3 基于Java的并行算法实现34.3.1 主要功能模块与实现方法34.3.2 实验加速比分析34.4 基于Windows API的并行算法实现34.4.1 主要功能模块与实现方法34.4.2 实验加速比分析34.5 基于.net的并行算法实现34.5.1 主要功能模块与实现方法34.5.2 实验加速比分析34.6并行计算技术在实际系统中的应用44.6.1 主要功能模块与实现方法44.6.2 实验加速比分析55. 设计体会56. 附录66.1 基于OpenMP的并行程序设计66.1.1 代码及注释66.1.2 执行结果截图66.1.3 遇到的问题及解决方案66.2 基于MPI的并行程序设计76.1.1 代码及注释76.2.2 执行结果截图76.2.3 遇到的问题及解决方案76.3 基于Java的并行程序设计86.3.1 代码及注释86.3.2 执行结果截图86.3.3 遇到的问题及解决方案96.4 基于Windows API的并行程序设计96.4.1 代码及注释96.4.2 执行结果截图106.4.3 遇到的问题及解决方案106.5 基于.net的并行程序设计116.5.1 代码及注释116.5.2 执行结果截图116.5.3 遇到的问题及解决方案116.6并行计算技术在实际应用系统的应用156.6.1 代码及注释156.6.2 执行结果截图156.6.3 遇到的问题及解决方案151. 设计目的、意义(功能描述)设计一个计算向量夹角的WinForm窗体应用,用户只需要在窗体上输入向量的维度,系统随机产生两个向量并将计算结果显示在窗体上。求两个n维向量的夹角,要用到求向量夹角的数学公式,当向量维度较小时计算量不大,而当维度过大时特别是百万级甚至千万级别的时候计算量就很大了,用并行计算求向量夹角,可以将任务分配给多个处理器,减小运算时间。所以要设计一个并行计算夹角的方法,提高计算速度,把并行和串行计算时间做个比较显示在窗体上。窗体应用比控制台程序更方便用户操作,简单直观,页面也更加友好。2. 方案分析(解决方案)定义两个数组分别存放两个向量,用for循环将产生的随机数赋值给数组。假设有两个向量X,Y X=(x1,x2,xn),Y=(y1,y2,yn)计算X,Y夹角的公式是:cos(X,Y)=XY/(|X|Y|)=(x1y1+x2y2+xnyn)/(x1+x2+xn)1/2(y1+y2+yn)1/2。由3个for循环分别实现求向量积和两个向量的模,最后用公式计算即可。3. 设计分析3.1 串行算法设计输入:向量的维度n输出:两个随机向量的夹角syy_angleBegin给存放向量的数组动态分配内存空间For i=0 to i=n-1 do 产生随机数给数组x赋值endForFor i=0 to i=n-1 do产生随机数给数组y赋值endForFor i=0 to i=n-1 do 计算向量积endForFor i=0 to i=n-1 do计算向量X模endForFor i=0 to i=n-1 do 计算向量Y模endFor利用公式计算夹角End3.2 并行算法设计输入:向量的维度n输出:两个随机向量的夹角syy_angleBegin给存放向量的数组动态分配内存空间For i=0 to i=n-1 do 产生随机数给数组x赋值endForFor i=0 to i=n-1 do产生随机数给数组y赋值endFor3个for循环串行执行,每个for循环由p个核并行执行:p个核同时执行第一个for循环For i=0 to i=n-1 do 计算向量积endForp个核同时执行第二个for循环For i=0 to i=n-1 do计算向量X模endForp个核同时执行第三个for循环For i=0 to i=n-1 do 计算向量Y模endFor利用公式计算夹角End3.3 理论加速比分析设加速比为S,串行运行时间为Ts,并行的运行时间为Tp。假设一次运算作为一个时间单位,对于串行算法来说其时间复杂度为O(n) 即Ts=O(n) ,对于并行算法来说,由于有p个处理器同时运行,则其时间复杂度为O(n/p) 即Tp=O(n/p) ,所以理论加速比S=Ts/Tp=O(n)/O(n/p)=p。4. 功能模块实现与最终结果分析4.1 基于OpenMP的并行算法实现4.1.1 主要功能模块与实现方法1:向量x,y赋值,用产生的随机数对存放向量的数组赋值,得到两个随机向量srand(int)time(0);/数组X赋值for(i=0;in;i+) j=(int)(100*rand()/(RAND_MAX+1.0); /随机产生的数xi=j; /数组Y赋值for(i=0;in;i+) j=(int)(100*rand()/(RAND_MAX+1.0); /随机产生的数yi=j; 2:计算向量积,向量x,y的模用并行实现。设置两个线程,用reduction实现并行计算,两个线程都会创建一个reduction变量的私有副本,在OPENMP区域结束后,将各个线程的计算结果相加赋值给原来的变量。#pragma omp parallel for reduction(+:syy_outer_product)for(i=0;in;i+)syy_outer_product=syy_outer_product+xi*yi;/计算向量积计算向量X,Y的模方法与上面类似4.1.2 实验加速比分析线程数设置为2时,向量维数小时,由于精度问题,运行时间显示为0,加速比无法计算。向量维数到达百万级以上,加速比介于1到2之间,根据向量维数的变化,加速比有一定的变化但不会超过范围。4.2 基于MPI的并行算法实现4.2.1 主要功能模块与实现方法使用MPI群集通信,由0进程接收输入的数组长度n,给数组动态分配内存后,用产生的随机数给数组赋值。用MPI_Bcast先将数组长度广播给其他进程,由其他进程给数组动态分配内存后,再将数组值广播给其他进程。求向量积,向量模的for由多个进程同时执行,将0到n-1次循环分配给P个进程,每个进程从i=myid开始执行,循环一次i加进程数。将每个进程的计算结果用MPI_Reduce函数规约。1:由0进程进行随机数组动态分配内存和赋值操作if(myid=0)/为数组x,y动态分配空间x = (int*)malloc(n * sizeof(int);y = (int*)malloc(n * sizeof(int);srand(int)time(0);/数组X赋值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /随即产生的数xi=j; 数组y赋值同上starttime=MPI_Wtime();2:用MPI_Bcast()函数将数组长度和值广播给其他进程MPI_Bcast(&n,1,MPI_LONG,0,MPI_COMM_WORLD);/将n值广播出去MPI_Bcast(x,n,MPI_INT,0,MPI_COMM_WORLD);/将x值广播出去MPI_Bcast(y,n,MPI_INT,0,MPI_COMM_WORLD);/将y值广播出去3:用MPI_Reduce()函数对各个进程的计算结果规约MPI_Reduce(&my_product,&syy_outer_product,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD); MPI_Reduce(&my_mol_x,&syy_mol_x,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);MPI_Reduce(&my_mol_y,&syy_mol_y,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);4:多个进程同时执行for循环for(i=syy_myid;in;i+=syy_numprocs) product+=xi*yi;/计算向量积计算向量x,y模与上面类似5:串行部分由0进程完成,在执行完并行计算后,再由0进程单独完成串行操作. if(syy_myid=0 )里执行的串行操作4.2.2 实验加速比分析并行时间比串行时间要长,加速比低于1,MPI并行是进程间相互通信传递数据。设置两个进程时,在0进程里输入向量维度,由0进程对向量数组赋值。再将n值和x,y动态数组广播给其他进程。串行计算只有0进程独立完成,可能是进程间通信过多使并行额外开销太大。4.3 基于Java的并行算法实现4.3.1 主要功能模块与实现方法1:继承Thread类,创建两个线程thread1,thread2。用start方法开始线程。使用join()方法等待线程结束后再继续执行。javaand thread1=new javaand(0,n,x,y);javaand thread2=new javaand(1,n,x,y);startTime=System.currentTimeMillis();thread1.start();thread2.start();thread1.join();thread2.join();2:两个线程同时执行run函数,thread1循环从0到n-1,每次循环i加2,thread2循环从1到n-1,每次循环i加2.最后两个线程的计算结果相加public void run()for(long i=start;iend;i+=2)syy_outer_product+=x(int)i*y(int)i;/计算向量积for(long i=start;iend;i+=2)syy_mol_x+=x(int)i*x(int)i;/计算向量X模for(long i=start;iend;i+=2)syy_mol_y+=y(int)i*y(int)i;/计算向量Y模3:用count函数实现串行计算,循环从0到n-1,每次循环i加1.循环部分代码与run方法中类似。分别用三个循环计算向量积,向量X,Y模后再根据公式计算向量夹角,最后返回运算结果。4.3.2 实验加速比分析数据量较小时,串并行显示的时间都为0,因此无法计算加速比,当数据量较大时加速比控制在1-2之间。输入向量的维度超过100000000时,出现内存溢出,无法计算加速比。数组长度定义过大时,程序消耗内存过大会出现内存溢出,即使是修改JVM -Xmx 参数后,向量维度也不能超过1000000004.4 基于Windows API的并行算法实现4.4.1 主要功能模块与实现方法1:创建两个线程thread1 ,thread2,分别指定线程函数为ThreadOne ThreadTwo创建成功后返回线程的句柄,等待两个线程计算完后将两个线程的执行结果相加HANDLE thread1=CreateThread(NULL,0,ThreadOne,NULL,0,NULL);HANDLE thread2=CreateThread(NULL,0,ThreadTwo,NULL,0,NULL);WaitForMultipleObjects(2,finish,true,INFINITE);for(int i=0;i2;i+)syy_outer_product+=producti;syy_mol_x+=mol_xi; syy_mol_y+=mol_yi;2:并行线程函数,将n次循环分成两部分,线程函数ThreadOne执行前半部分操作,函数ThreadTwo执行后半部分操作Thread1线程函数负责for循环从0到(n/2)-1:DWORD WINAPI ThreadOne(LPVOID param) Thread2线程函数负责for循环从n/2到n-1 :DWORD WINAPI ThreadTwo(LPVOID param)3:线程函数ThreadThree作为单线程执行,for循环从0到n-1DWORD WINAPI ThreadThree(LPVOID param)4.4.2 实验加速比分析串行和并行运算结果相同,但并行比串行时间大。从理论上分析,两个线程同时执行for循环,加速比应该在1-2之间,而实际情况是并行比串行时间还久。WaitForMultipleObjects(2,finish,true,INFINITE);这句运行时间长,使用WaitForMultipleObjects函数是让线程进入等待状态,直到finishi指向的内核对象都变为已通知状态。先完成工作的处理器要等待未完成工作的处理器,处理器空闲时间太大可能会造成并行比串行时间大。4.5 基于.net的并行算法实现4.5.1 主要功能模块与实现方法1:创建ThreadStart代理,即thread1 ,thread2。指定Work类的sum函数作为两个线程执行的线程函数。将thread1,thread2代理传递给Thread类的构造函数,最后调用Thread类的Start方法开启线程。Join方法可以保证应用程序域等待异步线程结束后才终止运行。Work work1 = new Work(0,n,x,y);ThreadStart thread1 = new ThreadStart(work1.Sum); Thread newthread1 = new Thread(thread1);Work work2 = new Work(1,n,x,y);ThreadStart thread2 = new ThreadStart(work2.Sum);Thread newthread2 = new Thread(thread2);2:用于实现并行计算的Work类的Sum函数。newthread1执行的循环是从0到n-1,每次循环i加2。newthread2执行的循环是从1到n-1,每次循环i加2。计算向量积的for循环如下:for (long i = start; i end; i += 2) syy_outer_product += xi * yi;/计算向量积 3:调用Work类的sumto函数实现串行计算,并返回计算得到的夹角。用3个for循环分别计算向量积和x,y的模,循环从0到n-1,每次i加1,最后用公式计算夹角。4.5.2 实验加速比分析设置两个线程同时计算,能得到较理想的加速比,数据量为十几时,加速比在1.8左右,数据量达到10000000000时,加速比能接近1.9.从总体的运行结果看,加速比在1.7到1.9之间,符合理论加速比的分析。4.6 并行计算技术在实际系统中的应用4.6.1 主要功能模块与实现方法1:确认按钮点击事件函数,当点击确认按钮后从文本框中获取向量的维度,传递给count函数:private void confirm_Click(object sender, EventArgs e)2:从窗体中获取向量维度后用count函数计算夹角,并把结果返回给窗体。用并行和串行方法计算的代码全部放在count函数里进行public void count(long n)3:创建两个线程实现并行计算创建两个线程代理thread1 ,thread2指定线程函数Work类里的Sum函数,然后将ThreadStart代理传递给Thread类的构造函数Work work1 = new Work(0,n,x,y);ThreadStart thread1 = new ThreadStart(work1.Sum); Thread newthread1 = new Thread(thread1);Work work2 = new Work(1,n,x,y);ThreadStart thread2 = new ThreadStart(work2.Sum);Thread newthread2 = new Thread(thread2);4:用于实现并行计算的Work类的Sum函数。newthread1执行的循环是从0到n-1,每次循环i加2。newthread2执行的循环是从1到n-1,每次循环i加2。计算向量积的for循环如下:for (long i = start; i end; i += 2) syy_outer_product += xi * yi;/计算向量积 5:调用Work类的sumto函数实现串行计算,并返回计算得到的夹角。用3个for循环分别计算向量积和x,y的模,循环从0到n-1,每次i加1,最后用公式计算夹角。4.6.2 实验加速比分析当数据量较小时加速比接近于1,比较小。当数据量大的时候,加速比有时会超过2,甚至接近于3,与理论分析的加速比有出入。可能跟WinForm窗体运行环境有关,用C#语言写的程序占用内存小加速比高。5. 设计体会这次课程设计是用了5种不同的方法实现求n维随机向量的夹角,在具体的编程过程中遇到了很多问题,在解决问题过程中也有不少收获,下面我就这五种实现方法谈谈我的设计体会。 用OpenMP编程时为了解决数据竞争的问题,我使用了reduction字句,在进入并行区域后两个线程就有各自的变量的副本,只要变量不公用,就不存在数据竞争的问题。OpenMP的编程是在parallel并行区内并行计算,我觉得相比其他四个编程方法这个更简单。 在MPI编程中,我遇到了最大的问题是不知道如何广播动态数组,后来上网查询,找到了一个解决方案是先将数组长度广播出去,然后非0进程动态非配空间后再广播该数组。 用java语言编写程序时,很多程序语言需要利用外部的线程软件包来实现多线程,而java语言则内在支持多线程,它的所有类都是在多线程的思想下定义的。Java编程中实现多线程有两种办法:一种是用户在自己定义的类中使用Runnable接口,另一种是继承Thread类。我用的就是第二种方法,在run函数中实现并行,在count函数中实现串行。 .net编程有很多地方与java相似,用两个线程做并行计算,都要先创建进程,但.net创建线程首先需要创建ThreadStart 代理,指定线程执行的线程函数,然后再创建Thread类线程,将ThreadStart代理传递给Thread类的构造函数。线程函数有点类似于java Thread类里的run函数,都是两个线程同时执行的函数。 Win32API编程不需要配置编程环境,应用程序只需要调用相关的函数就行,Win32 API提供了一系列处理线程的函数接口,向应用程序提供多线程的功能。总之,每种实现方法都各有特点。用不同的语言实现同一种算法,在具体的编程过程中也会有细小的差异,每一次修正错误都是一次学习。6. 附录6.1 基于OpenMP的并行程序设计6.1.1 代码及注释(变量名 名字首字母 开头)#include stdafx.h#include #include #include #include #include #include #define NUM_THREADS 2int _tmain(int argc, _TCHAR* argv)int j; /随机数long long i;long long n;long double syy_outer_product=0,syy_mol_x=0,syy_mol_y=0,syy_angle;/向量积clock_t t1,t2,t3,t4; printf(两条n维随即向量的夹角串并行计算n); printf(请输入向量的维度:n);scanf(%lld,&n);/为数组x,y动态分配空间int *x = (int*)malloc(n * sizeof(int);int *y = (int*)malloc(n * sizeof(int);srand(int)time(0);/数组X赋值for(i=0;in;i+) j=(int)(100*rand()/(RAND_MAX+1.0); /随即产生到的数xi=j; /数组Y赋值for(i=0;in;i+) j=(int)(100*rand()/(RAND_MAX+1.0); /随即产生到的数yi=j; /* 串行区域 */ t1=clock();for(i=0;in;i+)syy_outer_product=syy_outer_product+xi*yi;/计算向量积for(i=0;in;i+)syy_mol_x=syy_mol_x+xi*xi;/计算向量X模for(i=0;in;i+)syy_mol_y=syy_mol_y+yi*yi;/计算向量Y模t2=clock();t3=t2-t1;/串行时间syy_mol_x=sqrt(syy_mol_x);syy_mol_y=sqrt(syy_mol_y);syy_angle=syy_outer_product/(syy_mol_x*syy_mol_y);printf(随即产生两个向量,向量的夹角cos(x,y)=%fn,syy_angle);printf(串行时间=%dn,(t2-t1); syy_mol_x=0;syy_mol_y=0;syy_outer_product=0;omp_set_num_threads(NUM_THREADS);/设置线程数t1=clock();/* 并行区域 */#pragma omp parallel for reduction(+:syy_outer_product)for(i=0;in;i+)syy_outer_product=syy_outer_product+xi*yi;/计算向量积#pragma omp parallel for reduction(+:syy_mol_x)for(i=0;in;i+)syy_mol_x=syy_mol_x+xi*xi;/计算向量X模#pragma omp parallel for reduction(+:syy_mol_y)for(i=0;in;i+)syy_mol_y=syy_mol_y+yi*yi;/计算向量Y模t2=clock();t4=t2-t1;/并行时间syy_mol_x=sqrt(syy_mol_x);syy_mol_y=sqrt(syy_mol_y);syy_angle=syy_outer_product/(syy_mol_x*syy_mol_y);printf(随即产生两个向量,向量的夹角cos(x,y)=%fn,syy_angle);printf(并行时间=%dn,(t2-t1);printf(加速比=%fn,(float)t3/t4);free (x);free(y);system(pause);return 0;6.1.2 执行结果截图(体现串行时间、并行时间和加速比)(1)小数据量验证正确性的执行结果(2)大数据量获得较好加速比的执行结果6.1.3 遇到的问题及解决方案(1)问题一错误代码及后果遇到的问题是当向量的维度定义超过1亿级时会存在数组越界,其他没什么大问题。正确代码分析6.2 基于MPI的并行程序设计6.1.1 代码及注释(变量名 名字首字母 开头)/ syyMPI.cpp : 定义控制台应用程序的入口点。/#include stdafx.h#include mpi.h#include #include #include #include void main(int argc, char* argv)int j; /随机数int syy_myid,syy_numprocs;/线程编号和线程总数 long int i,n;/n为向量的维数 long double product,mol_x,mol_y,my_product,my_mol_x,my_mol_y; long double syy_outer_product,syy_mol_x,syy_mol_y,syy_angle;double starttime,endtime;int *x,*y;MPI_Init(&argc,&argv);/并行开始MPI_Comm_size(MPI_COMM_WORLD,&syy_numprocs);MPI_Comm_rank(MPI_COMM_WORLD,&syy_myid);if(syy_myid=0)printf(请输入向量的维度:n);fflush(stdout);scanf_s(%ld,&n);/为数组x,y动态分配空间x = (int*)malloc(n * sizeof(int);y = (int*)malloc(n * sizeof(int);srand(int)time(0);/数组X赋值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /随即产生的数xi=j; /数组Y赋值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /随即产生的数yi=j;starttime=MPI_Wtime();MPI_Bcast(&n,1,MPI_LONG,0,MPI_COMM_WORLD);/将n值广播出去if(syy_myid!=0)x = (int*)malloc(n * sizeof(int); y = (int*)malloc(n * sizeof(int);MPI_Bcast(x,n,MPI_INT,0,MPI_COMM_WORLD);/将x值广播出去MPI_Bcast(y,n,MPI_INT,0,MPI_COMM_WORLD);/将y值广播出去product=0.0;mol_x=0.0;mol_y=0.0;for(i=syy_myid;in;i+=syy_numprocs) product+=xi*yi;/计算向量积 for(i=syy_myid;in;i+=syy_numprocs) mol_y+=yi*yi;/计算向量Y模 for(i=syy_myid;in;i+=syy_numprocs) mol_x+=xi*xi;/计算向量X模my_product=product;my_mol_x=mol_x;my_mol_y=mol_y;MPI_Reduce(&my_product,&syy_outer_product,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);/将各线程求得的向量积求和MPI_Reduce(&my_mol_x,&syy_mol_x,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);/将各线程求得的向量X模求和MPI_Reduce(&my_mol_y,&syy_mol_y,1,MPI_LONG_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);/将各线程求得的向量Y模求和if(syy_myid=0)syy_mol_x=sqrt(syy_mol_x);syy_mol_y=sqrt(syy_mol_y);syy_angle=syy_outer_product/(syy_mol_x*syy_mol_y);endtime=MPI_Wtime();/并行结束时间printf(随机产生两个向量,向量的夹角cos(x,y)=%fn,syy_angle);printf(并行时间=%fn,endtime-starttime);/0进程做串行部分if(syy_myid=0 )syy_mol_x=0; syy_mol_y=0; syy_outer_product=0; starttime=MPI_Wtime();for(i=0;in;i+) syy_outer_product+=xi*yi;/计算向量积 for(i=0;in;i+) syy_mol_y+=yi*yi;/计算向量Y模 for(i=0;in;i+) syy_mol_x+=xi*xi;/计算向量X模syy_mol_x=sqrt(syy_mol_x);syy_mol_y=sqrt(syy_mol_y);syy_angle=syy_outer_product/(syy_mol_x*syy_mol_y);endtime=MPI_Wtime();/并行结束时间printf(随机产生两个向量,向量的夹角cos(x,y)=%fn,syy_angle);printf(串行时间=%fn,endtime-starttime);MPI_Finalize();/并行结束6.2.2 执行结果截图(体现串行时间、并行时间和加速比)(1) 小数据量验证正确性的执行结果进程数设置为2的运行结果(2)大数据量获得较好加速比的执行结果进程数设置为2的运行结果进程数设置为3的运行结果6.2.3 遇到的问题及解决方案(1)问题一错误代码及后果printf(请输入向量的维度:n);scanf(%ld,&n);后果:控制台没有任何输出结果正确代码printf(请输入向量的维度:n);fflush(stdout);scanf_s(%ld,&n);分析在0进程中输入n的值,如果没有使用fflush(stdout)(清除缓冲区后将内容输出),控制台会输出两遍而且运行不出来结果,修改后能正确输出(2)问题二错误代码及后果printf(请输入向量的维度:n);fflush(stdout);scanf_s(%ld,&n);/为数组x,y动态分配空间x = (int*)malloc(n * sizeof(int);y = (int*)malloc(n * sizeof(int);srand(int)time(0);/数组X赋值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /随即产生的数xi=j; /数组Y赋值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /随即产生的数yi=j;MPI_Init(&argc,&argv);/并行开始MPI_Comm_size(MPI_COMM_WORLD,&numprocs);MPI_Comm_rank(MPI_COMM_WORLD,&myid);if(myid=0)starttime=MPI_Wtime();正确代码MPI_Init(&argc,&argv);/并行开始MPI_Comm_size(MPI_COMM_WORLD,&numprocs);MPI_Comm_rank(MPI_COMM_WORLD,&myid);if(myid=0)printf(请输入向量的维度:n);fflush(stdout);scanf_s(%ld,&n);/为数组x,y动态分配空间x = (int*)malloc(n * sizeof(int);y = (int*)malloc(n * sizeof(int);srand(int)time(0);/数组X赋值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /随即产生的数xi=j; /数组Y赋值for(i=0;in;i+) j=(int)(10*rand()/(RAND_MAX+1.0); /随即产生的数yi=j;starttime=MPI_Wtime();分析把数组的赋值放在并行区域外执行,输出语句会执行两遍,如果由0进程对数组赋值,然后广播给其他进程就能正确执行。出现这种情况可能是两个进程串行的执行了输出语句。(3)问题三错误代码及后果MPI_Bcast(&n,1,MPI_LONG,0,MPI_COMM_WORLD);/将n值广播出去MPI_Bcast(&x,1,MPI_INT,0,MPI_COMM_WORLD);/将x值广播出去MPI_Bcast(&y,1,MPI_INT,0,MPI_COMM_WORLD);/将y值广播出去后果:程序执行不了,闪退正确代码MPI_Bcast(&n,1,MPI_LONG,0,MPI_COMM_WORLD);/将n值广播出去if(myid!=0)x = (int*)malloc(n * sizeof(int); y = (int*)malloc(n * sizeof(int);MPI_Bcast(x,n,MPI_INT,0,MPI_COMM_WORLD);/将x值广播出去MPI_Bcast(y,n,MPI_INT,0,MPI_COMM_WORLD);/将y值广播出去分析动态数组的广播:有时我们要广播的数据长度并不知道,这时就需要采用动态分配的方式分配数据,然后再将其广播。这里很容易出问题,问题的根本就是MPI程序是分布式程序,即使我们在写程序时所有的进程都公用相同的变量,但是在不同的进程下它们的含义不同。这就会导致有些进程的指针变量指向一块已经分配内存的空间,但是有些进程的指令变量还是空指针。这时如果不注意,就会导致动态数组广播的失败。解决办法是: 0进程从用户读取一个长度,然后利用malloc分配空间并赋值,然后将该数组广播到其他进程。方法是首先广播数组的长度,然后让其他进程分配相应的内存,最后再广播该数组。6.3 基于Java的并行程序设计6.3.1 代码及注释(变量名 名字首字母 开头)import java.util.Random;import java.util.Scanner;public class javaand extends Thread private long start;private long end;private double syy_outer_product=0,syy_mol_x=0,syy_mol_y=0;private double x,y;public javaand(long start,long end,double x,double y)super();this.start=start;this.end=end;this.x=x;this.y=y;public void run()for(long i=start;iend;i+=2)syy_outer_product+=x(int)i*y(int)i;/计算向量积for(long i=start;iend;i+=2)syy_mol_x+=x(int)i*x(int)i;/计算向量X模for(long i=start;iend;i+=2)syy_mol_y+=y(int)i*y(int)i;/计算向量Y模public double count()double syy_outer_product=0,syy_mol_x=0,syy_mol_y=0,syy_angle;for(long i=start;iend;i+)syy_outer_product+=x(int)i*y(int)i;/计算向量积for(long i=start;iend;i+)syy_mol_x+=x(int)i*x(int)i;/计算向量X模for(long i=start;iend;i+)syy_mol_y+=y(int)i*y(int)i;/计算向量Y模syy_mol_x=Math.sqrt(syy_mol_x);syy_mol_y=Math.sqrt(syy_mol_y);syy_angle=syy_outer_product/(syy_mol_x*syy_mol_y);System.out.println(随机产生两个向量,向量的夹角cos(x,y)=+syy_angle);return syy_angle;public double getproduct()return syy_outer_product;public double getmol_x()return syy_mol_x;public double getmol_y()return syy_mol_y;public static void main(String args)throws InterruptedExceptiondouble j; /随机数long i;long n;double syy_outer_product=0,syy_mol_x=0,syy_mol_y=0,syy_angle;/向量积long startTime,endTime; System.out.println(两条n维随即向量的夹角串并行计算n);System.out.println(请输入向量的维度(0到100000000之间):n);Scanner input=new Scanner(System.in);n=input.nextInt();double x=new double(int)n;double y=new double(int)n;/数组X赋值for(i=0;in;i+) Random rand = new Random();j=rand.nextInt(9)+1; /随即产生到的数x(int)i=j; /数组Y赋值for(i=0;in;i+) Random rand = new Random();j=rand.nextInt(9)+1; /随即产生到的数y(int)i=j; javaand thread1=new javaand(0,n,x,y);javaand thread2=new javaand(1,n,x,y);startTime=System.currentTimeMillis();thread1.start();thread2.start();thread1.join();thread2.join();endTime=System.currentTimeMillis();syy_mol_x=thread1.getmol_x()+thread2.getmol_x();/两个线程的计算结果相加syy_mol_y=thread1.getmol_y()+thread2.getmol_y(); syy_outer_product=thread1.getproduct()+thread2.getproduct();syy_mol_x=Math.sqrt(syy_mol_x);syy_mol_y=Math.sqrt(syy_mol_y);syy_angle=syy_outer_product/(syy_mol_x*syy_mol_y);System.out.println(随机产生两个向量,向量的夹角cos(x,y)=+syy_angle);System.out.println(并行时间=+(endTime-startTime);/下面是串行计算startTime=System.currentTimeMillis();javaand serial=new javaand(0,n,x,y);syy_angle=serial.count();endTime=System.currentTimeMillis();System.out.println(串行时间=+(endTime-startTime);6.3.2 执行结果截图(体现串行时间、并行时间和加速比)(1)小数据量
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 管理文书 > 工作总结


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!