HPC 领域中,除了基于共享内存的 OpenMP, 还有一种更广泛应用于分布式内存系统的并行编程范式——消息传递接口 (MPI)。MPI 不依赖于共享内存,而是通过进程间的显式消息传递来实现数据交换和同步,从而能支持更大规模的集群计算,是构建大规模 HPC 集群不可或缺的工具。
1. What is MPI? MPI (Message Passing Interface) 是一种用于分布式内存系统并行编程的标准化通信协议和库函数规范。它定义了一套可移植的函数接口,允许在并行计算环境中独立运行的进程之间进行消息传递,从而实现数据交换和协同工作。MPI 不指定如何启动进程,也不要求所有进程在同一台机器上,这使得它非常适合用于集群或多节点环境中的大规模并行计算。
2. The MPI Programming Model 分布式内存模型
在分布式内存模型中,各个处理节点可以独立运行自己的进程,使用自己的本地内存来存储和处理数据。每个进程的内存是私有的,其他进程无法直接访问它们。如果一个进程需要访问另一个进程的数据,就必须通过显式的消息传递机制将数据从一个进程发送到另一个进程。同一个节点(服务器)内部需要借助高速数据总线等硬件实现,而跨节点的通信通常由网络连接来实现,比如通过高速以太网、IB(InfiniBand)等。
核心概念
进程 (Process):一个 MPI 程序由一个或多个独立的进程组成。这些进程通过调用 MPI 库函数来进行通信。
通信子 (Communicator):一个通信子(MPI_Comm)定义了一个可以互相通信的进程组。最常用的通信子是 MPI_COMM_WORLD,它包含了程序启动时的所有进程。
秩 (Rank):在同一个通信子内,每个进程都被赋予一个唯一的整数标识,称为秩。秩的范围是从 0 到 进程总数 - 1。
消息传递 (Message Passing):进程间通信的核心机制,分为两大类:
点对点通信 (Point-to-Point):在两个指定的进程之间进行。 集体通信 (Collective):在一个通信子内的所有进程共同参与的通信。 通信协议:MPI 提供了多种通信协议,如阻塞通信(Blocking)、非阻塞通信(Non-blocking)、同步通信(Synchronous)等。
3. Basic Functions and Concepts 一个基础的 MPI 程序总是包含初始化、执行并行代码和结束这几个部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <mpi.h> #include <stdio.h> int main(int argc, char** argv) { // 1. 初始化 MPI 环境 MPI_Init(&argc, &argv); int world_size; int world_rank; char processor_name[MPI_MAX_PROCESSOR_NAME]; int name_len; // 2. 获取通信子信息 MPI_Comm_size(MPI_COMM_WORLD, &world_size); // 获取总进程数 MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); // 获取当前进程的秩 // 获取处理器名称 (可选) MPI_Get_processor_name(processor_name, &name_len); // 3. 基于秩执行不同的代码 printf("Hello world from processor %s, rank %d out of %d processors\n", processor_name, world_rank, world_size); // 4. 结束 MPI 环境 MPI_Finalize(); return 0; } MPI_Init():初始化 MPI 执行环境,必须是第一个被调用的 MPI 函数。 MPI_Comm_size():获取指定通信子(这里是 MPI_COMM_WORLD)中的总进程数。 MPI_Comm_rank():获取当前进程在指定通信子中的秩。 MPI_Finalize():清理并结束 MPI 环境,必须是最后一个被调用的 MPI 函数。 4. Point-to-Point Communication 点对点通信是 MPI 中最基本的通信模式,用于在一个进程向另一个进程发送数据。核心操作是 Send 和 Recv。
...