MPI学习笔记

MPI学习笔记文章目录 MPI 学习笔记 MPI 准备概述前置知识补充环境部署 1 修改 IP 及主机名 2 关闭防火墙 3 实现免密码 SSH 登录 4 配置 MPI 运行环境 5 测试程序的执行编译语句运行语句 MPI 编程 4 个基本函数 MPI 点对点通信函数非阻塞 MPI Send MPI Recv 阻塞 MPI IsendMPI 集合通信函数 1 n n 1n n 常用函数测试案例 sendMPI Scatter 与 MPI GatherMPI 学习笔记研究课题需要用到并行化 这里记录学习笔记 MPI 准备概述 MPI MessagePassi

MPI学习笔记

研究课题需要用到并行化,这里记录学习笔记

MPI准备

概述

前置知识补充

消息传输:从一个处理器的内存拷贝到另一个处理器内存的方式。
在分布式存储系统中,数据通常以消息包的形式通过网络从一个处理器发送到另一个处理器。

消息包 = 消息头控制信息 + 消息体数据信息

环境部署

三台虚拟机均为CentOS8,一台作为控制节点,另外两台作为计算节点。

1.修改IP及主机名
2.关闭防火墙

为了mpi运行成功,尽可以能降低通信延迟和系统开销,关闭防火墙达到最高的效率

关闭firewalld

[ranan@c105 ~]$ sudo systemctl stop firewalld //关闭防火墙 [ranan@c105 ~]$ sudo systemctl disable firewalld //设置防火墙不自启 

关闭selinux
1.暂时关闭

setenforce 0 
[ranan@c105 ~]$ sudo vim /etc/sysconfig/selinux [ranan@c105 ~]$ cat /etc/sysconfig/selinux # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=disabled # SELINUXTYPE= can take one of these three values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted 
3.实现免密码SSH登录

这个是之前配置hadoop免密登录的流程

4.配置MPI运行环境

三台主机都需要配置

下载包

上传包到/opt/software

[root@c105 software]# rz rz waiting to receive. zmodem trl+C ȡ 正在传输 mpich-3.1.3.tar.gz... 100% 11218 KB 11218 KB/ 00:00:01 0 [root@c105 software]# ll 总用量 11220 -rw-r--r--. 1 root root  11月 17 16:48 mpich-3.1.3.tar.gz 

解压包到/opt/module/

[root@c105 software]#tar -xvzf mpich-3.1.3.tar.gz -C /opt/module/ 

执行配置操作,作用是对即将安装的软件进行配置,检查当前的环境是否满足要安装软件的依赖关系。参数:–prefix=PREFIX 表示把所有文件装在目录PREFIX下而不是默认目录下。本系统安装目录为/home/mpi。配置成功后,最后一行提示显示“Configuration completed”。

[ranan@c105 mpich-3.1.3]$sudo ./configure --prefix=/home/mpi 

image

[ranan@c105 mpich-3.1.3]$ make [ranan@c105 mpich-3.1.3]$ make install 

配置环境变量/home/mpi

[ranan@c105 ~]$ vim ~/.bashrc export PATH=/home/mpi/bin:$PATH //与原来使用:进行拼接 export INCLUDE=/home/mpi/include:$INCLUDE export LD_LIBRARY_PATH=/home/mpi/lib:$LD_LIBRARY_PATH [ranan@c105 ~]$ source .bashrc //更新环境配置 

测试是否配置成功

which mpicc 

分发给c106 c107

Utunbu MPI安装

安装教程

5.测试

复制测试例子到/home/mpi目录下,修改/home/mpi文件权限

[root@c106 mpich-3.1.3]# cp -r examples /home/mpi [root@c106 mpich-3.1.3]# chown -R ranan:ranan /home/mpi 

单节点测试
现在是c106节点机

[ranan@c106 ~]$ cd /home/mpi/examples/ [ranan@c106 examples]$ m Process 0 of 6 is on c106 Process 1 of 6 is on c106 Process 2 of 6 is on c106 Process 4 of 6 is on c106 Process 5 of 6 is on c106 Process 3 of 6 is on c106 pi is approximately 3.31239, Error is 0.000000000 wall clock time = 0.019008 

多节点测试
测试6个进程再不同权重的节点机上运行

[ranan@c106 examples]$ vim nodes [ranan@c106 examples]$ cat nodes c105:3 c106:2 c107:1 [ranan@c106 examples]$ mpirun -np 6 -f nodes ./cpi Process 3 of 6 is on c106 Process 0 of 6 is on c105 Process 5 of 6 is on c107 Process 4 of 6 is on c106 Process 1 of 6 is on c105 Process 2 of 6 is on c105 pi is approximately 3.31243, Error is 0.000000000 wall clock time = 0.005398 

程序的执行

编译语句

c
gcc编译器

mpicc -O2(优化选项) -o(生成可持续文件) heeloworld(编译成的执行文件名) helloworld.c(被编译的源文件)

c++
gcc编译器

mpicxx -O2(优化选项) -o heeloworld helloworld.c

运行语句

mpi普通程序运行执行
mpirun(mpiexec) -np 产生的进程数 可执行文件

集群mpi上运行
集群作业调度系统特定参数 + 可执行文件

mpirun -np 产生的进程数 -f 集群配置文件 ./可执行文件

集群配置文件的格式

ip地址:进程个数 ip地址:进程个数 ... 

MPI编程

image

C语言中的头文件 #include "mpi.h"

4个基本函数

MPI点对点通信函数

MPI的通信机制是在一对进程之间传递数据,称为点对点通信

MPI提供的点对点通信数据传输有两种机制

  • 阻塞:等消息从本地发出之后,才进行执行后续的语句
  • 非阻塞:不需要等待,实现通信与计算的重叠
非阻塞MPI_Send/MPI_Recv

MPI_Send用于发送方

MPI_Send(void*buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm)

  • buf 发送的数据缓存区的起始地址
  • count 需要发送数据的个数
  • datatype 需要发送的数据类型
  • dest 目的进程的标识号
  • tag 消息标志为tag
  • comm 进程所在的域

MPI_Recv用于接收方

MPI_Recv(void*buf,int count,MPI_Datatype datatype,int source,int tag,MPI_Comm comm,MPI_Status *status)

从comm通信域中标识号为source的进程,接受消息标记为tag,消息数据类型为datatype,个数为count的消息并存储在buf缓冲区中,并将该过程的状态信息写入status中

阻塞MPI_Isend

Isend
int MPI_Isend(void*buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm,MPI_Request *request)

Irecv
int MPI_Irecv(void*buf,int count,MPI_Datatype datatype,int dest,int tag,MPI_Comm comm,MPI_Request *request)

MPI集合通信函数

image

1-n/n-1

集合通信还包括一个同步操作Barrier,所有进程都到达后才继续执行

MPI_Bcast(void *buffer,int count,MPI_Datatype datatype,int root,MPI_Comm comm)

从指定的一个根进程中把相同的数据广播发送给组中的所有其他进程

image

MPI_Scatter(void send_data,int send_count,MPI_Datatype send_datatype,void recv_data,int recv count,MPI_Datatype recv_datatype,int root,MPI_Comm communicator)

把指定的根进程中的数据分散发送给组中的所有进程(包括自己

image

MPI_Gather(void *sendbuf,int sent_count,MPI_Datatype send_datatype,void *recv_data,int recv_count,MPI_Datatype recv_datatype,int root,MPI_Comm communicator)

image

MPI_Reduce(void *send_data,void *recv_data,int count,MPI_Datatype datatype,MPI_Op op, int root,MPI_Comm communicator)

在组内所有的进程中,执行一个规约操作(算术等),并把结果存放在指定的一个进程中

image

举例

image

n-n

image

image

常用函数

案例

double start_time,end_time,total_time; //初始化 start_time = MPI_Wtime(); //需要计时的部分 end_time = MPI_Wtime(); total_time = end_time - start_time Printf("It looks %f seconds\n",total_time); 
//MPI_MAX_PROCESSOR_NAME代表MPI中允许机器名字的最大长度 int resultlen; char processor_name[MPI_MAX_PROCESSOR_NAME]; MPI_Get_processor_name(processor_name,&resultlen);//resultlen存放长度 cout"当前运行的机器" < 
  

测试案例

send

home/mpi/example/send_test.cpp

#include 
  
    #include 
   
     #include "mpi" using namespace std; /*从0号进程发送信息,其他进程接受信息*/ int main(int argc,char argv) { int rank;//记录进程标识号 int size;//记录通讯域中的进程个数 int senddata,recvdata; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&rank); MPI_Comm_size(MPI_COMM_WORLD,&size); MPI_Status status; recvdata=0; if(rank==0){ //发送数据的进程 for(int i=1;i 
    image 

MPI_Scatter 与 MPI_Gather
#include "stdio.h" #include "mpi.h" #include "stdlib.h" #include 
       
         #include 
        
          using namespace std; const int N=2; //每个进程接受两个数据 int main(int argc,char argv){ int size,rank; //size记录总进程数,rank记录当前进程的标识号 int *send; //每个进程的发送缓存区 int *recv; //每个进程的接受缓存区 int *result; //接受其他进程发送过来的数据 int send_data[N]; //其他进程发送的数据; int i=0; int j=0; int resultlen; //记录机器名的长度 char processor_name[MPI_MAX_PROCESSOR_NAME]; //运行的机器名 MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&rank); //获得当前进程号 MPI_Comm_size(MPI_COMM_WORLD,&size); //获得总进程数,假设4个 MPI_Get_processor_name(processor_name,&resultlen); recv = (int*) malloc(N*sizeof(int)); for(;i 
         image




版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/221060.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月17日 下午7:00
下一篇 2026年3月17日 下午7:01


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号