广东技术师范学院实验报告
实验 (三) 项目名称:并行程序设计(2)
一、实验目的
在一个局域网中建立能够互相通信的两台计算机,实现两台计算机并行运算。
二、实验内容:
要求:用MPI_Isend和MPI_Irecv代替代码deadlock.c中的MPI_send和MPI_recv来避免出现程序死锁。程序代码deadlock.c参考如下
#include <stdio.h>
#include <string.h>
#include "mpi.h"
#define SIZE 16
int
main(int argc, char **argv)
{
static int buf1[SIZE], buf2[SIZE];
int nprocs, rank, tag, src, dst;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &nprocs); /* 获取总进程数*/
MPI_Comm_rank(MPI_COMM_WORLD, &rank); /* 获取本进程的进程号*/
/* 初始化buf1 */
memset(buf1, 1, SIZE);
tag = 123;
dst = (rank >= nprocs - 1) ? 0 : rank + 1;
src = (rank == 0) ? nprocs - 1 : rank - 1;
MPI_Send(buf1, SIZE, MPI_INT, dst, tag, MPI_COMM_WORLD);
MPI_Recv(buf2, SIZE, MPI_INT, src, tag, MPI_COMM_WORLD, &status);
MPI_Finalize();
return 0;
}
实验源程序代码:
#include "mpi.h"
#include <stdio.h>
#include <iostream.h>
#include <fstream.h>
void main(int argc, char *argv[])
{
int rank, size;
const int MAXX = 8;
const int MAXY = 3;
const int MAXPROCESSOR = 64;
int myid, namelen;
float Data[8][8];
int ArraySize[2];
int i, j, k;
double startwtime, endwtime;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Request *Status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Get_processor_name(processor_name, &namelen);
if(rank == 0)
{
ifstream in("input.txt");
in>>ArraySize[0]>>ArraySize[1];
for(i = 0; i < ArraySize[0]; i++)
for(j = 0; j < ArraySize[1]; j++)
in>>Data[i][j];
cout<<"二维数组如下:"<<endl;
for(i = 0; i < ArraySize[0]; i++)
{
for(j =0; j < ArraySize[1]; j++)
cout<<Data[i][j]<<" ";
cout<<endl;
}
}
MPI_Bcast(ArraySize, 2, MPI_INT, 0, MPI_COMM_WORLD);
int AverageLineNumber, HeavyProcessorNumber, MyLineNumber;
int CurrentLine, StartLine, SendSize;
float SendArray[8*3];
MPI_Request *IERROR;
AverageLineNumber = ArraySize[0]/size;
HeavyProcessorNumber = ArraySize[0]%size;
if(rank < HeavyProcessorNumber)
MyLineNumber = AverageLineNumber + 1;
else
MyLineNumber = AverageLineNumber;
if(rank == 0)
{
CurrentLine = ArraySize[0];
for(i = size - 1; i >= 0; i--)
{
SendSize = 0;
if(i == 0)
startwtime = MPI_Wtime();
if(i < HeavyProcessorNumber)
StartLine = CurrentLine - AverageLineNumber;
else
StartLine = CurrentLine - AverageLineNumber + 1;
for(j = StartLine; j < CurrentLine; j++)
for(k = 0; k < ArraySize[1]; k++)
SendArray[SendSize++] = Data[j][k];
if(i != 0)
MPI_Send(SendArray, SendSize, MPI_FLOAT, i, 10, MPI_COMM_WORLD);
CurrentLine = StartLine - 1;
}
}
else
MPI_Irecv(SendArray, MyLineNumber * ArraySize[1], MPI_FLOAT, 0, 10, MPI_COMM_WORLD, Status);
float Sum;
Sum = 0;
for(i = 0; i < MyLineNumber * ArraySize[1]; i++)
Sum += SendArray[i];
float ALLSum[64];
MPI_Gather(&Sum, 1, MPI_FLOAT, ALLSum, 1, MPI_FLOAT, 0, MPI_COMM_WORLD);
Sum = 0;
if(rank == 0)
{
for(i = 0; i < size; i++)
Sum += ALLSum[i];
endwtime = MPI_Wtime();
cout<<"二维数据所有元素和为:"<<Sum<<endl;
printf("运行时间为:%f\n", endwtime-startwtime);
}
MPI_Finalize();
}
单机运行:
多机运行:
三、实验分析与结论
经过多次在机房与同学互相讨论,最终解决问题,成功实现多机执行。
第二篇:并行计算第一次实验报告
并行计算上机实验报告
题目:多线程计算Pi值
学生姓名
学院名称 计算机学院
专 业计算机科学与技术
时 间
一. 实验目的
1、 掌握集群任务提交方式;
2、 掌握多线程编程。
二. 实验内容
1、通过下图中的近似公式,使用多线程编程实现pi的计算;
2、通过控制变量N的数值以及线程的数量,观察程序的执行效率。
三. 实现方法
1. 下载配置SSH客户端
2. 用多线程编写pi代码
3. 通过文件传输界面,将文件上传到集群上
4.将命令行目录切换至data,对.c文件进行编译
5.编写PBS脚本,提交作业
6.实验代码如下:
#include <math.h>
#include <sys/time.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
static double PI=0;
static int N=0;
static int numOfThread=0;
static int length=0;
static int timeUsed=0;
static int numOfThreadArray[]={1,2,4,6,8,10,12,14,16,20,24,30};
static int threadArraySize=12;
static int nTime=4;
static int repeatTime=30;
static double totalTime=0;
struct timeval tvpre, tvafter;
pthread_mutex_t mut;
clockid_t startTime,endTime;
void cmpu(int i)
{
double p=0;
int k;
for(k=i*length;k<(i+1)*length;k++)
{
p+=4.0/((double)(1+(pow((k+0.5)/N,2 ))));
}
p=p/N;
pthread_mutex_lock(&mut);
PI+=p;
pthread_mutex_unlock(&mut);
}
void mu()
{
gettimeofday(&tvpre, NULL);
startTime=clock();
pthread_t *myThread;
myThread=(pthread_t*)malloc((sizeof(pthread_t)*numOfThread));
int i;
int res;
for(i=0;i<numOfThread;i++)
{
res=pthread_create(&myThread[i],NULL,cmpu,i);
if(res!=0)
{
perror("Thread join failed");
}
}
for(i=0;i<numOfThread;i++)
{
pthread_join(myThread[i],NULL);
}
int left;
for(left=(length*numOfThread);left<N;left++){
PI+=4.0/((double)(1+(pow((left+0.5)/N,2 ))))/N;
}
endTime=clock();
timeUsed=endTime-startTime;
gettimeofday(&tvafter, NULL);
}
void printResult()
{
printf("N is %d , num of threads is %d\n",N,numOfThread);
printf("Pi is %0.15f \n Used time %d ms\n",PI,(timeUsed));
printf("cost time: %ld msecond\n", (tvafter.tv_sec-tvpre.tv_sec)*1000+(tvafter.tv_usec-tvpre.tv_usec)/1000);
}
void mainPro(int ns,int n_thread,FILE *fp)
{
N=ns;
numOfThread=n_thread;
PI=0;
length=N/numOfThread;
mu();
}
void main(int arg,char **args)
{
N=100000;
FILE *fp=fopen("myLog.xls","a");
int i=0;
for(i=0;i<nTime;i++)
{
N=N*10;
int j=0;
for(j=0;j<threadArraySize;j++)
{
numOfThread=numOfThreadArray[j];
totalTime=0;
int q=0;
for(q=0;q<repeatTime;q++)
{
mainPro(N,numOfThread,fp);
totalTime+=(tvafter.tv_sec-tvpre.tv_sec)*1000+(tvafter.tv_usec-tvpre.tv_usec)/1000;
}
fprintf(fp,"%d,%d,%f\n",N,numOfThread,totalTime/repeatTime);
printf("%d,%d,%f\n",N,numOfThread,totalTime/repeatTime);
}
}
fclose(fp);
}
四.程序流程图
五. 加速比曲线
1.下图为线程数与运行时间的关系,横坐标代表线程数,纵坐标代表运行时间,黄色的曲线代表N=100000000,粉色的曲线代表N=1000000,黑色的线代表N=100000.
2.加速比曲线
六.总结感悟
随着运算线程增加,运算量一定情况下,运算时间减少。这符合加速比定律。此程序不需要线程间通信,而内存占用等因素集群又可满足,所以基本上加速比和线程数是成正比的。
通过此次实验,我学会了如何在集群上提交任务,如何查看任务情况等,了解并行程序和串行程序的差别,在课堂上学到的理论知识通过实践可以更深刻更透彻的理解,通过实验我收获很多。