mpi tutorial 介绍基本的mpi函数,源码地址
0, 基本概念
buffer, data count, data type, destination, source, tag。下述的mli函数的参数,都包括这些名词。其中buffer,就是发送/接收的变量名。c/c++中,参数按引用传递。
mpi是spmd模型,适合粗粒度并行。各节点的数据,除了通信沟通外,相互独立。
mpi_wtime(), 类似 omp_get_wtime(void)
MPI_Init() , 在mpi-2中,参数可以为null; mpi-1中,必须与main的参数一致。
一, 点对点通信
1.1 静态数据传输
MPI_Send(void* data, int count, MPI_Datatype datatype, int destination,
int tag, MPI_Comm communicator)
MPI_Recv(void* data, int count, MPI_Datatype datatype, int source,
int tag, MPI_Comm communicator, MPI_Status* status)
1.2 动态数据传输
MPI_Get_count(MPI_Status* status, MPI_Datatype datatype, int* count)
MPI_Probe(int source, int tag, MPI_Comm comm, MPI_Status* status)
mpi_probe,返回status的属性值,e.g. status.size, mpi_get_count 是访问status.size的函数
1.3 举例:随机游走
mpi策略分析:
1 域分解, 每个子域内的游走由一个mpi节点完成
2 每个子域内walker数列初始化:初始位置和总步数(随机生成)
3 每个子域内walker游走规则:所有walker均沿一个方向。当其超过子域的边界,将该walker加入 out_going_walker数列,其将与邻接的子域通信。
4 mpi通信规则: send_outgoing_walk, 将当前cpu中 outgoing_walker数列发送到下一个子域; receive_incoming_walk,接收前一个子域送来的walker数据
5 避免死锁:如果所有节点上的walkers都同步--即先send,后receive. 而network buffer不大,send数据都没法被线程接收。采用:偶数节点先发送,后接收;奇数节点,先接收后发送。如此避免死锁。
6 程序终止:给定最大步数,可以得到每个walker最大跨越的子域个数。完成这些跨越,该walker就终止了。
二, 集合通信
MPI_bcast(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)
send_data 是master进程上的数组A0,send_count表示发送给每个slave进程的单元数目。比如 send_count =1 ,则 0号进程将得A0[0], 1号进程得到A0[1],依次。
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)
MPI_Gather(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)
2.2 举例:计算平均值
1 master进程,生成随机数组, scatter到slave进程。注意各slave进程里要先开辟一个buffer,用来接收 scatter过来的 随机数组片段;
2 master进程,gather 各salve上的平均值,同样需要先开辟一个buffer,用来存储各slave平均值;
3 通信结束后,可释放上述各开辟的buffer
2.3 reduce
MPI_Reduce(void* send_data, void* recv_data, int count,
MPI_Datatype datatype, MPI_Op op, int root,
MPI_Comm communicator)
send_data, 是各slave进程中要拿来reduce的对象;recv_data是master进程中存 reduced结果的变量, count是对象/变量的长度(count =1,即一个变量;count=2,即一个长度为2的数组)
reduce 比 scatter + gather 要简洁些。
总结
mpi 算是底层的通信协议,这篇文章主要是了解下这些通信方式,当然还有很多复杂的通信模型allgather等等。mpi 在计算仿真领域的应用开发,都或多或少提供了更高层次的封装。比如petsc,以及进一步基于petsc的各类cfd/fea求解器开发,则是更上层。
根据课程进度,今后估计还有一些介绍矩阵计算,当然后期的重点是跟几个开源。barba group github