CS267 · Homework 2.2 导读

粒子模拟并行化(MPI 分布式内存)

同一粒子模拟,但用 MPI 在分布式内存上并行——每个进程只能访问本地粒子,跨域交互靠消息传递。

📅 截止:2025-03-07 📖 Lecture 7-8 💻 C++ (MPI) 🏆 扩展性 + 性能 + 解释

与课程的关系

Lecture 7 · MPI 基础
↓
点对点通信、分区
Lecture 8 · 集合通信
↓
Allgather、Alltoall
Lecture · 分布式分解
↓
域分解、Ghost Layer
Lecture · 扩展性
↓
Strong vs Weak Scaling

任务概述

与 HW2-1 相同的粒子模拟,但现在使用 MPI 分布式内存并行。每个进程只持有部分粒子,跨进程相互作用通过消息传递完成。

关键约束
不能使用 OpenMP,所有加速必须来自 MPI

规模限制
最多 2 节点、128 核、6,000,000 粒子

可修改文件
只能修改 mpi.cpp 中的 simulate_one_step 和 gather_for_save

评分重点
扩展性(Strong/Weak Scaling)+ 性能 + 方法论解释


代码组件一览

文件 / 函数 角色 可以修改? 课程关联
mpi.cpp → simulate_one_step 单步 MPI 并行模拟:力计算 + 粒子迁移 ✅ 是 Lec 7, 8
mpi.cpp → gather_for_save 收集所有粒子位置用于输出 ✅ 是 Lec 8
common.h / common.cpp 数据结构、I/O、验证 ❌ 否 —
serial.cpp / openmp.cpp 串行/OpenMP 参考实现 ❌ 否 HW2.1

分布式并行策略

1

域分解 (Domain Decomposition)

将模拟空间划分为 p 个子域,每个进程负责一个子域内的粒子。

2

Ghost Layer / Halo Exchange

每个子域边界外扩 cutoff 距离,存储相邻进程的粒子副本(ghost particles)。

⚠️ 常见坑:Ghost Layer 的厚度必须 ≥ cutoff,否则会漏掉远距离相互作用。周期性边界条件需要特别处理角落 ghost。
3

粒子迁移 (Particle Migration)

粒子移动后可能离开当前子域,需要迁移到正确的进程。

4

力计算并行化

每个进程独立计算本地粒子与本地 + ghost 粒子的相互作用。

5

全局收集 (gather_for_save)

输出时需要把所有粒子收集到根进程。


MPI 通信原语速查

原语 用途 类型
MPI_Send / MPI_Recv 点对点阻塞通信 点对点
MPI_Sendrecv 同时发送和接收,避免死锁 点对点
MPI_Isend / MPI_Irecv 非阻塞通信,可重叠计算 点对点
MPI_Allgather 全收集:每个进程获得所有数据 集合
MPI_Alltoallv 全交换:不规则数据分布 集合
MPI_Barrier 全局同步 集合

通信是分布式并行的最大敌人。 你的目标是最小化通信量、最大化计算/通信重叠。Ghost Halo 的厚度、迁移频率、Alltoallv 的数据分布——每一个选择都影响扩展性。


扩展性分析要点

扩展性类型 定义 关注指标
Strong Scaling 固定问题规模,增加处理器数 S = T₁ / Tₚ,理想 = p
Weak Scaling 固定每处理器问题规模,增加处理器数 E = T₁ / Tₚ,理想 = 1
通信开销 T_comm / T_total 随 p 的变化 应尽可能小
负载均衡 最大 / 平均负载比 理想 = 1

常见陷阱

⚠️ 死锁: 阻塞通信 MPI_Send / MPI_Recv 顺序不当会导致死锁。优先使用 MPI_Sendrecv 或非阻塞通信。
⚠️ 负载不均: 粒子分布不均匀时,某些进程空闲等待。考虑自适应域分解或动态负载均衡。
⚠️ 通信爆炸: 每步都做 MPI_Allgather 会让通信量 O(p) 增长。只在必要时收集数据。
⚠️ 忘记 PBC: 周期性边界条件下,ghost 粒子位置需要正确 wrap,否则力计算出错。

自测 Quiz

Q1. Ghost Layer (Halo) 的厚度应该如何选择?

Q2. 粒子迁移时,应该使用哪个 MPI 原语?

Q3. 在 3D 空间模拟中,哪种域分解的通信量最小?

Q4. 在 HW2.2 中,能否使用 OpenMP 加速单个 MPI 进程的计算?

Q5. 关于 Strong Scaling 和 Weak Scaling,以下哪项正确?