MPI入门:实现并行pagerank算法

部分代码参考自:https://www.cnblogs.com/luyi07/p/11110658.html

首先对所需要的跳跃矩阵,PR矩阵进行初始化,代码如下,由0进程负责数据的加载和初始化,然后使用MPI_Scatter将原数据分块后分散到各个进程中去。分块操作由MPI_Scatter自行完成。MPI_Scatter函数接口如下:

int MPI_Scatter(void*            send_buf_p,     /* IN */int             send_count,     /* IN */MPI_Datatype    send_type,      /* IN */void*           recv_buf_p,     /* OUT */int                recv_count,     /* IN */MPI_Datatype    recv_type,      /* IN */int             src_proc,       /* IN */MPI_Comm        comm            /* IN */)

其中send_count是为每个进程分配数据的大小,一般为data_count/comm_size,数据总数除以进程数。注意这里0进程使用MPI_Scatter进行分散的时候,0进程依然会得到“一块“数据的。其次,需要考虑分散后剩余数据的处理(可能存在均匀分配后剩余的数据)。参数src_proc确定了发送进程的编号。

#include<fstream>
#include<mpi.h>
#include<iostream>
using namespace std;
bool IniData(double m[],        //全局邻居矩阵double local_m[], //存放分片的邻居矩阵double pr[],       //进程计算的PR值double b[],       //原始的PR值int line,         //分片大小int size,         //网页数int my_rank,      //进程编号MPI_Comm comm     //通信子)
{if(my_rank==0){//初始化邻接矩阵、PR矩阵和初始PR矩阵for(int i=0;i<size;i++){for(int j=0;j<size;j++){m[ i*size + j ] = 0;}b[i] = 1/(double)size;pr[i] = 1/(double)size;}//从文件中读取数据ifstream Input;Input.open("data.txt");int s,d;while(Input >>s >>d){m[ d*size + s] =1;}//变为转移矩阵for(int i=0;i<size;i++){int cout=0;for(int j=0;j<size;j++){  if(m[j*size+i]==(double)1)cout++;}if(cout>0){for(int k=0;k<size;k++){ m[k*size+i]=m[k*size+i]/(double)cout;}}}//将分块的数据分发给各个进程,包括自己。MPI_Scatter(m, line * size, MPI_DOUBLE, local_m, line * size, MPI_DOUBLE, 0, comm );}else{//接受转移矩阵MPI_Scatter(m, line * size, MPI_DOUBLE, local_m, line * size, MPI_DOUBLE, 0, comm );}return true;
}

对于0进程调用MPI_Scatter为发送数据块给各个进程,对于其他进程,MPI_Scatter是接受0进程发送的数据块。另外MPI_Scatter是带有阻塞的,即接收方收到后才会进行后面的操作。

下面是并行计算部分的代码
int main(){double alpha=0.85;int my_rank;int num_procs;int size = 4;double start, finish;MPI_Init(NULL,NULL);MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);MPI_Comm_size(MPI_COMM_WORLD, &num_procs);int line = size / num_procs;cout<<" line = "<<line<<endl;double  m[size*size];           //整体的转移矩阵double  local_m[ line * size ]; //分发到各个进程中的分片矩阵信息double  b [size];               //初始概率矩阵,用于 计算陷阱问题double  pr[size];               //计算PR值double  local_pr[line];//初始化个数据并发送给各进程IniData(m,local_m,pr,b,line,size,my_rank,MPI_COMM_WORLD);//所以Barrier是在点对点通信中才需要,这里不需要//MPI_Barrier(MPI_COMM_WORLD);for(int it=0;it<10;it++){if( my_rank == 0 ){//start = MPI_Wtime();//广播每轮的pr值MPI_Bcast(pr, size, MPI_DOUBLE, 0, MPI_COMM_WORLD);//进程0计算自己分到的块for(int i= 0; i< line;i++){double temp = 0;for(int j=0;j<size;j++){temp += local_m[i*size+j] * pr[j];}local_pr[i] = temp;}//进程0负责计算分配之后剩下的for(int i= num_procs *line; i< size;i++){double temp = 0;for(int j=0;j<size;j++){temp += m[i*size+j] * pr[j];}pr[num_procs *line] = temp;}//获取其他进程矩阵相乘后的结果MPI_Gather( local_pr, line, MPI_DOUBLE, pr, line, MPI_DOUBLE, 0, MPI_COMM_WORLD );//for(int i=0;i<size;i++)//    cout<<pr[i]<<endl;//修正后的公式for(int i=0;i<size;i++){pr[i]=alpha*pr[i]+(1-alpha)*b[i];// cout<<"pr"<<pr[i]<"\t";}//MPI_Bcast(pr,size,MPI_DOUBLE,0,MPI_COMM_WORLD);if(it==9){FILE *fp = fopen("result.txt","w");for(int i=0;i<size;i++){// for(int j=0;j<size;j++)fprintf(fp,"%lf\t",pr[i]);fputc('\n',fp);}fclose(fp);}//finish = MPI_Wtime();//printf(" time: %lf s \n", finish - start );}else{//double * buffera = new double [ line*size ];//double * bufferc =new double [size];//接受PR矩阵MPI_Bcast(pr, size, MPI_DOUBLE, 0, MPI_COMM_WORLD);
//            for(int i=0;i<size;i++)
//            {//                cout<<"第"<<it<<"次 pr"<<pr[i]<<"\t";
//            }/*cout<<" b:"<<endl;for(int i=0;i<size;i++){for(int j=0;j<size;j++){cout<<b[i*size + j]<<",";}cout<<endl;}*/for(int i= 0; i< line;i++){double temp = 0;for(int j=0;j<size;j++){// cout<<"local_m"<<local_m[i*size+j]<<"pr"<<pr[j]<<endl;temp += local_m[i*size+j] * pr[j];}local_pr[i] = temp;//cout<<"local_pr"<<local_pr[i]<<"\t";}/*cout<<" ans:"<<endl;for(int i=0;i<line;i++){for(int j=0;j<size;j++){cout<<ans[i*size + j]<<",";}cout<<endl;}*/MPI_Gather(local_pr, line, MPI_DOUBLE, pr, line, MPI_DOUBLE, 0, MPI_COMM_WORLD );//delete [] buffera;}//MPI_Barrier(MPI_COMM_WORLD);}// delete [] m, b, local_m, pr;MPI_Finalize();return 0;
}

函数接口MPI_Scatter()是一对多的发送接口,而MPI_Gather()则是多对一的发送接口了,由各个进程计算完成后使用MPI_Gather()将计算结果发送给进程0做最后的汇总。MPI_Gather()的原型为:

int MPI_Gather(void*             send_buf_p,     /* IN */int             send_count,     /* IN */MPI_Datatype    send_type,      /* IN */void*           recv_buf_p,     /* OUT */int                recv_count,     /* IN */MPI_Datatype    recv_type,      /* IN */int             dest_proc,      /* IN */MPI_Comm        comm            /* IN */)

MPI_Bcast()是用来进行组内广播的,在每次迭代开始之前,将上一轮计算结果广播给各个进程用来进行下一次计算。使用集合通信的方法来实现pagerank算法是同步并行计算,其次使用矩阵存储的话,比较占内存空间,所以需要做很多优化,之后会慢慢改进。

MPI实现并行pagerank相关推荐

  1. 利用MPI实现并行排序算法PSRS

    参考 MPI实现psrs MPI并行正则采样排序PSRS算法原理及实现 实验题目 利用MPI实现并行排序算法PSRS 实验环境 操作系统 编译器 硬件配置 Ubuntu 16.04 mpicc 双核 ...

  2. 高性能计算实验——矩阵乘法基于MPI的并行实现及优化

    高性能计算实验--矩阵乘法基于MPI的并行实现及优化 1.实验目的 1.1.通过MPI实现通用矩阵乘法 1.2.基于MPI的通用矩阵乘法优化 1.3.改造实验1成矩阵乘法库函数 2.实验过程和核心代码 ...

  3. mpi并行 java_【并行计算】用MPI进行分布式内存编程(一)

    通过上一篇关于并行计算准备部分的介绍,我们知道MPI(Message-Passing-Interface 消息传递接口)实现并行是进程级别的,通过通信在进程之间进行消息传递.MPI并不是一种新的开发语 ...

  4. Linux下用eclipse调试C++并行程序(MPI)

    Linux下用eclipse调试C/C++并行程序(单机MPI) 并行调试工具 很多人调试MPI程序都是用print的,这里有一篇介绍的文章:https://segmentfault.com/a/11 ...

  5. 关于mpi的理论知识以及编写程序来实现数据积分中的梯形积分法。

    几乎所有人的第一个程序是从"hello,world"程序开始学习的 #include "mpi.h" #include <stdio.h> int ...

  6. 并行程序设计(MPICH环境配置)win10

    下载安装msmpisdk.msi和msmpisetup.exe 下载网址:Downloads | MPICH 进去后选择最新版下载: 点击下载: 然后全选: 下载完成后直接安装即可. 配置环境 新建W ...

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

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

  8. 基于mpi的奇偶排序_基于MPI的PSRS并行排序算法的实现

    基于MPI的PSRS并行排序算法的实现 摘 要本文介绍MPI并行编程环境和讨论和分析PSRS的并行排序算法,并在MP并行编程环境下实现PSRS的并行排序算法. 关键词PSRS:MPI:并行计算:消息传 ...

  9. anaconda安装支持mpi并行化的h5py

    anaconda安装支持mpi并行化的h5py 参考github上面的提问,可以用conda install -c conda-forge "h5py>=2.9=mpi*"通 ...

最新文章

  1. python 需要多久能够学精通_python入门到精通需要学多久-史上最详细python学习路线-从入门到精通,只需5个月时间...
  2. K8s-V1.17.6支持GPU
  3. mysql item_MySQL源代码:关于MySQL的Item对象
  4. java html写入到word文档_java 使用jacob将html页面写入word
  5. android自定义View学习(二)----自定义绘图
  6. Hive命名空间-自定义变量
  7. 反馈抑制器使用场景与市场
  8. Learn Git Branching 笔记
  9. r语言变量长度不一致怎么办_R语言实现数据离散化方法总结
  10. Charles手机的代理配置与证书的安装
  11. 安卓开发教你监听手机Home键
  12. yapi文档转换jmx脚本
  13. 企业邮箱邮件撤回可撤回几次?邮件误删恢复怎么用?
  14. BZOJ 1367 [Baltic2004]sequence
  15. 太阳高度角计算题_太阳高度练习题
  16. 美丽的汤 xlsx格式 csv 格式
  17. Linux more命令的简单实现
  18. MySQL与Python最详细的使用文档
  19. 将ibd恢复进数据库
  20. 阿里大数据之-分析型数据库 AnalyticDB(技术架构及主要组件工作原理详解)

热门文章

  1. 【XJTUSE 计算机组成与结构笔记】第六章 外存
  2. Tomcat多实例与负载均衡
  3. 小学数学第3册计算机教案,小学数学教案,小学数学教学设计
  4. 分糖问题和插板法:10个相同糖果分给3个小朋友,有几种分法?
  5. (Codeforce 757)E. Bash Plays with Functions(积性函数)
  6. thinkpad t480 简介文章
  7. python求图形面积_如何使用python语言中的if语句实现求取图形面积
  8. Mongo第三个参数的用法
  9. 超详细——手把手教你用threejs实现一个酷炫的模型发光扫描效果(一)
  10. LCD12864 液晶显示-汉字及自定义显示(串口)