About HPC
Applications

HPC Programming Models
Memory Sharing & Sync
- Shared Memory Model: (OpenMP, pThreads, …)
- 传统的物理上共享的内存区域较难实现,常用于单节点多核
- SHMEM: Symmetric Hierarchical MEMory
- 用于并行计算系统的单边通信库
- 是一种 PGAS 的实现
- 通过库函数直接访问对称内存区域中的远程数据,而不需要显式消息传递
- 对称:结构完全一致,运行时可以根据本地指针推断远程指针地址,适合 DP
- OpenSHMEM
- DSM: Distributed Shared Memory
- 在物理上是分布式内存,但通过软件或硬件提供全局共享内存视图
- 底层会处理一致性和通信
- Implementations: TreadMarks, Ivy…
- Distributed Memory Model: Message Passing (MPI, …)
- Message Passing Interface
- 显式地通过
send和receive等函数在进程间传递消息
- PGAS: Partitioned Global Address Space
- 一种编程模型,把整个系统的内存看作一个全局地址空间,但将其 分区 到不同进程/线程
- 每个进程只能访问自己的部分,但是也可以通过某种方式访问远程的内存
- 既能方便访问远程数据,又能优化数据局部性
- 内存模型中包含“本地”和“远程”部分,程序员对数据分布有显式控制
- UPC (Unified Parallel C), Coarray Fortran, Chapel, OpenSHMEM
- Hybrid: MPI+OpenMP, MPI+CUDA

MPI
MPI
- 进程间通信
- OpenMPI
- MPICH
- MVAPICH
- Intel MPI / IBM MPI / Microsoft MPI / …
- Objects
- Processes: Independent execution units, separate mem space.
- Communicators: Groups of procs that can communicate
- Ranks: Unique ID for procs within a communicator
- Communication Patterns
- P2P (Pair)
- Blocking:
MPI_Send,MPI_Recv- Non-Blocking:
MPI_Isend,MPI_Irecv
- Ensure sent:
MPI_Wait,MPI_Test- Collective (Group)
- Broadcast:
MPI_Bcast- Gather/Scatter ==(from/to
root)==:MPI_Gather,MPI_Scater- Reduction:
MPI_Reduce(toroot),MPI_Allreduce(to all)- One-Sided / Remote Memory Access
MPI_Put,MPI_Get- 窗口:在使用单边通信之前,进程必须明确地将一部分内存注册为一个“窗口”,允许其他进程对其进行单边访问。操作依据窗口的指定位置。
- 需要单独的同步机制(
MPI_Win_fence,MPI_Win_lock/MPI_Win_unlock, etc)来确保数据一致性和操作的完成#include <mpi.h> #include <stdio.h> int main(int argc, char** argv) { // Initialize MPI environment MPI_Init(&argc, &argv); // Get total number of processes int world_size; MPI_Comm_size(MPI_COMM_WORLD, &world_size); // Get the rank of the process int world_rank; MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); // Print a message from each processor printf("Hello from processor %d out of %d processors\n", world_rank, world_size); // Finalize the MPI environment MPI_Finalize(); return 0; }// Random Order Hello from processor 0 out of 4 processors Hello from processor 1 out of 4 processors Hello from processor 2 out of 4 processors Hello from processor 3 out of 4 processors指向原始笔记的链接
MPI_COMM_WORLD: Communicator
PGAS
- Illusion:抽象的全局的地址空间,逻辑上被所有进程分区
- Each process has affinity to a portion of the shared memory, enabling both local and remote memory accesses.(调优的时候注意优化亲和性)
- Feature
- 结合了共享内存编程的简便性与消息传递的性能
- 支持单边通信
- SPMD: Single Program Multiple Data/多数据执行
- Data Locality Awareness
- Implementations
- Lang-based: UPC (C), CAF (Fortran), X10, Chapel
- Lib-based: OpenSHMEM, Global Arrays
#include <upc.h>
shared int A[THREADS];
int main() {
A[MYTHREAD] = MYTHREAD;
upc_barrier;
printf("Thread %d sees A[0] = %d\n", MYTHREAD, A[0]);
return 0;
}Thread 0 sees A[0] = 0
Thread 1 sees A[0] = 0
Thread 2 sees A[0] = 0
Thread 3 sees A[0] = 0
shared: 逻辑上对所有 UPC 线程是可见的THREADS: 总的线程数(或进程数)
Shared Memory Model
- 多个处理器或线程访问一个公共的内存空间
- 直接读取和写入共享变量
- Features
- Global Address Space: 所有线程共享相同的内存地址空间
- Implicit Communication: 数据交换通过共享变量发生
- Thread-Based Parallelism: 通常在一个单一进程内使用线程来实现
- 架构实现
- SMP (Symmetric Multiprocessing): 所有 CPU 核心通过一个统一的总线或其他互连机制连接到共享内存。每个处理器访问任何内存地址的延迟和带宽大致相同。
- NUMA (Non-Uniform Memory Access): 处理器被组织成多个“NUMA节点”,每个节点都有自己的本地内存控制器和内存。
- 编程实现
- OpenMP, Pthreads
- 挑战
- Sync: Race condition & Deadlocks
- Scalability: 更多的线程不一定会得到更好的性能
- Memory Consistency
- Debugging difficulty
- 最佳实践
- 适当地使用同步原语
- 尽可能减少对共享数据的访问/传递:减少/私有化无用成员
- 线程安全:细粒度锁、尽量多不变性、倾向原子操作、封装
Hybrid
- 结合了多种并行编程模型(异构:CPU, GPU, Network)
- MPI: inter-node (distributed memory)
- OpenMP: intra-node (shared memory)
- CUDA/OpenACC: accelerators like GPUs
- 常见
- MPI + OpenMP - CPU Multi-cores
- MPI + Pthreads - Fine-grained
- MPI + CUDA/OpenACC - CPU + GPU
- MPI + PGAS - PGAS within nodes, MPI across
- 挑战
- 理解和管理不同模型之间的交互、数据传输和同步
- 将程序的并行结构(例如 MPI 进程的数量和 OpenMP 线程的数量)与底层硬件的拓扑结构(如节点数量、每个节点的核心数、缓存层次、NUMA 域)精确匹配
- 调试和性能分析在混合编程环境中变得更加困难
- 线程安全(尤其是
MPI_THREAD_MULTIPLE)
- 最佳实践
- Coarse-grained MPI + fine-grained OpenMP
- MPI: 大的、独立的计算任务块
- OpenMP:并行化节点内的细粒度循环或计算
- MPI process per NUMA domain
- 避免跨 NUMA 域的昂贵内存访问
- Avoid over-subscription
- Benchmark different configurations (MPI ranks vs threads)
- Coarse-grained MPI + fine-grained OpenMP
- Examples
- Climate models (气候模型): 模拟地球气候系统,涉及大量的分布式计算和节点内部的并行化。
- Fluid dynamics (流体力学): 模拟流体行为,如空气动力学、水流等,通常需要大规模并行计算。
- Deep learning frameworks (深度学习框架): 如 TensorFlow、PyTorch 等,在训练大型神经网络时,经常在分布式集群中使用 MPI 进行模型或数据并行,并在每个节点内部使用线程(通常是 GPU 上的 CUDA 线程)进行高效的矩阵运算。
CUDA
CUDA 是 NVIDIA 的并行计算平台和编程模型,它使开发人员能够利用 GPU 的海量计算能力(大规模并行)。
关键概念:
- 数十万个线程:
- 专为细粒度并行设计。GPU 并发运行大量线程。
- SIMT 执行模型:
- 线程被分组到 warps 中,以同步(单指令,多线程)方式执行。
- 分层内存:
- 全局内存: 所有线程可访问。
- 共享内存: 快速的、按块(block)划分的内存。
- 局部内存: 每个线程私有。
- 编程语言:
- 主要使用带扩展的 C/C++,并通过封装器(wrappers)支持 Python、Fortran 和其他语言。

Utils
nvidia-smi topo 分析 GPU 之间的互联结构
Assets
- NVIDIA HPC SDK
- DALI 是一个加载数据的加速模块

- Magnum IO 加速数据中心 IO 性能
- 用 NCCL 替换 MPI 可以显著提升 VASP 的性能。UCX 可以加速 VASP、Chroma、MIA-AI、Fun3d、CP2K 和 Spec-HPC2021 等科学计算应用,从而缩短运行时间。