MPI-3 学习笔记(二):单边通信
MPI-3 单边通信(One-sided Communication)特性学习笔记。
基本观点:将数据交换和同步进行解耦,交换数据时不需要远端进程进行同步。
优点:
- 一些不规则的通信模式(communication pattern)可以更容易实现,不需要额外的步骤来确定要进行多少次 Send/Recv;
- 如果系统硬件支持远端内存访问(Remote Memory Access, RMA),可以比 Send/Recv 获得更好的性能。
术语:
- 源进程(Origin process):拥有源数据、发起通信的进程;
- 目标进程(Target process):拥有目标数据的进程,不需要显式调用通信函数;
- 阶段(Epoch):一个数据交换时间段;
- 断言(Assert):指示如何使用单边通信,给出『快速』优化提示。
主要函数一览:
MPI_Win_create(*base, total_bytes, unit_bytes, info, comm, *win_handle)
- 创建一个 Window 并暴露一段连续的内存给 MPI
MPI_Win_allocate(total_bytes, unit_bytes, info, comm, *baseptr, *win_handle)
- 与
MPI_Win_create
类似,但是会申请内存分配; - 可能会消耗更少的资源,应该尽可能使用!
- 与
MPI_Win_create_dynamic(info, comm, *win_handle)
- 创建一个 Window, 但是不绑定暴露的内存;
- 只有在使用
MPI_Win_attach
绑定了暴露给 MPI 的内存以后,其他进程才能使用。
MPI_Get/Put(*local_buf_addr, local_buf_entry_count, local_entry_datatype, target_rank, target_entry_offset, target_entry_datatype, win_handle)
- 非阻塞;
- 冲突访问时系统的行为是未定义的;
Rput/Rget
:有 Request 句柄的版本,也是非阻塞的,但是开销更大。
MPI_Accumulate(*local_buf_addr, local_buf_entry_count, local_entry_datatype, target_rank, target_entry_offset, target_entry_datatype, op, win_handle)
- 逐个元素的 原子操作,类似于
MPI_Put
; - 仅支持预定义的操作;
- 允许冲突访问,此时会根据 ordering rules 来进行操作。
- 逐个元素的 原子操作,类似于
MPI_Get_accumulate(<local_src_params>, <local_get_result_params>, <target_params>, op, win_handle)
- 从
*target*
处取数据存到*result*
,然后将*local_src*
的数据累加操作到*target*
处。
- 从
MPI_Fetch_and_op(*local_entry_addr, *result_entry_addr, datatype, target_rank, *target_entry_offset, op, win_handle)
- 单个元素版本的
MPI_Get_accumulate
,
(MPI_Compare_and_swap
参数太复杂了我没看明白……)
- 单个元素版本的
RMA 同步模型:解决如下问题:一个进程什么时候可以读写远端进程的数据?X 进程写的数据 Y 进程什么时候可以用?
- Fence:主动同步
- 在同一个 “win” 组中的所有进程都需要调用
MPI_Win_fence
来启动一个数据交换阶段; - 数据交换阶段中所有进程都可以发出读写操作请求;
- 在同一个 “win” 组中的所有进程都需要调用
MPI_Win_fence
来结束一个数据交换阶段; - 第二次 fence synchronization 完成时所有的操作请求都已完成;
- 比较适用于 BSP 模式的程序,比如需要边界交换程序或者稠密线性代数程序(用
MPI_Get
,MPI_Put
来代替MPI_Allgather
,MPI_Send/Recv
)。
- 在同一个 “win” 组中的所有进程都需要调用
- PSCW 同步:主动同步
- 和 fence 类似,但源进程和目标进程指出他们可以和哪一个组的进程进行通信;
- 目标进程:启动一个暴露阶段(Exposure Epoch):
MPI_Win_post
打开,MPI_Win_wait
关闭; - 源进程:启动一个访问阶段(Access epoch):
MPI_Win_start
打开,MPI_Win_complete
关闭。
- Lock/Unlock:被动同步
- 单边非同步通信;
- 目标进程不主动参与通信过程;
MPI_Win_lock
/MPI_Win_unlock
开始/结束被动通信阶段;- 独占/共享 模式决定了其他进程能否取得目标进程的锁(使用目标进程的数据),使用独占模式时只有源进程调用 unlock 以后才会释放目标进程的锁;
MPI_Win_flush
:完成所有还没完成的操作;- 类似的函数:
MPI_Win_lock_all
/MPI_Win_unlock_all
, lock/unlock 源进程以外所有其他进程
如何选择使用的模式:
- 主动模式: Bulk synchronization, 如交换 ghost cell;
- 被动模式:非同步数据交换,或者数据很大时。
内存模型:
- 统一模式:公共和私有的 window 是同一片内存;
- 分隔模式:公共和私有的 window 不是同一片内存,但 MPI 提供软件保证的一致性。
- 这两种模式的语义都非常复杂……
发布于
tags:
{ MPI }