多级混合编程概述
计算机系统的性能提升:
Scale Up(纵向扩展)模式:单个计算节点的计算能力越来越强大。
Scale Out(横向扩展)模式:可计算节点的规模越来越大。
多极化计算机的发展趋势:Scale Up + Scale Out
多级并行计算系统
| 架构 | 特点 |
|---|---|
| SMP节点 | 节点内多个处理器彼此共享内存,节点之间通过互连网络连接,编程模型为MPI+OpenMP |
| 多GPU | 单个节点内包含多个GPU(CUDA),节点之间通过互连网络连接,编程模型为MPI+CUDA |
MPI+OpenMP
MPI描述了多个进程间的并行化(独立的地址空间),通常面向分布式网络计算环境,以消息发送接收的方式进行通信。
线程并行化提供了进程内部的共享内存模式。OpenMP是一个常用的线程并行化模型,基于用户提供的编译制导语句,线程的创建和管理由编译器负责。
| 并行方法 | 优点 | 缺点 |
|---|---|---|
| MPI | 高可扩展性、高可移植性、节点间扩展 | 开发调试困难、显示通信、粗粒度划分、负载平衡困难 |
| OpenMP | 容易部署、延迟低、隐式通信、可粗细粒度划分、动态负载平 | 仅运行于共享内存机器、仅节点内可扩展、线程顺序未定义 |
MPI+OpenMP的可行性:概念上简单(两级并发),适合多核节点架构、缓解纯MPI的可扩展性问题,降低进程数和网络洪水。
单个进程内存在多个并发执行线程,所有线程共享全部的MPI对象(通信域、请求对象等),每一个线程创建多个OpenMP线程。
| 步骤 | 操作 |
|---|---|
| Step1 | 初始化MPI |
| Step2 | 在每一个MPI进程中创建一个OpenMP并行域 |
| Step3 | 在串行或并行区域调用MPI库 |
| Step4 | 结束MPI |
示例:
|
|
消息通信
单一线程通信:通信来自MPI并行区域的单一线程或者串行临界区。
多线程通信:通信来自MPI并行区域的多个线程。

线程中的MPI调用
使用MPI_Init_thread选择和决定MPI线程的支持级别。

MPI2定义了线程调用的4种情况:
Single:不支持多线程。Funneled:只有主线程能调用MPI。Serialized:多个线程可以调用MPI,但一次只允许一个线程调用。Multiple:任何线程都可以调用MPI。
MPI_THREAD_FUNNELED:需要显式调用OMP_BARRIER进行同步,此时其他线程均处在休眠状态。
|
|
MPI_THREAD_SERIALIZED:OMP_BARRIER只需要在开始时候调用,此时其他线程均处于休眠状态。
|
|
MPI_THREAD_MULTIPLE:有潜在错误和死锁风险。
计算和通信重叠
某个线程负责通信,通信过程中其他线程继续执行计算。可提升效率,但同步与负载均衡更复杂。
MPI+CUDA
硬件并发:
- GPU层:多处理器上运行的线程。
- 节点层:将CPU、GPU和网卡绑定在一起。
- 集群层:通过互连网络将不同节点连接在一起。
并发策略:节点内采用CUDA进行并发,节点间采用MPI。

CUDA和MPI分工合作:CUDA处理GPU层次的并发,MPI负责处理节点间的并发。
可以每一个GPU由一个MPI进程负责。
数据通信
设备间的数据传输方式:
- Sender:将数据从设备内存拷贝到临时的host缓冲区;将host缓冲区数据进行网络发送。
- Receiver:接收数据时将其存入host缓冲区,将数据拷贝到设备内存。
统一寻址
在host内存和device显存之间根据访问需要自动迁移数据,同时保证二者均可访问。应用程序不需要知道访问时数据所在位置。
需要进行显式同步。
其他方法
- P2P:允许同一节点内部的多个GPU直接进行内存数据拷贝,不需要经过主存。
- RDMA:将数据从GPU直接推送到网卡,然后通过网络发送到另一台机器。