OpenURMA Unified Bus

导言

一次 64 B 远端读取,数据在链路上只需要约 200 ns,端到端却可能超过 2 μs;当 1024 个本地发起上下文连接 1024 个远端端点时,按 Queue Pair(QP)组织的连接状态又会膨胀到约 537 MB。OpenURMA 认为这不是某个 RDMA Kernel 写得不够快,而是 QP over PCIe 这一抽象同时制造了状态乘积和外围设备往返。

OpenURMA 是 Unified Bus(UB)传输层与事务层的 clean-room 开放实现。它用 Jetty / TP Channel 拆开应用状态与可靠传输状态,把 UB Controller 放到片上总线,并为短同步操作提供绕过 Work Queue 的 Load/Store 路径。本文沿这条依赖链解释方案,同时把 500 ns / 2186 ns 放回论文的模拟条件:这组结果证明新抽象值得继续做成硅,不等于 Ascend 950 或任意商用 UB 产品已经交付同样数字。

先说判断

我的判断是,OpenURMA 最有价值的贡献不是“比 RoCE 快 4.37 倍”,而是把四个原本纠缠在 QP 里的责任拆开,并用一套开放实现检验它们能否重新组合:

  1. 应用身份由每个本地发起上下文的 Jetty 保存;
  2. 可靠传输由每个远端主机的 TP Channel 共享;
  3. 短同步访问用 CPU Load/Store 与 TP Bypass 直达远端内存;
  4. 顺序保证不再全部常开,而由应用按服务模式、执行顺序、Fence 和完成顺序选择。

这四项不是互不相关的功能清单,而是一条依赖链:

1
2
3
4
5
6
7
8
Jetty / TP Channel 拆分
→ 连接状态从 O(N·M) 变成 O(N+M)
→ 工作集有机会常驻片上 SRAM
→ Controller 才适合放到片上总线
→ CPU Load/Store 才能绕过 PCIe、WQE 与 CQE

Jetty 已有的本地计数器
→ 让按需排序只在真正阻塞时付费

其中,论文真正实现并评估的是一套 OpenClickNP / FPGA HLS 传输与事务层、双节点 SystemC 模型和 gem5 全系统脚手架。Controller 的片上放置与 CPU Load/Store 路径在模型中闭合,但没有在真实 CPU SoC、FPGA 板卡或 Ascend 950 上测量。这条边界贯穿全文。

QP 为何同时带来两笔成本

从应用看,RDMA READ 很像“读一个远端地址”;从设备看,它却是提交给 PCIe 外设的一项队列事务。RoCEv2 RC 的 QP 同时绑定本地应用、远端端点和可靠传输上下文,于是两类成本一起出现。

状态按连接对增长

设一台主机有 $N$ 个独立发起上下文,需要访问 $M$ 台远端主机。论文的 matched OpenRoCE 模型为每个 QP 计约 512 B 状态,于是:

$$
S_{\text{RoCE}}
\approx N \times M \times S_{\text{QP}}.
$$

这里的 $N$ 不是随意放大的“应用数”。多个线程共享同一个 Work Queue 会在队列上串行,因此论文把追求高性能时需要独立发起的上下文计入 $N$。如果一台远端主机还暴露多个独立端点,真实 QP 数可能继续乘上端点数。

当 $N=M=1024$ 时,模型得到约 104 万个 QP、536.9 MB 状态。论文进一步假设 NIC 约有 256 KB 上下文 SRAM;活跃 QP 超过缓存容量后,每项操作都可能增加一次到 Host DRAM 的状态回取。状态问题因此不只是容量问题,还会变成延迟台阶。这些数字来自论文 Table 4、Table 5 与 Figure 14 的模型,不应外推成所有商用 RNIC 都使用同样的 QP 布局和缓存大小。OpenURMA arXiv v1 §7

小操作仍要穿过外围协议

标准队列路径至少包含下面这些动作:

  1. CPU 构造 WQE,并通过 MMIO Doorbell 通知 NIC;
  2. NIC 通过 PCIe DMA 获取 WQE;
  3. 目标 NIC 访问目标 Host Memory;
  4. 响应数据和 CQE 通过 DMA 回到发起端内存;
  5. CPU 轮询并看到完成记录。

论文导言把发起端编程模型概括为四次 PCIe Traversal;其双端成本模型又显式加入目标 NIC 与目标 DRAM 之间的一次 DMA,因此 Figure 1 标出了五次。这不是两套互相矛盾的协议,而是单端计数与端到端计数的观察边界不同OpenURMA arXiv v1 §2.1、§5.2

![RoCE 与 OpenURMA 的状态、排序和提交路径对比](https://pic.shaojiemike.top/shaojiemike/2026/07/3af1fbc9457f3fc26fa3efc644ea33bc.png){ width=95% }
来自论文 Figure 1。上半部分对比 PCIe 外设 RNIC 与片上 UB Controller,下半部分给出状态、排序和提交路径三项设计承诺。

这张图最值得观察的不是蓝色路径比红色路径少了几根箭头,而是:状态拆分先让 Controller 的工作集变小,片上放置再让 Load/Store 快路径成立。只优化 Doorbell、批量提交或 QP Cache,能够削减其中一段成本,却没有改变这条依赖关系。

Jetty 与 TP Channel 怎样拆开状态

OpenURMA 不再让一个对象同时回答“谁在发请求”和“怎样可靠送到对端”两个问题。

对象 所在位置与粒度 保存内容 生命周期
Jetty 本地 NIC,每个独立应用发起上下文一份 完成队列句柄、访问 Token、类型与状态、排序计数 随应用上下文长期存在
TP Channel 本地 NIC,每个远端主机一份 PSN 窗口、SACK Bitmap、重传与拥塞状态 随主机间传输关系长期存在,可被多个 Jetty 复用
Destination Jetty ID 每个 Packet Header 指明远端应用端点 只随当前 Packet 移动
WQE / CQE Host Memory 与 Controller 异步 Work Request 及完成记录 仅 URMA Work Queue 路径使用
LD/ST Outstanding Entry Load/Store Engine 同步请求的 TASSN 与 Opcode 请求返回后释放;论文源码表大小为 64

发送时,Jetty 表先完成应用级准入与排序,再按目标主机找到共享 TP Channel,由后者分配序号、选择路径并管理可靠传输。接收时顺序反过来:TP Channel 先验证和重排 Packet,再根据 Header 中的 Destination Jetty ID 投递给目标应用。

状态规模因此变成:

$$
S_{\text{UB}}
\approx N \times S_{\text{Jetty}}

  • M \times S_{\text{TP}}
  • S_{\text{shared}}.
    $$

一个最小例子就能看出差别。2 个本地线程访问 3 台远端主机时,RoCE RC 的简化全连接模型需要 6 个 QP;UB 使用 2 个 Jetty 与 3 个 TP Channel。任何 Jetty 都能借用目标主机对应的 TP Channel,远端应用身份放进 Packet Header,而不是固化在连接对象里。

论文实现的 Jetty MVP 为 20 B,TP Channel 为 56 B;把尚未实现的完整 Jetty 状态机、异常模式与 Group Back-pointer 计入后,Jetty 预计为 48 B。在 $N=M=1024$ 时,MVP 状态为 110.6 KB,对比 OpenRoCE 的 536.9 MB,比例为 4855 倍;按完整 Jetty 估计则为 139.3 KB,比例降为 3855 倍。数量级结论来自结构拆分,4855 这个精确倍数则依赖论文的字段与对照模型。OpenURMA arXiv v1 Table 4、Table 5

拆分也有代价:每个 Packet 多携带目标 Jetty ID,收发两端各多一次索引;Jetty 与 TP Channel 成为生命周期不同的两个资源,Runtime 和故障恢复必须分别管理。它消除的是跨主机的 $N\times M$ 状态乘积,不会让多个线程共享同一 Jetty 时的队列串行凭空消失。

为什么同时保留两条数据路径

把 Controller 放到片上总线,并不意味着所有通信都应该变成 CPU 指令。OpenURMA 保留了两条互补路径。

URMA Work Queue 路径

异步 READ、WRITE、SEND、Atomic 和较大 Payload 仍由 Work Request 驱动。请求依次经过 Jetty Scheduler、Ordering、BTAH、TP Channel、Congestion Window、Retransmission、RTP Header 和 Ethernet Encapsulation。它拥有传输层可靠性、队列深度和异步并发能力,适合吞吐受限或需要多个 In-flight Operation 的工作负载。

即使这条路径仍使用 WQE / CQE,片上 UB Controller 也不再支付外围 RNIC 的 PCIe Doorbell、WQE DMA 和 CQE DMA 固定成本。论文同时比较 UB URMAUB LD/ST,正是为了区分“Controller 放置位置”和“是否绕过队列”各自贡献了什么。

Load/Store 与 TP Bypass

小型 Load、Store 和同路径 Atomic 可以由 CPU 指令进入 Controller,构造事务 Header,并标记 TP_BYPASS。它不分配传输层 PSN,不占用 Retransmission Buffer,也不生成独立 CQE;Load 的数据沿指令依赖返回 CPU Register,超时后由 CPU 重新发起。

论文提交前的源码没有正式 Tag。本文把提交前约 16 分钟的 0c60151 作为接近 arXiv v1 的源码锚点,这是根据提交时间作出的版本推断,不是作者声明的 Release。其 Load/Store Topology 把发起端路径写得很直接:

1
2
3
4
5
6
7
host_in -> doorbell -> ldst
ldst[1] -> btah_b -> nth_b -> ethenc -> tor_out

tor_in -> ethdec -> nth_p
nth_p[1] -> btah_p
btah_p[2] -> [2]ldst
ldst[2] -> host_out

这段摘录只展示发起端请求与响应相关路径;目标端的 Memory Region 检查、Read / Write / Atomic Dispatch 和本地内存访问位于同一 Topology 后续分支,没有被省略为“无检查直通”。真正应注意的是,快路径没有出现 Jetty_Sched → TPChannel_TX → Cong_Window → Retrans_Buffer → RTPH_Build 链。examples/openurma_loadstore/topology.clnp L53-L75

代码仍复用了名为 doorbell 的 Host-Ingress Element 来校验模拟 Flit,因此 Topology 文本里能看到这个名字;论文的延迟模型把该输入解释为片上总线上的 Load/Store Aperture 请求,没有重新计入 PCIe MMIO Doorbell 与 WQE DMA。这里必须区分 Element 名称和物理提交路径。

快路径不是通用替代

TP Bypass 只接受语义能够承受传输层绕过的短同步操作。Bulk Transfer、长异步流水和需要 NIC 可靠重传的流量仍应走 URMA Work Queue。CPU 重试还要求系统明确 Timeout、重复执行与 Atomic 幂等边界,不能只看到“少五级 Pipeline”就把任意 WQE 改写成 Load/Store。

按需排序怎样工作

RoCE RC 在每个 QP 内提供严格有序语义。它简单,但某项早期操作停住时,后续无关操作也可能被 Head-of-Line Blocking。UB 把顺序拆成四个可选择的轴:

回答的问题 典型选择
Service Mode Packet 在链路与目标侧允许怎样重排 ROI、ROT、ROL、UNO
Execution Order 当前事务是否必须等待更早事务 NO、RO、SO
Fence 应用是否显式建立前后 Barrier 开 / 关
Completion Order Completion 按到达还是提交顺序退休 Out-of-order / In-order

OpenURMA 将四个轴实现为四个 Pipeline Gate。请求没有选择 Gate 时,所有服务模式的冷路径都在 24 Cycle 发出第一帧;真正请求 Fence 或 Strong Order 时,论文测得额外等待低于 50 Cycle。由于 Gate 按 Jetty 的本地计数器索引,一个 Initiator 被卡住时,其他 Initiator 的 Unordered Request 仍能绕过,不需要共享一个全局严格顺序。OpenURMA arXiv v1 §9

“按需”不等于“没有一致性责任”。相反,应用或 Collective Runtime 必须知道哪些操作可交换、哪里需要 Fence、Completion 被观察时远端数据是否已经可见。对于交换律成立且最终在 Barrier 汇合的梯度聚合,放松逐操作顺序可能合理;对于分布式锁、引用计数或生产者—消费者 Flag,错误选择会直接变成正确性问题。

开放实现验证了什么

OpenURMA 的实验设计比单一模拟器更有说服力,因为同一套 .clnp Element Source 被放到三个层级,并为每层准备 matched OpenRoCE:

  1. 软件 Emulator验证 Wire Format、Opcode、Ordering、Atomic 与数据完整性;
  2. SystemC 双节点模型测量 Pipeline Cycle、双端 Wire / DRAM 成本、延迟、吞吐、丢包与拥塞;
  3. gem5 全系统脚手架启动 Linux 4.14、模拟 Driver 和真实 ARM Binary,测量 MMIO、Syscall、Scheduler 与 CQE Delivery 的软件开销;
  4. 同一 Element Source 再经 Vitis HLS 与 Vivado,在 Alveo U50 目标上做 Out-of-context 综合和 P&R。

这套结构让两个问题得以分开:RTL 能不能综合并收敛时序,以及新协议在相同成本模型下是否改变关键路径。它不能回答的,是带真实 PHY、MAC、Host Bus、Driver、Firmware、功耗和拥塞环境的物理芯片会跑出什么绝对数字。

论文 v1 报告 38 个 Work-Queue-Driven Element 全部达到 322 MHz;OpenURMA 占 122,710 LUT、194,266 FF 和 328 BRAM18,约为 U50 LUT 预算的 14.1%。matched OpenRoCE 使用 46,636 LUT,因此 OpenURMA 并不比基线“更省硬件”:它分别多用 2.63 倍 LUT、2.11 倍 FF 和 4.90 倍 BRAM18,换取更丰富的排序、选择重传、多路径与事务层能力。OpenURMA arXiv v1 Table 2、Table 3

实验数字应该怎样读

论文 Figure 19 选择了三种小操作:64 B Pointer Chase、64 B Bulk Write 和 8 B FAA Distributed Barrier。共同设置是单向 Link Delay 100 ns、Concurrency 1,并显式计入目标 NIC 到 DRAM 的访问。

![OpenURMA 与 OpenRoCE 的三类小操作延迟](https://pic.shaojiemike.top/shaojiemike/2026/07/095b691f8d42c9f7788b7747e06456a8.png){ width=95% }
来自论文 Figure 19。`500 ns / 2186 ns` 只对应 64 B、100 ns 单向链路、Concurrency 1 的冷 Pointer Chase;另外两栏显示 Write 与 FAA 的路径差异。
主张 论文设置 v1 结果 能支持的结论
连接状态有界 $N=M=1024$,MVP 字段模型 110.6 KB vs 536.9 MB,4855 倍 Jetty / TP Channel 拆分消除了状态乘积
短同步读取更低延迟 64 B、Link 100 ns、Concurrency 1 UB LD/ST 500 ns;UB URMA 757 ns;RoCE DMA 2186 ns 片上放置与 TP Bypass 分别减少固定提交成本
稳态 WR 吞吐更高 256 WR Burst,matched Pipeline 150.36 vs 53.62 WR/μs,2.80 倍 当前两套模型的依赖与 Initiation Interval 不同
按需排序不增加无阻塞级数 12 种 Service / Execution 组合 第一帧均为 24 Cycle;按需 Gate 低于 50 Cycle 未请求的 Gate 可旁路,阻塞按 Initiator 隔离
资源可综合 U50、322 MHz、Out-of-context P&R 14.1% LUT,全部 Element 正 WNS 传输与事务层在该 FPGA 目标上具备实现可行性

其中最容易被误读的是 4.37 倍。它比较的是同一模型中“CPU 获取 64 B 远端数据”的两种等价语义:UB 用 §8.3 LOAD,RoCE 用 RC READ。它没有比较经过多年产品优化的 ConnectX-7 与量产 Ascend 950,也没有证明所有 URMA Verb 都能获得 4.37 倍。

论文自己给出了三个收敛区间:

  • 16–64 KB Bulk Transfer 进入带宽受限区后,各方案相差约 5%;
  • RoCE Blue Flame 的 WRITE / SEND 能省去 WQE DMA,差距可缩到 2 倍以内;
  • 小于约 23 个活跃端点时,论文模型中的 QP Cache 尚未溢出,UB 只剩每操作固定路径优势。

YCSB-A 的 9.2 倍吞吐同样需要谨慎。论文在 10K 个 64 B Value、Zipfian Key、Concurrency 256 下得到 UB LD/ST 4.6 Mops/s、RoCE DMA 0.50 Mops/s,并把超过 4.37 倍的部分归因于热点 Key 的 CPU Cache 命中;作者估计更现实的 Set-associative Cache 会把倍数降到约 6 倍。与此同时,gem5 AtomicCPU 并不能定量区分 WB / WT / UC Cache Policy,这部分真实 Cache Hierarchy 收益仍需要 Timing CPU 或物理系统验证。OpenURMA arXiv v1 §8.2、§8.3、§10.2

论文与滚动源码不要混读

调研时,OpenURMA 没有与 arXiv v1 对应的正式 Git Tag。论文于 2026 年 5 月 27 日提交;当前仓库 main 已继续增加 UMDK 集成、应用覆盖和 Pipeline Data Path,数字也发生了变化。

口径 源码锚点 Remote Fetch Pipeline 描述
arXiv v1 提交前的 0c60151 作为近似锚点 500 ns vs 2186 ns,4.37 倍 论文报告 38 个 Work-Queue-Driven Element
调研时 main 0ae5dce,2026-06-12 README 为 500 ns vs 2236 ns,4.47 倍 README 清单为 41 个 UB Element

因此,本文所有实验结论固定到 arXiv v1;当前仓库只用于说明后续工程状态。若要复现,应该先选择论文口径还是滚动 main,记录 Commit、OpenClickNP 版本和 Result CSV,再比较输出。直接在当前 main 运行 ./reproduce.sh smoke,不应期待得到 v1 的 2186 ns。OpenURMA 当前 README

官方 openEuler UMDK 提供 URMA 的单边、双边和 Atomic 软件接口。OpenURMA 当前仓库声称可在 gem5 中运行未修改的 UMDK Stack,这是比早期自定义 libopenurma Harness 更接近真实软件面的进展;它仍然是模拟平台上的集成,不应写成物理 UB NIC 已经开放。

适用场景与工程缺口

这套方案最值得投入的场景具有几个共同特征:

  • 端点扇出很大,QP Working Set 已经成为 NIC SRAM 或 Host Memory 压力;
  • 8–64 B 短操作很多,Doorbell、DMA 和 Completion 的固定成本高于 Payload 传输;
  • Pointer Chase、KV Hot Row 或细粒度 Atomic 有局部性,同步 Load/Store 能进入 CPU Cache Hierarchy;
  • 平台能共同设计 CPU / NPU、片上总线与 Controller,而不是只能把标准 RNIC 插在 PCIe 后面;
  • 应用能准确表达 Ordering,愿意用 Fence 和 Completion Contract 换取 Relaxed Path。

以下场景更适合继续使用成熟 RDMA,或者至少保留双路径:

  • 主要负载是 16 KB 以上的大块顺序传输,瓶颈已转向链路带宽;
  • 需要跨厂商互通、成熟 Driver、Telemetry、Tenant Isolation 和现场故障工具;
  • 现有系统已经充分使用 Blue Flame、Inline WQE、Batch、Unsignaled Completion 与 GPUDirect;
  • 无法把 Controller 集成到片上总线,只能在 PCIe FPGA / SmartNIC 上模拟协议功能。

尚未闭合的产品化问题

arXiv v1 没有在物理 FPGA 或 ASIC 上运行,没有面向真实板卡的 Kernel Driver,也没有测量完整 Shell、PHY、功耗及真实 Loss / Contention 下的首包延迟。Vivado 数据是逐 Element 的 Out-of-context P&R;Jetty Fault Drain、Exception Mode、Async Event、Public Jetty、Per-Jetty Token、完整多 Flit 选择重传、虚拟化和完整 Tenant Isolation 仍未闭合。论文只声称实现 UB 的 Transport / Transaction Layer,不包含 UB Physical / Link Layer,也不包含 Ascend 950 的 Hardware Collective Engine。

如果把 OpenURMA 当作工程起点,我会优先补齐六项验证,而不是先追更漂亮的平均延迟:

  1. 固定 Spec 与源码版本:建立 UB 2.0.1 字段、OpenURMA Commit 和 UMDK ABI 的一一映射;
  2. 重做状态账本:用目标并发、Endpoint、MR、TPG、Retransmit Window 和 Tenant 数计算真实 SRAM 上界;
  3. 定义双路径阈值:明确哪些 Opcode、Payload、并发和可靠性进入 LD/ST,哪些退回 URMA WR;
  4. 证明 Timeout 与幂等:覆盖 Load Retry、Store 重放、Atomic 重复执行和故障恢复;
  5. 补齐物理路径:在真实 Host Bus、Driver、PHY 和 DRAM 上测 Mean、Tail、Power 与 Congestion;
  6. 保留 matched baseline:同硬件、同拓扑、同 Payload、同 Completion Mode 对比生产级 RoCE,而不是跨论文抄倍数。

结论

回到开头那次 64 B 读取,OpenURMA 的答案不是把某个 DMA Kernel 再压缩几十纳秒,而是追问:既然应用想表达一次远端 Load,为什么必须先把它包装成 PCIe 外设的队列事务?

Jetty / TP Channel 拆分让状态从乘法变成加法;有界状态让 Controller 有机会留在片上;片上 Controller 让 Load/Store 与 TP Bypass 成为真正不同的短路径;按需排序再避免为不需要的顺序持续付费。这条依赖链,是论文已经用开放实现和 matched model 支持的核心结论。

尚未被证明的是量产性能:4.37 倍来自 arXiv v1 的特定模型,OpenRoCE 不是生产 ConnectX,OpenURMA 也不是物理 Ascend 950。更稳妥的定位是:它已经把 Unified Bus 从一份难以测量的规范推进为可检查、可综合、可复现实验的研究载体;下一步应该用真实硅、完整 Driver 与生产 Workload 检验这条架构链,而不是把模拟数字提前写成产品承诺。

参考资料

  1. Bojie Li, OpenURMA: A Clean-Room Open Implementation of the Unified Bus Protocol, arXiv v1, 2026-05-27;HTML 全文
  2. OpenURMA, 接近 arXiv v1 的源码锚点 0c60151。该对应关系由提交时间推断,仓库未提供正式论文 Tag。
  3. OpenURMA, 调研时 main0ae5dce,用于核对论文之后的实现与复现口径变化。
  4. openEuler, Unified Memory Development Kit,用于核对 URMA 软件接口与公开组件边界。
  5. Bojie Li, OpenClickNP,OpenURMA 的 Element Compiler、Software Emulator、SystemC 与 FPGA HLS 基础工具链。
Author

Shaojie Tan

Posted on

2026-08-31

Updated on

2026-09-01

Licensed under