Pull Request已成功合入, 合并人@liuchongming74
(感谢 xu-xianliang 的贡献)变更摘要
该 PR 为 Qwen3.5 风格的 Gated DeltaNet(线性注意力)层新增了上下文并行(Context Parallel)支持。与之前简单的序列 gather/slice 钩子方案不同,本次提供了两种 CP 执行策略:纯 Ulysses 模式(通过 differentiable all-to-all 在序列维度和头维度之间重分布 Q/K/V/B/A 张量)和 P2P 模式(每个 rank 持有一个序列分片,通过点对点通信传递循环状态,并支持 recompute 和 graph 两种反向传播实现)。同时将 CP 执行逻辑封装为 LinearAttentionContextParallel(一个 ParallelStyle 子类),并集成到 Qwen3.5 模型的并行化流程中。
主要改动
-
新增
LinearAttentionContextParallel类及两种 CP Wrapper:在linear_attention_context_parallel.py中实现LinearAttentionUlyssesCPWrapper(纯 Ulysses 模式,通过_differentiable_all_to_all_shard实现序列/头维度转换)和LinearAttentionP2PCPWrapper(序列分片模式,通过_GDNStateP2PFunction或_gdn_state_p2p_graph实现 P2P 状态传递),统一由LinearAttentionContextParallel.apply()根据mode参数选择并挂载到目标模块。 -
实现 P2P 循环状态传递的两种反向传播策略:
_GDNStateP2PFunction采用 recompute 方式——前向通过dist.send/dist.recv传递 hidden state,反向时重新计算局部 GDN 并通过自定义 autograd 计算梯度;_gdn_state_p2p_graph则将收/发操作拆分为独立的_RecvInitialStateP2PFunction和_SendFinalStateP2PFunction,利用 autograd 图直接进行端到端梯度传递。 -
重构 Qwen3.5 中线性注意力的 CP 应用方式:删除
parallelize.py中原有的_redistribute_first_tensor和基于register_forward_pre_hook/register_forward_hook的 gather/slice 实现,替换为调用LinearAttentionContextParallel,并新增linear_attention_cp_mode配置项支持从外部指定 CP 模式。 -
新增 TP+CP 兼容性检查与 GQA 展开逻辑修正:在
parallelize_qwen3_5中添加线性注意力层 TP+CP 不支持的明确报错;修改_needs_gqa_kv_expand_for_cp的判断逻辑,增加对local_q_heads可被cp_mesh.size()整除且能被local_kv_heads整除的条件检查。 -
模块导出更新:在
hyper_parallel/__init__.py和hyper_parallel/core/context_parallel/__init__.py中注册并导出LinearAttentionContextParallel。


代码审查
审查总结
共审查 4 个变更文件,发现 3 个问题(1 个为 P2/P3 重复报告,实际独立问题 2 个),按优先级分布如下:
- P3: 2 个(均为潜在隐患或 dtype 不一致,当前路径不可达或影响极小)
逐文件审查结果
| 文件 | 审查结论 |
|---|---|
hyper_parallel/__init__.py |
无问题(仅新增导入和 __all__ 导出) |
hyper_parallel/core/context_parallel/__init__.py |
无问题(仅新增导入和 __all__ 导出) |
hyper_parallel/core/context_parallel/linear_attention_context_parallel.py |
发现 2 个 P3 级问题(recon_concat_dim 负值潜在隐患 + dht dtype 不一致) |
hyper_parallel/models/qwen3_5/parallelize.py |
无问题(重构为使用 LinearAttentionContextParallel,_needs_gqa_kv_expand_for_cp 逻辑改进,新增 TP+CP 守卫正确) |
整体风险评估
低风险。新文件 linear_attention_context_parallel.py 整体设计合理,Ulysses CP 和 P2P CP 两条路径的 P2P 通信配对正确,autograd 图构建策略(send_token * 0 注入梯度、_RecvInitialStateP2PFunction / _SendFinalStateP2PFunction 分离前向/反向通信)是正确的。发现的 2 个问题均为潜在隐患或边缘情况,在正常使用场景下不可达或无明显影响。其余 3 个文件的变更为纯导入/导出或重构调用方式,无引入问题。
注:
_differentiable_all_to_all_shard中recon_concat_dim负值问题被报告了两次(第一次误判为 P2,经深入分析确认当前所有调用路径中该代码不可达,修正为 P3)。以 P3 级别报告为准。
| 类型 | 数量 |
|---|---|
| 🔴 阻塞 | 0 |
| 🟡 建议 | 2 |
💬 仅评论


The ci-pipeline-passed label is expired. Please retest again.


What type of PR is this?
/kind feature
What does this PR do / why do we need it:
Qwen3.5 采用 3:1 的 Linear Attention(Gated DeltaNet)与 Full Attention
混合层结构。原有 Qwen3.5 Context Parallel 仅能通过整段序列 gather/slice
处理 Linear Attention,无法利用其按 head 独立计算和递归状态较小的特点。
本 PR 新增
LinearAttentionContextParallel,并接入 Qwen3.5 dense 模型的CP 并行化流程,支持以下三种执行模式:
ulyssesShard(sequence) -> Shard(head)。RMSNorm、门控和输出投影。
p2p不复制完整序列。
H_out = M @ H_in + S。backward 中按相反方向传递 state gradient。
all_gather(S, M)状态摘要并打包为一次可微 all-gather。token output。
同时完成以下集成:
按 chunk 构造
(S, M)的完整 autograd graph,backward 按需重算 summary,降低 eager 小算子实现的训练峰值显存。
ContextParallel,Linear Attention 使用新增 CP executor。
ulysses,不改变未配置用户的执行行为。Which issue(s) this PR fixes:
Fixes #<填写对应 Issue/SR/AR 编号>
Test Plan and Test result:What scenarios were tested, and what were the
verification results(Function, performance, reliability, etc.):
1. UT 与分布式 ST
新增 UT:
(S, M)摘要 pack/unpack、仿射前缀合并及 autograd 梯度。(S, M)输出及K/V/g/beta 梯度一致性。
结果:
新增 2 卡 Ascend 910B BF16 分布式 ST:
batch=1, local sequence=1的Shard(sequence) -> Shard(head) -> Shard(sequence)round-trip及其 backward。
K/V heads=4/8,K/V head dim=16/16。
ulysses、p2p、all_gather。结果:
所有测试通过。BF16 parameter gradient 的最大单点误差来自不同分布式
计算顺序下的舍入;最差单个 parameter 的 relative-L2 保持在
4.1e-3以内,整体 grad norm 相对误差保持在2e-5以内。ST 不把当前 eager 小算子的单点舍入特征固化为公共接口契约。为兼容后续
融合后端采用不同 reduction order,max-abs 阈值设置为:
Parameter gradient 的原始 max-abs 受 loss、shape 和随机梯度量级影响,
只打印用于诊断,不作为通过条件。精度通过条件使用尺度化校验:
max_abs / reference_abs_max <= 1e-1,relative-L2 <= 5e-2;max_abs / reference_abs_max <= 1e-1,relative-L2 <= 1e-1;global grad-norm relative difference 阈值为
1e-2。宽松 max-abs 只作为output/input 的异常保险;逐参数 relative-max 和 relative-L2 避免大权重
梯度掩盖
A_log、dt_bias等较小参数的错误。为评估阈值稳定性,额外在相同 2 卡 NPU ST shape 上扫描了 100 组模型初始化、
输入和 grad-output 随机种子。三种 mode 共 300 组前反向全部通过,跨全部
样本观测到的最大值为:
100 组中,所有参数参考梯度的最小
max-abs为6.6406e-2,最小L2 norm 为
1.0297e-1,均来自dt_bias,未出现接近零的相对误差分母。原始 parameter-gradient max-abs 最高为
9.0625e-1。旧的param_grad_max_abs <= 3e-1会失败,说明该指标过度依赖固定随机样本,因此已从 assert 中移除。提交的 ST 仍使用固定 seed 保证 CI 可复现;
100-seed sweep 只作为阈值制定实验,不增加日常 CI 时间。
2. CP8 100 步整网精度
配置:
[linear_attention, linear_attention, linear_attention, full_attention]。K/V head dim=128/128。
1e-4,weight decay=0.01,共 100 步。结果:
100 步内未观察到误差随 optimizer step 持续放大,三种 CP 路径均与单卡
reference 保持一致的 loss 与 grad-norm 轨迹。
3. 性能验证
统一设置:
单层 Linear Attention,CP4/global sequence=32K:
summary checkpoint 的单独收益:
整段 summary checkpoint 分别为 P2P/AllGather 减少约 953/949 MiB 峰值
allocated,代价为约 2.8%/3.4% 的 forward+backward 时间。分段 summary
checkpoint 和 token-scan checkpoint 均在实测中增加了运行时间,且没有
进一步降低训练峰值,因此没有进入提交代码。
CP8 长序列扩展:
固定 local sequence=8K 时,从 CP4/global 32K 扩展到 CP8/global 64K,
P2P 和 AllGather 的 forward+backward 分别只增长约 0.5% 和 0.4%,
peak allocated 基本保持不变;当前 eager Ulysses 因完整序列上的 chunk
循环数翻倍而增长约 97.4%。
说明:以上结果用于比较本 PR 的 eager 数据路径,不代表未来融合 GDN
后端的最终性能。Ulysses 在 eager 后端上以完整序列、较少 local heads
执行大量小算子,kernel launch 和小 shape 效率较差,因此该结果不能直接
外推到融合算子实现。checkpoint 后 P2P/AllGather 与 Ulysses 的单层峰值
差距已缩小到约 5%~6%;后续专用 summary forward/backward 算子仍可继续
减少重算开销和临时 workspace。
Self-checklist:
Special notes for your reviewers:
ulysses为默认模式,未配置用户行为不变。NotImplementedError。通信接口不变的情况下替换本地算子。