
模式 | 特点 | 典型工具 |
|---|---|---|
共享内存(Shared Memory) | 多线程访问同一内存空间 | OpenMP, Pthreads |
分布式内存(Distributed Memory) | 每个节点有独立内存,通过网络通信 | MPI |
混合模型(Hybrid) | 结合两者优势,节点内用 OpenMP,节点间用 MPI | MPI + OpenMP/CUDA |
MPI:主要用于分布式内存系统,适合跨多个服务器节点的大规模并行任务。
MPI 是一种标准化的消息传递库接口,定义了进程之间如何发送和接收数据。其核心思想是:
关键优势:
应用领域 | 使用场景 | 是否依赖 MPI |
|---|---|---|
气象预报(WRF) | 大气网格划分与同步更新 | 是 |
流体力学(OpenFOAM) | 分布式求解 Navier-Stokes 方程 | 是 |
分子动力学(LAMMPS) | 粒子间力的并行计算 | 是 |
地震波模拟(SPECFEM3D) | 波场传播的域分解 | 是 |
AI 数据预处理 | 分布式读取 TFRecord/HDF5 文件 | 可选但高效 |
统计数据:据 Open MPI 官方报告,超过 90% 的 Top500 超算系统默认安装 MPI 实现。
(1) HPC 集群典型架构图

(2) MPI 点对点通信流程图

发送先于接收:虽然两个进程可能在不同时间点调用函数,但数据传输动作本身(斜线箭头)必须始于发送方,终于接收方。Rank 1 即使很早就调用了 Recv,也必须等到 T4 时刻数据真正到达才算完成。
(3) MPI 集合通信 — Allreduce 示例

所有进程最终获得相同的结果(如梯度平均),常用于 AI 分布式训练。
sudo apt update
sudo apt install openmpi-bin libopenmpi-devsudo dnf install openmpi openmpi-develCentOS 7推荐安装 openmpi3 ,openmpi 的版本过低:
sudo yum install openmpi3 openmpi3-devel推荐选择 OpenMPI:社区活跃、文档丰富、支持 GPU 直接通信(CUDA-aware)
module load mpi/openmpi3-x86_64如果出现 -bash: module: command not found,使用source /etc/profile.d/modules.sh再加载
mpirun --version
mpicc --showme输出应类似:
mpirun (Open MPI) 3.1.3
...
创建测试目录:
mkdir ~/mpi-demo && cd ~/mpi-demo编写一个简单的 hello.c:
#include <mpi.h>
#include <stdio.h>
int main(int argc, char** argv) {
MPI_Init(&argc, &argv);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
printf("Hello from process %d of %d\n", rank, size);
MPI_Finalize();
return 0;
}编译并运行:
mpicc -o hello hello.c
mpiexec -n 8 ./hello输出:

如果出现:
[1764820148.412669] [compute01:10228:0] sys.c:618 UCX ERROR shmget(size=2097152 flags=0xfb0) for mm_recv_desc failed: Operation not permitted, please check shared memory limits by 'ipcs -l'
[1764820148.414829] [compute01:10229:0] sys.c:618 UCX ERROR shmget(size=2097152 flags=0xfb0) for mm_recv_desc failed: Operation not permitted, please check shared memory limits by 'ipcs -l'
[1764820148.412682] [compute01:10230:0] sys.c:618 UCX ERROR shmget(size=2097152 flags=0xfb0) for mm_recv_desc failed: Operation not permitted, please check shared memory limits by 'ipcs -l'
[1764820148.414706] [compute01:10233:0] sys.c:618 UCX ERROR shmget(size=2097152 flags=0xfb0) for mm_recv_desc failed: Operation not permitted, please check shared memory limits by 'ipcs -l'
[1764820148.416116] [compute01:10235:0] sys.c:618 UCX ERROR shmget(size=2097152 flags=0xfb0) for mm_recv_desc failed: Operation not permitted, please check shared memory limits by 'ipcs -l'
[1764820148.421206] [compute01:10236:0] sys.c:618 UCX ERROR shmget(size=2097152 flags=0xfb0) for mm_recv_desc failed: Operation not permitted, please check shared memory limits by 'ipcs -l'
[1764820148.421431] [compute01:10237:0] sys.c:618 UCX ERROR shmget(size=2097152 flags=0xfb0) for mm_recv_desc failed: Operation not permitted, please check shared memory limits by 'ipcs -l'
[1764820148.421575] [compute01:10239:0] sys.c:618 UCX ERROR shmget(size=2097152 flags=0xfb0) for mm_recv_desc failed: Operation not permitted, please check shared memory limits by 'ipcs -l'
Hello from process 0 of 8
Hello from process 1 of 8
Hello from process 2 of 8
Hello from process 3 of 8
Hello from process 4 of 8
Hello from process 5 of 8
Hello from process 6 of 8
Hello from process 7 of 8这是OpenMPI + UCX(Unified Communication X)在 CentOS 7 上因共享内存限制导致的警告:
ipcs -l
------ Messages Limits --------
max queues system wide = 32000
max size of message (bytes) = 8192
default max size of queue (bytes) = 16384
------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 18014398509465599
max total shared memory (kbytes) = 18014398442373116
min seg size (bytes) = 1
------ Semaphore Limits --------
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 32
semaphore max value = 32767可以看到:max seg size (kbytes) = 18014398509465599,限制已经非常大(接近无限),不用修改
nano /etc/security/limits.conf
# 添加如下内容:
# Increase SHM limits for MPI
* soft memlock unlimited
* hard memlock unlimited
* soft nofile 65536
* hard nofile 65536# 确保 SSH 登录时加载 limits。编辑:
sudo nano /etc/ssh/sshd_config
# 确认包含:
UsePAM yes
# 若没有包含,则添加后重启 sshd:
sudo systemctl reload sshdMPI_Init(&argc, &argv); // 必须第一个调用
// ... 中间写并行逻辑 ...
MPI_Finalize(); // 必须最后一个调用int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank); // 当前进程编号(从0开始)
MPI_Comm_size(MPI_COMM_WORLD, &size); // 总共多少个进程if (rank == 0) {
int data = 100;
MPI_Send(&data, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
} else if (rank == 1) {
int buf;
MPI_Recv(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("Received: %d\n", buf);
}注意:MPI_Recv 必须等待对应 Send 到达才会返回(阻塞式)
(1) 广播(Broadcast)
int value;
if (rank == 0) value = 42;
MPI_Bcast(&value, 1, MPI_INT, 0, MPI_COMM_WORLD); // 所有进程都得到 value=42(2) 归约(Reduce)—— 主从结构汇总
int local_sum = rank * 10;
int global_sum;
MPI_Reduce(&local_sum, &global_sum, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
if (rank == 0) {
printf("Total sum = %d\n", global_sum);
}(3) 数据分发与收集
int send_data[4] = {10, 20, 30, 40};
int recv_item;
MPI_Scatter(send_data, 1, MPI_INT, &recv_item, 1, MPI_INT, 0, MPI_COMM_WORLD);
printf("Rank %d received %d\n", rank, recv_item);输出(假设 n=4): Rank 0 received 10 Rank 1 received 20 Rank 2 received 30 Rank 3 received 40
mpicc -o myprogram myprogram.c # 编译
mpiexec -n 8 ./myprogram # 运行8个进程强制绑定到特定CPU核心(提升缓存效率)
mpiexec --bind-to core -n 4 ./hello
[用户] → 编辑代码 → 提交 .job 脚本 → [Slurm 调度器] → 分配资源 → srun 启动 mpiexec → 计算节点运行 → 输出日志
保存为 run_mpi.job:
#!/bin/bash
#SBATCH --job-name=mpi_hello
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=8
#SBATCH --time=00:10:00
#SBATCH --output=hello_%j.out
#SBATCH --error=hello_%j.err
# 加载模块(根据系统调整)
module load openmpi/openmpi3-x86_64
# 编译(可选:也可提前编译好)
mpicc -o hello hello.c
# 启动作业
srun mpiexec -n 16 ./hello参数说明:
sbatch run_mpi.jobsqueue -u $USERsacct -j <jobid>cat hello_*.out问题 | 原因 | 建议 |
|---|---|---|
Command 'mpicc' not found | 模块未加载 | 添加 module load openmpi |
作业长时间 pending | 队列拥塞 | 使用 sinfo 查看可用资源 |
运行时报错 “connection closed” | SSH 或 OFED 驱动异常 | 联系管理员检查 InfiniBand 状态 |
MPI_Request req;
MPI_Isend(buffer, count, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD, &req);
// 做其他计算...
do_local_work();
// 等待发送完成
MPI_Wait(&req, MPI_STATUS_IGNORE);优点:通信与计算重叠,提高资源利用率
技巧 | 说明 |
|---|---|
合并小消息 | 减少通信次数,提升带宽利用率 |
使用拓扑通信 | 如 Cartesian topology 优化邻域通信 |
避免热点进程 | 均衡负载,防止主节点成为瓶颈 |
启用 CUDA-aware MPI | GPU 显存直传,避免主机中转 |
Bootstrap: docker
From: ubuntu:20.04
%post
apt update
apt install -y openmpi-bin libopenmpi-dev gcc
%runscript
exec mpiexec "$@"singularity build mpi_container.sif Singularity.def
srun singularity run mpi_container.sif -n 16 ./my_mpi_app优势:环境隔离、可复现、便于部署复杂依赖
案例一:OpenFOAM 流体仿真中的 MPI 应用
案例二:天文 N 体模拟(Gadget-2)
案例三:金融蒙特卡洛期权定价
Python 伪代码(通过 mpi4py)
from mpi4py import MPI
import numpy as np
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
# 每个进程生成 10000 条路径
local_paths = generate_paths(n=10000)
local_price = np.mean(local_paths)
# 全局平均
global_price = comm.reduce(local_price, op=MPI.SUM, root=0)
if rank == 0:
final_price = global_price / size
print(f"期权价格估计: {final_price:.4f}")本地机器8个进程测试:
mpiexec -n 8 python option_pricing.py

效果:100 万次模拟仅运行3.09秒(使用 8 进程)
MPI 不仅仅是一种编程接口,它是连接算法与硬件之间的桥梁,是实现“算得更快、看得更远”的关键技术支撑。 通过本教程的学习,你应该已经能够:
但这只是起点。随着异构计算(GPU+CPU)、混合编程模型(MPI + OpenMP/CUDA)的发展,MPI 正在与其他并行范式深度融合。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。