您的位置:首页 > 大数据 > 云计算

mpi求前缀和

2015-12-03 01:13 447 查看

1.数据分成n份(n是进程数),然后每个进程单独求和,
2.把每个进程的最后一位数传到下面的进程里面。然后在每个接下来的进程里面最后一位数加上这个数,此时每个进程的最后一位数都是真正的前缀和
3.把每一个进程的的最后一位数传到下面一个进程,下面那个进程里面除了最后一位数,其他所有数都加上这个数。求得前缀和。
4.收集到一起。
下面是代码:

/*
1.求前缀和,利用的方法是scan
2.求前缀和,但是还是不能运行。
*/

#include <mpi.h>

#include <iostream>
#include <time.h>
using namespace std;
//开一个40000的数组
//改变这个值可以改变测试量的大小
const int maxn = 40000;
int a[maxn];

int main(int argc, char **argv)
{
//int i;
int b[maxn];
int p=0;
int senddata,recvdata;
int receiver , sender;
int my_rank=0;
int tag;
int n=5;
const int maxn1=maxn/4;
for ( int i = 0; i <= maxn; i++)
{
a[i] = i+1;
//b[i] = i;
}
int begin1=clock();
std::cout << "begin: " << begin1<<std::endl;
//mpi的初始化
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD,&p);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Status status;

int c[maxn1];
int temp = my_rank*maxn1;
//各个进程单独求和
for (int i = 1; i < maxn1; i++ )
{
c[i] = c[i]+c[i-1];
}
MPI_Barrier(MPI_COMM_WORLD);
//发送数据,每个进程都给下面的所有进程发
senddata=c[maxn1-1];
tag =1;
for ( int i = 1; i<p-my_rank;i++)
MPI_Send(&senddata,1,MPI_INT,my_rank+i,tag,MPI_COMM_WORLD);

//接受数据
if(my_rank!=0){
for (int i = my_rank; i>0;i--){
MPI_Recv(&receiver,1,MPI_INT, my_rank-i,tag, MPI_COMM_WORLD,&status);
//std::cout << "this is process: " << my_rank<< " , i receive " << receiver << endl;
c[maxn1-1]=c[maxn1-1]+receiver;

}
}
MPI_Barrier(MPI_COMM_WORLD);
//再次发送数据,只给下面的那一个
senddata=c[maxn1-1];
tag =2;
if(my_rank!=p-1)
MPI_Send(&senddata,1,MPI_INT,my_rank+1,tag,MPI_COMM_WORLD);

if(my_rank!=0){
MPI_Recv(&receiver,1,MPI_INT, my_rank-1,tag, MPI_COMM_WORLD,&status);
for ( int i = 0; i < maxn1-1; i++ )
{
c[i]=c[i]+receiver;
}
}
/*
for ( int i = 0; i < maxn1; i++ )
{
std::cout << c[i]<< " " ;
}
std::cout << endl;
*/
MPI_Barrier(MPI_COMM_WORLD);
//注释里面的一堆和下面的手机是相同作用。
/*
if(my_rank!=0)
MPI_Send(&c[0],maxn1,MPI_INT,0,tag,MPI_COMM_WORLD);
if(my_rank==0)
{
for (int i = 1; i<4; i++)
MPI_Recv(&b[i*maxn/4],maxn1,MPI_INT,i ,tag, MPI_COMM_WORLD,&status);
for ( int i = 0; i < maxn1; i++)
{
b[i]=c[i];
}
}
*/
//不知道为什么gather不能用。
//请千万小心此处的maxn1,不是maxn,不然就是出错。(默认按照这么大来拼接)

MPI_Gather(&c[0],maxn1, MPI_INT, &b[0], maxn1, MPI_INT, 0, MPI_COMM_WORLD);
if(my_rank==0)
{

int end1 = clock();
printf("耗费时间 is %d\n",end1-begin1);
}
/*
if(my_rank==0)
{
for ( int i = 0; i < maxn; i++ )
{
std::cout << b[i]<< " " ;
}
}
*/

MPI_Finalize();
//system("pause");
return 0;
}

下面是一点总结:
1.mpi的几个进程不是从ini开始,也不是从哪里结束。从一开始就开始了。也没有结束。

2.计算时间还是不要用mpi自带的MPI_Wtime了。clock,单位ms

3.发现在主进程已经得到结果的情况下,其他进程并没有结束。而是继续运行

  所以计算时间只能计算主进程的时间。当然,为什么其他进程还要运行很长时间

  而不是直接被杀死(已经finalize过了)还不知道。

4.mian函数之外的值好像只属于主进程

5.对于收集(MPI_Gather)操作,小心RecvCount指的是从每个进程里面接受的数目,不是

  总得数目。这个要小心
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mpi 并行计算 云计算