主要递归混合器区域获胜
四个主要形状的前向+反向分别快 24.6%、27.6%、37.3%、40.2%。加入完整循环块的公共层后,收益缩小但仍为 5.8%–7.6%。
NVIDIA H800 PCIe 80 GB · 训练后端实测 · 2026-08-31
我们先完善 RG-LRU 的 GPU 实现,再在相同测试条件下比较两种递归结构。SAMU 在已测主要训练形状中用时更短、实际分配显存更少,保存分块入口状态的临时数组也更小。
01 · 实测概览
四个主要形状的前向+反向分别快 24.6%、27.6%、37.3%、40.2%。加入完整循环块的公共层后,收益缩小但仍为 5.8%–7.6%。
主要递归混合器形状的峰值实际分配显存低 22.0%–23.5%;保存分块等价变换和入口状态的临时工作区约为 RG-LRU 的一半。
固定 D=1024 时,L=32768、65536、131072 的前向+反向用时分别缩短 37.0%、27.2%、25.7%;固定 L=32768 时,D=1024–2560 的用时缩短 37.3%–40.8%。
SAMU 每个位置只有共享相位和共享保持率两个动态控制标量;RG-LRU 每个位置仍需为全部 D 个通道分别生成写入门和保持门。
02 · 符号与测量范围
这些符号同时决定并行度、工作量和 GPU 路径。不同形状不能只按序列长度比较,也不能把递归混合器时间当成完整模型时间。
一次同时处理的独立序列条数。B=4 表示四条序列并行,通常能提供更多 GPU 并行工作;B=1 更容易暴露长序列前缀传播的成本。
每条序列包含的位置数。L=32768 表示每条序列有 32768 个递归时间步。页面中的 32K、65K、131K 分别是 32768、65536、131072。
用于公平匹配状态容量。RG-LRU 使用 \(D\) 个实数状态通道;SAMU 使用 \(M=D/2\) 个复数模态,每个复数模态由两个实数分量组成,因此双方都保留 \(D\) 个实数状态量。
K=32 表示一个 GPU 程序实例先在寄存器中顺序处理 32 个时间步,再把该分块压缩成一个仿射摘要。K 越大,分块数越少,但寄存器压力也越高。
包含控制量或门值准备、递归状态更新和可见输出。页面计时排除首次编译,但包含该路径正常执行所需的 CUDA 内核。
使用稠密输出梯度,计算输入梯度、初始状态梯度和全部参数梯度。它不是只传播状态梯度,也不是只测一个反向扫描内核。
把同一次完整前向和完整反向的 GPU 时间相加。它不包含 AdamW 参数更新;加入 AdamW 后的数字在单循环块优化器更新表中单独报告。
包括 RG-LRU 的门或 SAMU 的控制器、状态转移、递归写入、输出,以及相应反向。它不包括循环块外层的归一化、深度卷积、公共投影和多层感知机。
在递归混合器外加入公共归一化、输入投影、深度卷积、输出投影和门控多层感知机。当前只测一个 RecurrentBlock,不是多层语言模型。
每一行保留两轮、每轮五次,共十个计时样本。中位数是主值,方括号给出十个样本的最小值和最大值,不挑单次最快结果。
BF16 是 16 位脑浮点格式,用于输入和输出以降低带宽与存储开销;FP32 是 32 位单精度格式,用于递归状态、关键归约和控制器导数累加,以控制长链误差。
一种带解耦权重衰减的优化器。本页的单循环块 AdamW 更新包含该循环块的前向、反向和一次参数更新。
单位为毫秒。比较百分比按 \((t_{\mathrm{RG}}-t_{\mathrm{SAMU}})/t_{\mathrm{RG}}\) 计算;正数表示 SAMU 用时更少,表格同时保留双方绝对时间。
实际分配显存是活动张量真正占用的峰值;保留显存还包括 CUDA 缓存分配器暂存、可供后续复用的显存。两者必须分开报告。
临时工作区只统计每个分块的等价变换和入口状态等中间量;内核启动数是一次前向和反向触发的 CUDA 程序次数。启动更少通常有利,但不能单独决定总延迟。
每个位置只计算一次 \(E_t=e^{c_t}\)、\(C_t=\cos d_t\)、\(S_t=\sin d_t\),该位置的全部复数模态随后复用这三个值。不同位置仍使用各自的控制量,不同样本也保留各自的状态。
把相邻 64 个分块的等价变换放进一个执行组,按后文的 \(L_c\)、\(U_g\)、\(O_g\)、\(Q_c\) 公式求出每个分块的入口状态。被组合的是执行时的等价变换,不是控制量、模态或模型参数。
长序列含有很多分块,逐个传递会限制并行度。按 \(Q_c=L_c\circ O_g\) 分开计算组内组合与更早分组组合,只需与分块数成正比的组合次数,并允许不同执行组同时工作。
03 · H800 正式实测
输入和输出为 BF16,递归状态常驻 FP32;首次编译排除;第一轮先测 RG-LRU 再测 SAMU,第二轮交换先后顺序;每轮各取五个计时样本。图表显示十个样本的中位数与最小—最大区间。
正在读取递归混合器原始数据……
正在读取长度扩展数据……
正在读取宽度扩展数据……
包含归一化、两路输入投影、逐通道卷积、递归混合器、连接与输出、第二次归一化、门控多层感知机,以及输入和参数反向。
正在读取循环块数据……
包含循环块前向、输入与参数反向、融合 AdamW 参数更新;优化器状态在计时前完成初始化。
正在读取优化器数据……
04 · RG-LRU 在 GPU 上如何运行
RG-LRU 的方程和重置语义按固定版本的 RecurrentGemma 核对;H800 上运行的 Triton/CUDA 内核由本项目实现。
\(\ell^x\)、\(\ell^a\) 是两张分块对角投影产生的写入门和保持门原始值;\(\alpha\) 是每个状态通道的静态保持参数。分块 \(c=[s,e]\) 的等价变换是 \(S_c\)。若第 \(g\) 组覆盖分块 \(g_0\) 到 \(g_1\),则 \(L_c=S_{c-1}\circ\cdots\circ S_{g_0}\),\(U_g=S_{g_1}\circ\cdots\circ S_{g_0}\),\(O_g=U_{g-1}\circ\cdots\circ U_0\),最终 \(Q_c=L_c\circ O_g\) 给出分块 \(c\) 之前的完整变换;空组合取恒等变换。遇到打包序列的新段起点时,\(a_t\) 置零,写入归一化系数置一,因此旧段状态不会泄漏到新段。
两张规范分块对角投影为每个位置、每个状态通道产生写入门和保持门原始值,形状均为 \([B,L,D]\)。
Triton 内核内部完成 S 型门函数、软正值函数、指数保持系数、平方根写入归一化和重置处理,不额外物化多张逐点中间张量。
程序实例对分块 \(c=[s,e]\) 严格按 \(T_e\circ\cdots\circ T_s\) 组合,因此 \(S_c\) 与逐位置执行 16 次递推完全等价。
每 32 个分块为一组,分别计算上文定义的 \(L_c\)、\(U_g\)、\(O_g\) 和 \(Q_c\)。组合次数随分块数线性增长。
用正确入口状态重新执行分块中的 16 个位置;最后一个不完整分块、非零初始状态和分块内多次重置都保持规范语义。
递归输出继续经过双方相同的连接投影、残差、归一化和门控多层感知机,因此完整循环块表能反映公共计算对优势的稀释。
从输出梯度构造逆时间的实数仿射变换,并把重置位置编码为 \(a_t=0\)。
仍按 \((a_2,b_2)\circ(a_1,b_1)\) 组合,只把时间次序反转,从而并行得到每个反向分块的入口梯度。
重新计算门值、保持系数和平方根写入因子,得到输入、两组门原始值和状态的梯度。
每个批次和分块先产生 \(\alpha\) 的局部梯度,随后沿批次和分块维求和到 \([D]\)。
同时返回非零初始状态梯度,处理最后一个不完整分块,并对平方根导数使用与规范参考一致的数值截断。
| 适配 | 解决的问题 | 当前实现 |
|---|---|---|
| 门准备与递推融合 | 避免 S 型门函数、指数、平方根写入因子和递归写入之间产生多张中间张量及额外内核 | 门投影完成后,由同一可微 Triton 后端直接消费两个门原始值、输入和静态参数 \(\alpha\) |
| 把连续 16 步合成支持重置的等价变换 | 普通无重置扫描不能处理打包序列、分块内多次重置或非零初始状态 | 重置位置编码为零保持系数;支持任意重置、最后不完整分块、初始状态与初始状态梯度 |
| 按 \(Q_c=L_c\circ O_g\) 并行求入口状态 | 逐分块串行传播并行度低,多轮全局扫描又会增加组合次数和内核启动 | 每 32 个分块为一组,分别计算 \(L_c\)、\(U_g\)、\(O_g\) 和 \(Q_c\) |
| 每个程序处理的时间步数和通道数按形状选择 | 一次处理更多时间步会减少分块数,但增加寄存器压力;通道数太小或太大都会降低占用 | 最终主路径每个程序处理 16 步;短形状每次处理 128 个通道,中等及 \(D=1024\) 长形状为 256 个,\(D=2048\) 长形状为 128 个 |
| 反向重算与局部梯度归约 | 保存全部逐点保持系数和写入因子会增加训练显存 | 反向重放时重算门值和逐点项,分块先形成 \(\alpha\) 的局部梯度,再归约到 \([D]\) |
| 规范参考与开源实现分开使用 | RecurrentGemma 和 Fattori 实现支持的重置、初始状态与门结构不同 | RecurrentGemma 用于核对方程和重置语义;Fattori 只比较双方共同支持的零初始状态、无重置路径 |
状态和仿射系数都是实数,单步只需实数乘加;门计算与分块组合经过融合后,短序列和窄状态的固定开销较低。
两个动态门都随位置和 \(D\) 个通道变化,门准备、保存和反向天然具有 \([B,L,D]\) 规模。SAMU 只有两个随位置变化的共享控制量,这是长序列和宽状态时逐渐显现优势的根源。
正在读取公开实现复现数据……
测量条件:固定提交的 hawk-pytorch 不支持当前 RG-LRU 路径中的任意重置、重置位置写入归一化和非零初始状态,因此这里只比较零初始状态、无重置的完整前向与反向。
05 · SAMU 在 GPU 上如何运行
下面先完整写出正式 SAMU 的控制公式,再说明 GPU 如何执行这些公式。方向向量、幅度、\(1/\sqrt{M}\) 缩放和有界径向函数均未改变;两个幅度初始化为零,因此初始时精确退化到 RTU。
先把选择输入 \(x_t^{\mathrm{sel}}\) 末尾补一个常数 1,再分别与两个单位长度方向 \(\widehat w_\phi,\widehat w_r\) 做内积。双曲正切得到 \(p_t,r_t\),随后严格按上式得到共享相位改变量 \(d_t\) 和共享保持改变量 \(c_t\)。GPU 实现只合并这些内积和逐点函数,不改变控制器公式。
相邻两步严格使用 \(T_2\circ T_1\),也就是先执行 \(T_1\),再执行 \(T_2\)。乘法次序不能交换。对一个包含 \(K\) 个位置的分块 \(c=[s,e]\),程序按 \(T_e\circ\cdots\circ T_s\) 得到该分块的一个等价变换。
记第 \(c\) 个分块的等价变换为 \(S_c\),第 \(g\) 组从 \(g_0\) 到 \(g_1\)。先算组内早于分块 \(c\) 的组合 \(L_c=S_{c-1}\circ\cdots\circ S_{g_0}\) 和整组组合 \(U_g=S_{g_1}\circ\cdots\circ S_{g_0}\),再算更早各组的组合 \(O_g=U_{g-1}\circ\cdots\circ U_0\),最后用 \(Q_c=L_c\circ O_g\) 得到分块入口前的完整变换。以 64 个分块为一组只是并行计算这些公式。
先计算 \(\widetilde{x}_t^{\mathsf T}\widehat w_\phi\) 和 \(\widetilde{x}_t^{\mathsf T}\widehat w_r\),再按上式得到 \(p_t,r_t,d_t,c_t\)。投影内积和导数累加使用 FP32。
计算 \(E_t\)、\(C_t\)、\(S_t\)。同一位置的全部 \(M\) 个复数模态复用它们,不为每个模态重复计算指数、正弦和余弦。
把共享控制与静态频谱 \(\nu_m\)、\(\theta_m\) 合成 \(\lambda_{t,m}\)。不把两个形状为 \([B,L,M]\) 的实部、虚部转移张量写入显存。
每个程序实例严格按 \(T_e\circ\cdots\circ T_s\) 顺序处理 32 个位置,得到一个与逐步执行完全相同的复数仿射变换。
中长序列每 64 个分块为一组,分别计算上文定义的 \(L_c\)、\(O_g\) 和 \(Q_c\),从而并行得到各分块的正确入口状态。
从分块入口状态重新处理 32 个位置;写入归一化和可见输出融合在重放内,减少中间张量和额外读写。
状态梯度严格按上式通过共轭转移传播;每个程序实例从后向前把连续 32 步合成一个等价变换。
仍使用 \((\lambda_2,b_2)\circ(\lambda_1,b_1)\) 的组合规则和 \(Q_c=L_c\circ O_g\),但分块按逆时间排列,左右次序不能交换。
在程序实例内部重新生成 \(\lambda_{t,m}\),计算状态、写入、\(\nu_m\)、\(\theta_m\) 的梯度,不保存完整模态转移历史。
每个模态分片只写出两个局部和;第二次求和用 FP32 把 \([B,L,N_{\mathrm{tiles}},2]\) 变为 \([B,L,2]\),不产生 \([B,L,M]\) 控制梯度张量。
利用前向保存的 \(p_t,r_t\),按上式计算两个方向向量、两个有符号幅度和输入的梯度;方向归一化的导数也保持不变。
RG-LRU 的保持门随位置和通道变化;SAMU 的相位与保持控制每个位置各一个,再与静态模态频谱组合。
不写出 \([B,L,M]\) 的复数转移实部和虚部,减少显存往返;代价是重新执行分块内部时间步时需要再次计算。
相对 RG-LRU 每个程序处理 16 步,SAMU 每个程序处理 32 步,因此需要保存的分块等价变换和入口状态更少。
跨模态仍要做计算,但临时结果压缩为两个共享标量的分片归约,而不是完整 \([B,L,M]\) 张量。
SAMU 的整体反向没有变成 \(O(BL)\)。状态梯度、\(\nu\) 梯度、\(\theta\) 梯度和写入梯度仍然按模态计算;被压缩的是动态控制器梯度的中间表示。
控制器缓存约定
选中的实现会在前向保存每个位置的相位坐标 \(p\) 和径向链条所需的原始量 \(r\),连同递归输入交给融合控制器反向。方向归一化、方向梯度投影和幅度局部和都使用 FP32 累加。\(E_t,C_t,S_t\) 足以重放状态转移,但不足以单独恢复完整控制器导数。
精确分块闭式 · 可选路径
闭式使用最后一个不完整分块的真实 \(K_c\)。每个分块只保存两个统计量 \(G_c,D_c\),其整体形状为 \([B,C,2]\),即可在反向中重建原本形状为 \([B,C,M]\) 的复数乘法转移 \(P\)。但它与按 \(Q_c=L_c\circ O_g\) 并行求入口状态的实现组合后没有通过最终 BF16 输出误差门槛,因此默认路径仍直接保存 \(P\)。
实际效果
在长序列 \(D=2048\) 的剖析形状上,连续的共轭反向、输出融合和每程序 32 步的入口梯度并行计算,把反向 CUDA 事件合计从 6.265 毫秒降到 3.777 毫秒,下降 39.7%。其中求反向分块入口为 0.250 毫秒、逐步恢复导数为 0.602 毫秒、形成每块等价变换为 0.166 毫秒、共享控制梯度求和为 0.022 毫秒。
四个主要形状的前向+反向延迟降低 24.6%–40.2%,峰值实际分配显存降低 22.0%–23.5%。这包含控制器、状态递推、可见输出和全部相关梯度,不是单个扫描内核的结果。
归一化、公共投影、逐通道卷积和多层感知机不会因 SAMU 改变,因此递归混合器优势被稀释到 5.8%–7.6%;加入 AdamW 后进一步变为 3.8%–6.5%。
SAMU 每次前向+反向有 70–74 次 CUDA 内核启动,RG-LRU 为 50–51 次。复数重放和控制器小内核仍有固定成本,因此当前实现继续根据批量大小、序列长度和状态宽度选择路径。
| 形状区域 | SAMU | 经过充分优化的 RG-LRU |
|---|---|---|
| B≥4,L≤2048 | 每位置复用 \(e^{c_t},\cos d_t,\sin d_t\),每程序处理 32 步,分块入口依次传播 | 每程序处理 16 步;每 32 个分块为一组计算 \(Q_c\) |
| B=1,L=8192,D≥2048 | 每程序处理 32 步;每 64 个分块为一组计算 \(Q_c\) | 每程序处理 16 步;每 32 个分块为一组计算 \(Q_c\) |
| B=1,16384≤L<65536 | 每程序处理 32 步;每 64 个分块为一组计算 \(Q_c\) | 每程序处理 16 步;每 32 个分块为一组计算 \(Q_c\) |
| B=1,L≥65536 | 前向入口依次传播;反向每 64 个分块为一组计算 \(Q_c\);每程序处理 32 步 | 每程序处理 16 步;每 32 个分块为一组计算 \(Q_c\) |
| 含重置、打包序列或未支持形状 | 回退到精确规范路径 | 精确且支持重置的规范路径 |
表中的每 64 个分块为一组只说明怎样并行计算 \(Q_c=L_c\circ O_g\)。它没有把两个控制量分组,没有把模态分组,也没有改变 SAMU 的模型方程。
06 · 显存、参数和内核启动
实际分配显存、CUDA 缓存分配器保留显存、求分块入口状态的临时工作区和参数量分别报告。保留显存受分配器缓存影响,不能与实际分配显存混写。
| 形状 | SAMU | RG-LRU |
|---|---|---|
| B=4,L=2048,D=2048 | 6.000 MiB | 12.375 MiB |
| B=1,L=8192,D=2560 | 7.617 MiB | 15.469 MiB |
| B=1,L=32768,D=1024 | 12.188 MiB | 24.750 MiB |
| B=1,L=32768,D=2048 | 24.375 MiB | 49.500 MiB |
这里只统计每个分块的等价变换和入口状态数组,不含输出、模型激活或 CUDA 分配器保留量。
| 实数状态宽度 D | SAMU | RG-LRU |
|---|---|---|
| 1024 | 3,076 | 134,144 |
| 2048 | 6,148 | 530,432 |
| 2560 | 7,684 | 826,880 |
这里只比较被替换的递归混合器参数;完整循环块仍包含双方共有的大矩阵和多层感知机。
07 · 代码与原始证据
主结果使用 PyTorch 2.1.2 + CUDA 11.8;Fattori 复现使用 PyTorch 2.4.1 + CUDA 12.4。
正在读取 H800 环境记录……