3.3 关键概念 -------------------- 3.3.1 发送请求 (Send Request, SR) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ SR 定义发送多少数据、从哪里发送、怎样发送以及使用 RDMA 发送到哪里。 :code:`struct ibv_send_wr` 被用于实现 SR 。 3.3.2 接收请求 (Receive Request, RR) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ RR 定义要接收非 RDMA 操作数据的缓冲区。如果未定义缓冲区,并且发送者尝试发送操作或带立即数写入, 则会发送"接收未准备好 (Receive not Ready, RNR)" 错误。 :code:`struct ibv_recv_wr` 用于实现 RR。 3.3.3 完成队列 (Completion Queue, CQ) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | CQ 是一个对象,包含发送到工作队列 (Work Queue, WQ) 的已完成的工作请求 (Work Request, WR) 。 每个完成项表示该 WR 已经完成(成功完成的 WR 和未成功完成的 WR)。 | CQ 是一种机制,用于通知应用程序有关 WR 结束的信息(状态、操作码、大小、来源)。 | CQ 有 n 条完成队列项 (Completion Queue Entry)。CQE 的数目在 CQ 被创建的时候被给定。 | 轮询 CQ 时,它会从 CQ 中删除 CQE。 | CQ 是 CQE 的 FIFO (先入先出队列)。 | CQ 可以为发送队列、接收队列或两者提供服务。 | 来自多个 QP 的 WQ 可以与单个 CQ 相关联。 | :code:`struct ibv_cq` 用于实现 CQ 。 3.3.4 内存注册 (Memory Registration) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 内存注册是一种机制,允许应用程序使用虚拟地址将一组虚拟连续内存位置或一组物理连续内存位置描述为 网络适配器的虚拟连续缓冲区。 | 注册进程将固定内存页(以防止页被换出并保持物理<->虚拟映射)。 | 在注册期间,操作系统会检查被注册块的权限。 | 注册进程将虚拟到物理地址表写入网络适配器。 | 当注册内存时,会为区域设置权限。权限包括:本地写入、远程写入、原子和绑定。 | 每个 MR 都有远程密钥和本地密钥 (r_key, l_key)。本地密钥被用于本地 HCA 访问本地内存,比如在接收 操作期间。远程密钥被提供给远程 HCA ,以允许远程进程在 RDMA 期间访问系统内存。 | 相同的内存缓冲区可以被注册多次(即使使用不同的访问权限),每次注册都会产生一组不同的密钥。 | :code:`struct ibv_mr` 被用于实现内存注册。 3.3.5 内存窗口 (Memory Window) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ MW 允许应用程序对内存的远程访问进行更灵活的控制。内存窗口被用于以下场景中: - 希望动态地对被注册区域授予和撤销远程访问权限,与注销/注册或重新注册相比,性能损失较小。 - 希望对不同的远程代理授予不同的权限,或在被注册区域内的不同范围授予这些权限。 将 MW 与 MR 关联的操作成为"绑定 (binding)"。不同的 MW 可以覆盖相同的 MR (即使访问权限 不同)。 3.3.6 地址向量 (Address Vector) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 地址向量是描述从本地节点到远程节点的路由的对象。在每个 UC/RC QP 的上下文中都有一个 地址向量。在 UD QP 中,地址向量应该在每个发布的 SR 中定义。 :code:`struct ibv_ah` 被用于实现地址向量。 3.3.7 全局路由头 (Global Routing Header, GRH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | GRH 被用于在子网之间路由。当使用 RoCE 时, GRH 被用于在子网内部路由,因此是必需的。 对于同时支持 IB 和 RoCE 的应用程序,使用 GRH 是必需的。 | 当在 UD QP 上使用全局路由时,接收缓冲区的前 40 个字节中将包含一个 GRH。该区域被用于 存储全局路由信息,所以可以生成适当的地址向量以响应接收到的数据包。如果 GRH 与 UD 一起 被使用, RR 应该总是为 GRH 提供额外的 40 字节。 | :code:`struct ibv_grh` 被用于实现 GRH。 3.3.8 保护域 (Protection Domain) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 其组件只能相互交互的对象。这些组件可以是 AH、QP、MR 和 SRQ。保护域被用于将 QP 与 MR 和 MW 关联起来,作为使能和控制网络适配器对主机系统内存访问的一种方法。PD 也被用来将 UD QP 与 AH 关联起来,作为控制对 UD 目的地访问的一种方法。 :code:`struct ibv_pd` 被用于实现 PD。 3.3.9 异步事件 (Asynchronous Events) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 网络适​​配器可以发送异步事件以向SW通知系统中发生的事件。 有两种异步事件类型: - 附属事件 (Affiliated events): 发生在私有对象 (CQ、QP、SRQ) 上的事件。这些事件将被发送 到特定的进程。 - 非附属事件 (Unaffiliated events): 发生在全局对象 (网络适配器、端口错误) 的事件。这些事件 将被发送给所有的进程。 3.3.10 集散 (Scatter Gather) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 使用集散元素 (gather scatter elements) 来收集/分散数据,包括: - 地址 (Address): 本地数据缓冲区的地址,被用于数据的收集和分发。 - 大小 (Size): 读写到该地址的数据的大小。 - L_key: 注册到该缓冲区的 MR 的本地密钥。 :code:`struct sge` 被用于实现集散元素。 3.3.11 轮询 (Polling) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | 轮询 CQ 是否完成就是获取已发布的 WR (发送或接收) 的详细信息。 | 如果我们从 WR 获取到不良状态的 completion,那么其他的 completions 全部为不良状态(工作队列将被移 至错误状态)。 | 每个不含 completion (未被轮询)的 WR 都未完成。 | 只有在 WR 获取到 completion 后,发送/接收缓冲区才能被使用/重用/释放。 | 完成状态应该始终被检查。 | 当一个 CQE 被轮询时,它将从 CQ 中被删除。 | 轮询是通过 :code:`ibv_poll_cq` 操作完成的。